]> code.ossystems Code Review - openembedded-core.git/blob
f3e8159ebd43c073aceb66bdf54c08307b682a34
[openembedded-core.git] /
1 From b5dc72f2a0bc509a241e03eea51e739204315f93 Mon Sep 17 00:00:00 2001
2 From: Zheng Ba <zheng.ba@intel.com>
3 Date: Thu, 1 Apr 2010 16:24:20 +0800
4 Subject: [PATCH 2/3] Moorestown Camera Imaging driver Beta 10.0
5
6 Patch-mainline: 2.6.35?
7
8 Changes from Beta 9.0:
9 1. Fixed hsd sighting
10         3469638 3469639 3469710 3469822 (high)
11         3469697 (medium)
12
13 Changes from Beta 8.0:
14 1. Fixed hsd sighting
15         3469056 3469058 (critical)
16         3469705 3469696 3469709 3469510 (medium)
17
18 Changes from Beta 7.0:
19 1. Fixed hsd sighting 3469681,3469682,3469683 (high)
20
21 Changes from Beta 6.0:
22 1. Fixed hsd sighting 3469668 (high)
23 2. Fixed ov5630 v4l2 view-finding dark issue
24 3. Enabled support for popular v4l2 applications (cheese, skype, ffmpeg)
25
26 Changes from Beta 5.1:
27 1. Fixed CRITICAL sighting 3469558 -- ciapp fails to launch with segment fault
28 2. Fixed HIGH sighting 3479513 -- ov5630 AWB unstable
29 3. Improved KMOT sensor 720p fps from 30 to 40
30
31 Changes from Beta 5.0:
32 Fixed a critical issue of camera driver not loading -- hsd 3469557
33
34 Main changes from Beta 4.0:
35 Fixed 4 HSD sightings: 3469392,3469099,3469470,3469500
36
37 Main changes from Beta 3.0:
38 Fixed 7 HSD sightings: 3469264,3469112,3469395,3469103,3469105,3469471,3469484
39
40 Main changes from Beta 2.0:
41 Fixed 6 HSD sightings: 3469047,3469315,3469317,3469101,3468409,3469391
42
43 Main changes from Beta 1.1:
44 1. Added interrupt mode for jpeg capture and KMOT viewfinding
45 2. Fixed HSD sighting 3469228 and 3469147
46
47 Main changes from Alpha2:
48 Enabled MIPI interface in ISP driver and KMOT sensor s5k4e1.
49 Enabled FIFO in ISP driver, which doubled the fps in view-finding mode.
50 Enabled Subdev Framework in CI kernel driver.
51 Enabled AF Continuous Mode.
52 Enabled AE scene evaluation.
53
54 Enabled the camera drivers in kernel:
55 Device Drivers --> Multimedia support --> Video For Linux
56 Device Drivers --> Mulitmedia support --> Video capture adapters -->
57 --> Moorestown Langwell Camera Imaging Subsystem support.
58
59 Kernel configs:
60 1. camera driver depends on GPIO library and I2C driver.
61 CONFIG_GENERIC_GPIO=y
62 CONFIG_I2C=y
63 CONFIG_GPIOLIB=y
64 2. camera driver depends on videobuf-core and videobuf-dma-contig.
65 VIDEOBUF_GEN=y
66 VIDEOBUF_DMA_CONTIG=y
67 3. enable multimedia support and video capture.
68 CONFIG_MEDIA_SUPPORT=y
69 CONFIG_VIDEO_DEV=y
70 CONFIG_VIDEO_V4L2_COMMON=y
71 CONFIG_VIDEO_MEDIA=y
72 CONFIG_VIDEO_V4L2=y
73 4. camera drivers incluing ISP, 5630, 5630-motor, s5k4e1, s5k4e1-motor, 2650,
74 9665, flash.
75 CONFIG_VIDEO_MRSTCI=y
76 CONFIG_VIDEO_MRST_ISP=y
77 CONFIG_VIDEO_MRST_OV5630=y
78 CONFIG_VIDEO_MRST_OV5630_MOTOR=y
79 CONFIG_VIDEO_MRST_S5K4E1=y
80 CONFIG_VIDEO_MRST_S5K4E1_MOTOR=y
81 CONFIG_VIDEO_MRST_FLASH=y
82 CONFIG_VIDEO_MRST_OV2650=y
83 CONFIG_VIDEO_MRST_OV9665=y
84
85 Signed-off-by: Zheng Ba <zheng.ba@intel.com>
86 ---
87  drivers/media/video/mrstci/Kconfig                 |   26 +
88  drivers/media/video/mrstci/Makefile                |    8 +
89  drivers/media/video/mrstci/mrstisp/Kconfig         |   10 +
90  drivers/media/video/mrstci/mrstisp/Makefile        |    7 +
91  .../video/mrstci/mrstisp/__mrstisp_private_ioctl.c |  324 +++
92  drivers/media/video/mrstci/mrstisp/mrstisp_dp.c    | 1301 +++++++++
93  drivers/media/video/mrstci/mrstisp/mrstisp_hw.c    | 1622 +++++++++++
94  drivers/media/video/mrstci/mrstisp/mrstisp_isp.c   | 1993 +++++++++++++
95  drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c   |  569 ++++
96  drivers/media/video/mrstci/mrstisp/mrstisp_main.c  | 2977 ++++++++++++++++++++
97  drivers/media/video/mrstci/mrstisp/mrstisp_mif.c   |  763 +++++
98  11 files changed, 9600 insertions(+), 0 deletions(-)
99  create mode 100644 drivers/media/video/mrstci/Kconfig
100  create mode 100644 drivers/media/video/mrstci/Makefile
101  create mode 100644 drivers/media/video/mrstci/mrstisp/Kconfig
102  create mode 100644 drivers/media/video/mrstci/mrstisp/Makefile
103  create mode 100644 drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c
104  create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_dp.c
105  create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_hw.c
106  create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_isp.c
107  create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c
108  create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_main.c
109  create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_mif.c
110
111 diff --git a/drivers/media/video/mrstci/Kconfig b/drivers/media/video/mrstci/Kconfig
112 new file mode 100644
113 index 0000000..9ac7065
114 --- /dev/null
115 +++ b/drivers/media/video/mrstci/Kconfig
116 @@ -0,0 +1,26 @@
117 +menuconfig VIDEO_MRSTCI
118 +        bool "Moorestown Langwell Camera Imaging Subsystem support"
119 +        depends on VIDEO_V4L2
120 +        default y
121 +
122 +        ---help---
123 +       Say Y here to enable selecting the Intel Moorestown Langwell Camera Imaging Subsystem for webcams.
124 +
125 +if VIDEO_MRSTCI && VIDEO_V4L2
126 +
127 +source "drivers/media/video/mrstci/mrstisp/Kconfig"
128 +
129 +source "drivers/media/video/mrstci/mrstov5630/Kconfig"
130 +source "drivers/media/video/mrstci/mrstov5630_motor/Kconfig"
131 +
132 +source "drivers/media/video/mrstci/mrsts5k4e1/Kconfig"
133 +source "drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig"
134 +
135 +source "drivers/media/video/mrstci/mrstflash/Kconfig"
136 +
137 +source "drivers/media/video/mrstci/mrstov2650/Kconfig"
138 +
139 +source "drivers/media/video/mrstci/mrstov9665/Kconfig"
140 +
141 +endif # VIDEO_MRSTCI
142 +
143 diff --git a/drivers/media/video/mrstci/Makefile b/drivers/media/video/mrstci/Makefile
144 new file mode 100644
145 index 0000000..9d3449e
146 --- /dev/null
147 +++ b/drivers/media/video/mrstci/Makefile
148 @@ -0,0 +1,8 @@
149 +obj-$(CONFIG_VIDEO_MRST_OV2650) += mrstov2650/
150 +obj-$(CONFIG_VIDEO_MRST_OV9665) += mrstov9665/
151 +obj-$(CONFIG_VIDEO_MRST_OV5630) += mrstov5630/
152 +obj-$(CONFIG_VIDEO_MRST_OV5630_MOTOR) += mrstov5630_motor/
153 +obj-$(CONFIG_VIDEO_MRST_S5K4E1) += mrsts5k4e1/
154 +obj-$(CONFIG_VIDEO_MRST_S5K4E1_MOTOR) += mrsts5k4e1_motor/
155 +obj-$(CONFIG_VIDEO_MRST_FLASH) += mrstflash/
156 +obj-$(CONFIG_VIDEO_MRST_ISP) += mrstisp/
157 diff --git a/drivers/media/video/mrstci/mrstisp/Kconfig b/drivers/media/video/mrstci/mrstisp/Kconfig
158 new file mode 100644
159 index 0000000..8e58a87
160 --- /dev/null
161 +++ b/drivers/media/video/mrstci/mrstisp/Kconfig
162 @@ -0,0 +1,10 @@
163 +config VIDEO_MRST_ISP
164 +       tristate "Moorstown Marvin - ISP Driver"
165 +       depends on VIDEO_V4L2
166 +       select VIDEOBUF_DMA_CONTIG
167 +       default y
168 +       ---help---
169 +         Say Y here if you want support for cameras based on the Intel Moorestown platform.
170 +
171 +         To compile this driver as a module, choose M here: the
172 +         module will be called mrstisp.ko.
173 diff --git a/drivers/media/video/mrstci/mrstisp/Makefile b/drivers/media/video/mrstci/mrstisp/Makefile
174 new file mode 100644
175 index 0000000..30f4e62
176 --- /dev/null
177 +++ b/drivers/media/video/mrstci/mrstisp/Makefile
178 @@ -0,0 +1,7 @@
179 +mrstisp-objs   := mrstisp_main.o mrstisp_hw.o mrstisp_isp.o    \
180 +                mrstisp_dp.o mrstisp_mif.o mrstisp_jpe.o       \
181 +               __mrstisp_private_ioctl.o
182 +
183 +obj-$(CONFIG_VIDEO_MRST_ISP)    += mrstisp.o
184 +
185 +EXTRA_CFLAGS   +=      -I$(src)/../include -I$(src)/include
186 diff --git a/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c b/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c
187 new file mode 100644
188 index 0000000..85cc482
189 --- /dev/null
190 +++ b/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c
191 @@ -0,0 +1,324 @@
192 +/*
193 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
194 + *
195 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
196 + *
197 + * This program is free software; you can redistribute it and/or
198 + * modify it under the terms of the GNU General Public License version
199 + * 2 as published by the Free Software Foundation.
200 + *
201 + * This program is distributed in the hope that it will be useful,
202 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
203 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
204 + * GNU General Public License for more details.
205 + *
206 + * You should have received a copy of the GNU General Public License
207 + * along with this program; if not, write to the Free Software
208 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
209 + * 02110-1301, USA.
210 + *
211 + *
212 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
213 + */
214 +
215 +#include "mrstisp_stdinc.h"
216 +
217 +/*
218 +static u32 copy_sensor_config_from_user(struct ci_sensor_config *des,
219 +                                       struct ci_sensor_config *src)
220 +{
221 +       u32 ret = 0;
222 +       ret = copy_from_user((void *)des, (const void *)src,
223 +               sizeof(struct ci_sensor_config));
224 +       if (ret)
225 +               return -EFAULT;
226 +       return ret;
227 +}
228 +
229 +static u32 copy_sensor_caps_from_user(struct ci_sensor_caps *des,
230 +                                     struct ci_sensor_caps *src)
231 +{
232 +       u32 ret = 0;
233 +       ret = copy_from_user((void *)des, (const void *)src,
234 +               sizeof(struct ci_sensor_caps));
235 +       if (ret)
236 +               return -EFAULT;
237 +       return ret;
238 +}
239 +
240 +static u32 copy_isp_config_from_user(struct ci_isp_config *des,
241 +                                    struct ci_isp_config *src)
242 +{
243 +       int ret = 0;
244 +       ret = copy_from_user((void *)des, (const void *)src,
245 +               sizeof(struct ci_isp_config));
246 +       if (ret) {
247 +               eprintk("returning %d", ret);
248 +               return ret;
249 +       }
250 +       return 0;
251 +}
252 +*/
253 +
254 +static void print_bls_cfg(struct ci_isp_config *isp_cfg)
255 +{
256 +       struct ci_isp_bls_config *bls_cfg = &isp_cfg->bls_cfg;
257 +
258 +       dprintk(4, "print_bls_cfg:");
259 +       dprintk(4, "enable_automatic:%d", (bls_cfg->enable_automatic ? 1 : 0));
260 +       dprintk(4, "disable_h:%d", (bls_cfg->disable_h ? 1 : 0));
261 +       dprintk(4, "disable_v:%d", (bls_cfg->disable_v ? 1 : 0));
262 +       dprintk(4, "enable_window1:%d",
263 +               (bls_cfg->isp_bls_window1.enable_window ? 1 : 0));
264 +       dprintk(4, "start_h:%d", (int)bls_cfg->isp_bls_window1.start_h);
265 +       dprintk(4, "stop_h:%d", (int)bls_cfg->isp_bls_window1.stop_h);
266 +       dprintk(4, "start_v:%d", (int)bls_cfg->isp_bls_window1.start_v);
267 +       dprintk(4, "stop_v:%d", (int)bls_cfg->isp_bls_window1.stop_v);
268 +       dprintk(4, "enable_window2: %d",
269 +               (bls_cfg->isp_bls_window2.enable_window ? 1 : 0));
270 +       dprintk(4, "start_h%d", (int)bls_cfg->isp_bls_window2.start_h);
271 +       dprintk(4, "stop_h%d", (int)bls_cfg->isp_bls_window2.stop_h);
272 +       dprintk(4, "start_v%d", (int)bls_cfg->isp_bls_window2.start_v);
273 +       dprintk(4, "stop_v%d", (int)bls_cfg->isp_bls_window2.stop_v);
274 +       dprintk(4, "bls_samples%d", (int)bls_cfg->bls_samples);
275 +       dprintk(4, "fixed_a0x%02x", (int)bls_cfg->bls_subtraction.fixed_a);
276 +       dprintk(4, "fixed_b0x%02x", (int)bls_cfg->bls_subtraction.fixed_b);
277 +       dprintk(4, "fixed_c0x%02x", (int)bls_cfg->bls_subtraction.fixed_c);
278 +       dprintk(4, "fixed_d0x%02x", (int)bls_cfg->bls_subtraction.fixed_d);
279 +       dprintk(4, "\n");
280 +}
281 +
282 +static int mrst_isp_set_cfg(struct file *file, void *priv,
283 +                           struct ci_pl_system_config *arg)
284 +{
285 +       struct video_device *dev = video_devdata(file);
286 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
287 +
288 +       WARN_ON(priv != file->private_data);
289 +
290 +       DBG_entering;
291 +
292 +       if (arg == NULL) {
293 +               eprintk("NULL pointer of arg");
294 +               return 0;
295 +       }
296 +       mutex_lock(&isp->mutex);
297 +
298 +       /*
299 +       if (arg->isi_config != NULL) {
300 +               dprintk(2, "sync isi cfg");
301 +               copy_sensor_config_from_user(isp->sys_conf.isi_config,
302 +                                            arg->isi_config);
303 +       } else {
304 +               eprintk("NULL arg->isi_config");
305 +               ret = CI_STATUS_NULL_POINTER;
306 +               goto exit_unlock;
307 +       }
308 +
309 +       if (arg->isi_caps != NULL) {
310 +               dprintk(2, "sync isi caps");
311 +               copy_sensor_caps_from_user(isp->sys_conf.isi_caps,
312 +                                          arg->isi_caps);
313 +       } else {
314 +               eprintk("NULL arg->isi_caps");
315 +               ret = CI_STATUS_NULL_POINTER;
316 +               goto exit_unlock;
317 +       }
318 +       */
319 +
320 +       memcpy(&isp->sys_conf.isp_cfg, &arg->isp_cfg,
321 +                    sizeof(struct ci_isp_config));
322 +
323 +       print_bls_cfg(&isp->sys_conf.isp_cfg);
324 +
325 +       dprintk(2, "gammagamma2 = %d", arg->isp_cfg.flags.gamma2);
326 +       dprintk(2, "gammagamma2 now = %d", isp->sys_conf.isp_cfg.flags.gamma2);
327 +       mutex_unlock(&isp->mutex);
328 +
329 +       isp->sys_conf.isp_hal_enable = 1;
330 +
331 +       DBG_leaving;
332 +       return 0;
333 +}
334 +
335 +/* for buffer sharing between CI and VA */
336 +static int mrst_isp_get_frame_info(struct file *file, void *priv,
337 +                                  struct ci_frame_info *arg)
338 +{
339 +       struct video_device *dev = video_devdata(file);
340 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
341 +
342 +       WARN_ON(priv != file->private_data);
343 +
344 +       DBG_entering;
345 +
346 +       mutex_lock(&isp->mutex);
347 +
348 +       arg->width = isp->bufwidth;
349 +       arg->height = isp->bufheight;
350 +       arg->fourcc = isp->pixelformat;
351 +       arg->stride = isp->bufwidth; /* should be 64 bit alignment*/
352 +       arg->offset = arg->frame_id * PAGE_ALIGN(isp->frame_size);
353 +#if 0
354 +       if (isp->bufwidth == 640 && isp->bufheight == 480)
355 +               arg->offset = arg->frame_id * 0x71000;
356 +       else if (isp->bufwidth == 1280 && isp->bufheight == 720)
357 +               arg->offset = arg->frame_id * 0x152000;
358 +#endif
359 +
360 +
361 +       dprintk(2, "w=%d, h=%d, 4cc =%x, stride=%d, offset=%d,fsize=%d",
362 +               arg->width, arg->height, arg->fourcc, arg->stride,
363 +               arg->offset, isp->frame_size);
364 +
365 +       mutex_unlock(&isp->mutex);
366 +
367 +       DBG_leaving;
368 +       return 0;
369 +}
370 +
371 +static int mrst_isp_set_jpg_enc_ratio(struct file *file, void *priv, int *arg)
372 +{
373 +       struct video_device *dev = video_devdata(file);
374 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
375 +
376 +       WARN_ON(priv != file->private_data);
377 +
378 +       DBG_entering;
379 +
380 +       dprintk(2, "set jpg compression ratio is %d", *arg);
381 +
382 +       mutex_lock(&isp->mutex);
383 +       isp->sys_conf.isp_cfg.jpeg_enc_ratio = *arg;
384 +       mutex_unlock(&isp->mutex);
385 +
386 +       DBG_leaving;
387 +       return 0;
388 +}
389 +
390 +int mrst_isp_get_isp_mem_info(struct file *file, void *priv,
391 +                             struct ci_isp_mem_info *arg)
392 +{
393 +       u32 ret = 0;
394 +       struct video_device *dev = video_devdata(file);
395 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
396 +
397 +       WARN_ON(priv != file->private_data);
398 +
399 +       DBG_entering;
400 +
401 +       mutex_lock(&isp->mutex);
402 +       arg->isp_bar0_pa = isp->mb0;
403 +       arg->isp_bar0_size = isp->mb0_size;
404 +       arg->isp_bar1_pa = isp->mb1;
405 +       arg->isp_bar1_size = isp->mb1_size;
406 +       mutex_unlock(&isp->mutex);
407 +
408 +       DBG_leaving;
409 +       return ret;
410 +}
411 +
412 +int mrst_isp_create_jpg_review_frame(struct file *file, void *priv,
413 +                                    struct v4l2_jpg_review_buffer *arg)
414 +{
415 +       struct video_device *dev = video_devdata(file);
416 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
417 +
418 +       u32 width = arg->width;
419 +       u32 height = arg->height;
420 +       u32 pix_fmt = arg->pix_fmt;
421 +       u32 jpg_frame = arg->jpg_frame;
422 +
423 +       static struct v4l2_jpg_review_buffer *jpg_review;
424 +
425 +       jpg_review = &isp->sys_conf.jpg_review;
426 +
427 +       WARN_ON(priv != file->private_data);
428 +
429 +       DBG_entering;
430 +
431 +       if (width > 640 || height > 480 || width < 32 || height < 16) {
432 +               eprintk("unsupported resolution: %d * %d", width, height);
433 +               return -EINVAL;
434 +       }
435 +
436 +       if (jpg_frame >= isp->num_frames) {
437 +               eprintk("error jpeg frame id");
438 +               return -1;
439 +       }
440 +
441 +       jpg_review->width = width;
442 +       jpg_review->height = height;
443 +       jpg_review->pix_fmt = pix_fmt;
444 +       jpg_review->jpg_frame = jpg_frame;
445 +
446 +       switch (arg->pix_fmt) {
447 +       case V4L2_PIX_FMT_YUV422P:
448 +               jpg_review->bytesperline = width * 2;
449 +               jpg_review->frame_size = width * height * 2;
450 +               break;
451 +       case V4L2_PIX_FMT_YUV420:
452 +       case V4L2_PIX_FMT_YVU420:
453 +       case V4L2_PIX_FMT_NV12:
454 +               jpg_review->bytesperline = width * 3/2;
455 +               jpg_review->frame_size = width * height * 3/2;
456 +               break;
457 +       default:
458 +               eprintk("unsupported pix_fmt: %d", arg->pix_fmt);
459 +               return -EINVAL;
460 +       }
461 +
462 +       jpg_review->offset = isp->mb1_size - 640*480*2;
463 +
464 +       isp->sys_conf.jpg_review_enable = 1;    /* enable jpg review flag */
465 +
466 +       /* set user space data */
467 +       arg->bytesperline = jpg_review->bytesperline;
468 +       arg->frame_size = jpg_review->frame_size;
469 +       arg->offset = jpg_review->offset;
470 +
471 +       dprintk(1, "create jpg review frame successfully: "
472 +               "bytesperline = %d, frame_size = %d,"
473 +               " offset = %d\n", arg->bytesperline,
474 +               arg->frame_size, arg->offset);
475 +
476 +       DBG_leaving;
477 +       return 0;
478 +}
479 +
480 +/* isp private ioctl for libci */
481 +long mrst_isp_vidioc_default(struct file *file, void *fh,
482 +                            int cmd, void *arg)
483 +{
484 +       void *priv = file->private_data;
485 +
486 +       DBG_entering;
487 +
488 +       switch (cmd) {
489 +       case VIDIOC_GET_ISP_MEM_INFO:
490 +               return mrst_isp_get_isp_mem_info(file, priv,
491 +                                                (struct ci_isp_mem_info *)arg);
492 +
493 +       case VIDIOC_SET_SYS_CFG:
494 +               return mrst_isp_set_cfg(file, priv,
495 +                                       (struct ci_pl_system_config *)arg);
496 +
497 +       case VIDIOC_SET_JPG_ENC_RATIO:
498 +               return mrst_isp_set_jpg_enc_ratio(file, priv, (int *)arg);
499 +
500 +       case ISP_IOCTL_GET_FRAME_INFO:
501 +               return mrst_isp_get_frame_info(file, priv,
502 +                                              (struct ci_frame_info *)arg);
503 +
504 +       case VIDIOC_CREATE_JPG_REVIEW_BUF:
505 +               return mrst_isp_create_jpg_review_frame(file, priv,
506 +                                       (struct v4l2_jpg_review_buffer *)arg);
507 +       default:
508 +               v4l_print_ioctl("lnw_isp", cmd);
509 +               dprintk(2, "VIDIOC_SET_SYS_CFG = %x", VIDIOC_SET_SYS_CFG);
510 +               return -EINVAL;
511 +       }
512 +
513 +       DBG_leaving;
514 +       return 0;
515 +}
516 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c b/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c
517 new file mode 100644
518 index 0000000..dd892fb
519 --- /dev/null
520 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c
521 @@ -0,0 +1,1301 @@
522 +/*
523 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
524 + *
525 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
526 + *
527 + * Copyright (c) Silicon Image 2008  www.siliconimage.com
528 + *
529 + * This program is free software; you can redistribute it and/or
530 + * modify it under the terms of the GNU General Public License version
531 + * 2 as published by the Free Software Foundation.
532 + *
533 + * This program is distributed in the hope that it will be useful,
534 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
535 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
536 + * GNU General Public License for more details.
537 + *
538 + * You should have received a copy of the GNU General Public License
539 + * along with this program; if not, write to the Free Software
540 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
541 + * 02110-1301, USA.
542 + *
543 + *
544 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
545 + */
546 +
547 +#include "mrstisp_stdinc.h"
548 +
549 +/* mask for all chroma subsampling settings */
550 +#define CI_ISP_DPD_CSS_MASK  (CI_ISP_DPD_CSS_H_MASK | CI_ISP_DPD_CSS_V_MASK)
551 +
552 +#define SCALER_COFFS_COSITED 0x400
553 +#define FIXEDPOINT_ONE 0x1000
554 +
555 +/* limitations of main and self scaler */
556 +#define MAIN_SCALER_WIDTH_MAX 2600
557 +
558 +#define SELF_SCALER_WIDTH_MAX 640
559 +#define SCALER_MIN 16
560 +
561 +#define SELF_UPSCALE_FACTOR_MAX 5
562 +
563 +#define MAIN_UPSCALE_FACTOR_MAX 5
564 +
565 +/*
566 + * upscale lookup table for smooth edges
567 + * (linear interpolation between pixels)
568 + */
569 +
570 +/* smooth edges */
571 +static const struct ci_isp_rsz_lut isp_rsz_lut_smooth_lin = {
572 +       {
573 +       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
574 +       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
575 +       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
576 +       0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
577 +       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
578 +       0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
579 +       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
580 +       0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
581 +       }
582 +};
583 +
584 +/*
585 + * upscale lookup table for sharp edges
586 + * (no interpolation, just duplicate pixels)
587 + */
588 +
589 +/* sharp edges */
590 +static const struct ci_isp_rsz_lut isp_rsz_lut_sharp = {
591 +       {
592 +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 +       0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
597 +       0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
598 +       0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
599 +       0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F
600 +       }
601 +};
602 +
603 +/* structure combining virtual ISP windows settings */
604 +struct ci_isp_virtual_isp_wnds {
605 +       struct ci_isp_window wnd_blacklines;
606 +       struct ci_isp_window wnd_zoom_crop;
607 +};
608 +
609 +/* static storage to remember last applied virtual ISP window settings */
610 +static struct ci_isp_virtual_isp_wnds last_isp_wnds;
611 +
612 +/*
613 + * Calculates the value to program into the struct ci_isp_scale or
614 + * tsMrvSScale structures to scale from in pixels to out pixels.
615 + *
616 + * The formulas are taken from the MARVIN / MARVIN3PLUS user
617 + * manuals (fixed-point calculation using 32 bit during
618 + * processing, will overflow at an output size of 1048575 pixels).
619 + */
620 +static u32 ci_get_scale_reg(u16 in, u16 out)
621 +{
622 +       if (in > out) {
623 +               /* downscaling */
624 +               return (u32) (((((u32) out - 1) * RSZ_SCALER_BYPASS) /
625 +                                 (u32) (in - 1)) + 1);
626 +       } else if (in < out) {
627 +               /* upscaling */
628 +               return (u32) (((((u32) in - 1) * RSZ_SCALER_BYPASS) /
629 +                                 (u32) (out - 1)) | (u32) RSZ_UPSCALE_ENABLE);
630 +       }
631 +
632 +       /* no scaling */
633 +       return RSZ_SCALER_BYPASS;
634 +}
635 +
636 +/*
637 + * Calculates the values of the ci_isp_scale structure for the
638 + * given input size and data path descriptor.
639 + */
640 +static u32 ci_calc_scale_factors(const struct ci_isp_datapath_desc *source,
641 +                                const struct ci_isp_datapath_desc *path,
642 +                                struct ci_isp_scale *scale, int implementation)
643 +{
644 +       u32 scaler_output_format;
645 +       u32 cssflags;
646 +       u32 scaler_input_format;
647 +
648 +       u16 chroma_in_w;
649 +       u16 chroma_in_h;
650 +       u16 chroma_out_wcr;
651 +       u16 chroma_out_wcb;
652 +       u16 chroma_out_h;
653 +
654 +       memset(scale, 0, sizeof(struct ci_isp_scale));
655 +       dprintk(1, "srcw %d, srch %d;", source->out_w, source->out_h);
656 +       dprintk(1, "dstw %d, dsth %d", path->out_w, path->out_h);
657 +
658 +       /* calculate Y scale factors */
659 +       scale->scale_hy = ci_get_scale_reg(source->out_w, path->out_w);
660 +       scale->scale_vy = ci_get_scale_reg(source->out_h, path->out_h);
661 +
662 +       /* figure out the color input format of the scaler */
663 +       switch (path->flags & CI_ISP_DPD_MODE_MASK) {
664 +       case CI_ISP_DPD_MODE_DMAYC_DIRECT:
665 +       case CI_ISP_DPD_MODE_DMAYC_ISP:
666 +       case CI_ISP_DPD_MODE_DMAJPEG_DIRECT:
667 +       case CI_ISP_DPD_MODE_DMAJPEG_ISP:
668 +               /* DMA-read originated data */
669 +               scaler_input_format = path->flags & CI_ISP_DPD_DMA_IN_MASK;
670 +               break;
671 +       default:
672 +               /* ISP originated data */
673 +               scaler_input_format = CI_ISP_DPD_DMA_IN_422;
674 +               break;
675 +       }
676 +
677 +       dprintk(1, "scaler_input_format is 0x%x", scaler_input_format);
678 +
679 +       switch (scaler_input_format) {
680 +       case CI_ISP_DPD_DMA_IN_422:
681 +               chroma_in_w = source->out_w / 2;
682 +               chroma_in_h = source->out_h;
683 +               chroma_out_wcr = path->out_w / 2;
684 +               chroma_out_wcb = (path->out_w + 1) / 2;
685 +               chroma_out_h = path->out_h;
686 +               break;
687 +       case CI_ISP_DPD_DMA_IN_420:
688 +               chroma_in_w = source->out_w / 2;
689 +               chroma_in_h = source->out_h / 2;
690 +               chroma_out_wcr = path->out_w / 2;
691 +               chroma_out_wcb = (path->out_w + 1) / 2;
692 +               chroma_out_h = path->out_h / 2;
693 +               break;
694 +       case CI_ISP_DPD_DMA_IN_411:
695 +               chroma_in_w = source->out_w / 4;
696 +               chroma_in_h = source->out_h;
697 +               chroma_out_wcr = path->out_w / 4;
698 +               chroma_out_wcb = (path->out_w + 2) / 4;
699 +               chroma_out_h = path->out_h;
700 +               break;
701 +       case CI_ISP_DPD_DMA_IN_444:
702 +       default:
703 +               chroma_in_w = source->out_w;
704 +               chroma_in_h = source->out_h;
705 +               chroma_out_wcb = chroma_out_wcr = path->out_w;
706 +               chroma_out_h = path->out_h;
707 +               break;
708 +       }
709 +
710 +       /* calculate chrominance scale factors */
711 +       switch (path->flags & CI_ISP_DPD_CSS_H_MASK) {
712 +       case CI_ISP_DPD_CSS_H2:
713 +               chroma_out_wcb /= 2;
714 +               chroma_out_wcr /= 2;
715 +               break;
716 +       case CI_ISP_DPD_CSS_H4:
717 +               chroma_out_wcb /= 4;
718 +               chroma_out_wcr /= 4;
719 +               break;
720 +       case CI_ISP_DPD_CSS_HUP2:
721 +               chroma_out_wcb *= 2;
722 +               chroma_out_wcr *= 2;
723 +               break;
724 +       case CI_ISP_DPD_CSS_HUP4:
725 +               chroma_out_wcb *= 4;
726 +               chroma_out_wcr *= 4;
727 +               break;
728 +       default:
729 +               /*leave chroma_out_w untouched*/
730 +               break;
731 +       }
732 +
733 +       scale->scale_hcr = ci_get_scale_reg(chroma_in_w, chroma_out_wcr);
734 +       scale->scale_hcb = ci_get_scale_reg(chroma_in_w, chroma_out_wcb);
735 +       scale->scale_hcb = scale->scale_hcr;
736 +
737 +       switch (path->flags & CI_ISP_DPD_CSS_V_MASK) {
738 +       case CI_ISP_DPD_CSS_V2:
739 +               chroma_out_h /= 2;
740 +               break;
741 +       case CI_ISP_DPD_CSS_V4:
742 +               chroma_out_h /= 4;
743 +               break;
744 +       case CI_ISP_DPD_CSS_VUP2:
745 +               chroma_out_h *= 2;
746 +               break;
747 +       case CI_ISP_DPD_CSS_VUP4:
748 +               chroma_out_h *= 4;
749 +               break;
750 +       default:
751 +               /* leave chroma_out_h untouched */
752 +               break;
753 +       }
754 +
755 +       scale->scale_vc = ci_get_scale_reg(chroma_in_h, chroma_out_h);
756 +
757 +       /* additional chrominance phase shifts */
758 +       if (path->flags & CI_ISP_DPD_CSS_HSHIFT)
759 +               scale->phase_hc = SCALER_COFFS_COSITED;
760 +       if (path->flags & CI_ISP_DPD_CSS_VSHIFT)
761 +               scale->phase_vc = SCALER_COFFS_COSITED;
762 +
763 +       /* additional luminance phase shifts */
764 +       if (path->flags & CI_ISP_DPD_LUMA_HSHIFT)
765 +               scale->phase_hy = SCALER_COFFS_COSITED;
766 +       if (path->flags & CI_ISP_DPD_LUMA_VSHIFT)
767 +               scale->phase_vy = SCALER_COFFS_COSITED;
768 +
769 +       /* try to figure out the outcoming YCbCr format */
770 +       cssflags = path->flags & CI_ISP_DPD_CSS_MASK;
771 +       if (cssflags == (CI_ISP_DPD_CSS_H_OFF | CI_ISP_DPD_CSS_V_OFF)) {
772 +               /* trivial case: the output format is not changed */
773 +               scaler_output_format = scaler_input_format;
774 +       } else {
775 +               /* output format gets changed by the scaler setting */
776 +               /* assume invalid format by default */
777 +               scaler_output_format = (u32) (-1);
778 +               switch (scaler_input_format) {
779 +               case CI_ISP_DPD_DMA_IN_444:
780 +                       if (cssflags == (CI_ISP_DPD_CSS_H2
781 +                                        | CI_ISP_DPD_CSS_V_OFF)) {
782 +                               /* conversion 444 -> 422 */
783 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_422;
784 +                       } else if (cssflags == (CI_ISP_DPD_CSS_H4
785 +                                               | CI_ISP_DPD_CSS_V_OFF)) {
786 +                               /* conversion 444 -> 411 */
787 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_411;
788 +                       } else if (cssflags == (CI_ISP_DPD_CSS_H2
789 +                                               | CI_ISP_DPD_CSS_V2)) {
790 +                               /* conversion 444 -> 420 */
791 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_420;
792 +                       }
793 +                       break;
794 +
795 +               case CI_ISP_DPD_DMA_IN_422:
796 +                       if (cssflags == (CI_ISP_DPD_CSS_HUP2
797 +                                        | CI_ISP_DPD_CSS_V_OFF)) {
798 +                               /* conversion 422 -> 444 */
799 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_444;
800 +                       } else if (cssflags == (CI_ISP_DPD_CSS_H2
801 +                                               | CI_ISP_DPD_CSS_V_OFF)) {
802 +                               /* conversion 422 -> 411 */
803 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_411;
804 +                       } else if (cssflags == (CI_ISP_DPD_CSS_H_OFF
805 +                                               | CI_ISP_DPD_CSS_V2)) {
806 +                               /* conversion 422 -> 420 */
807 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_420;
808 +                       }
809 +                       break;
810 +
811 +               case CI_ISP_DPD_DMA_IN_420:
812 +                       if (cssflags == (CI_ISP_DPD_CSS_HUP2
813 +                                        | CI_ISP_DPD_CSS_VUP2)) {
814 +                               /* conversion 420 -> 444 */
815 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_444;
816 +                       } else if (cssflags == (CI_ISP_DPD_CSS_H2
817 +                                               | CI_ISP_DPD_CSS_VUP2)) {
818 +                               /* conversion 420 -> 411 */
819 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_411;
820 +                       } else if (cssflags == (CI_ISP_DPD_CSS_H_OFF
821 +                                               | CI_ISP_DPD_CSS_VUP2)) {
822 +                               /* conversion 420 -> 422 */
823 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_422;
824 +                       }
825 +                       break;
826 +
827 +               case CI_ISP_DPD_DMA_IN_411:
828 +                       if (cssflags == (CI_ISP_DPD_CSS_HUP4
829 +                                        | CI_ISP_DPD_CSS_V_OFF)) {
830 +                               /* conversion 411 -> 444 */
831 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_444;
832 +                       } else if (cssflags == (CI_ISP_DPD_CSS_HUP2
833 +                                               | CI_ISP_DPD_CSS_V_OFF)) {
834 +                               /* conversion 411 -> 422 */
835 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_422;
836 +                       } else if (cssflags == (CI_ISP_DPD_CSS_HUP2
837 +                                               | CI_ISP_DPD_CSS_V2)) {
838 +                               /* conversion 411 -> 420 */
839 +                               scaler_output_format = CI_ISP_DPD_DMA_IN_420;
840 +                       }
841 +                       break;
842 +
843 +               default:
844 +                       /* DMA input format not supported */
845 +                       break;
846 +               }
847 +       }
848 +
849 +       return scaler_output_format;
850 +}
851 +
852 +/*
853 + * Returns the address of up-scaling lookup table to use for
854 + * the given data path flags.
855 + */
856 +static const struct ci_isp_rsz_lut *ci_get_rsz_lut(u32 flags)
857 +{
858 +       const struct ci_isp_rsz_lut *ret_val;
859 +       switch (flags & CI_ISP_DPD_UPSCALE_MASK) {
860 +       case CI_ISP_DPD_UPSCALE_SHARP:
861 +               ret_val = &isp_rsz_lut_sharp;
862 +               break;
863 +       default:
864 +               ret_val = &isp_rsz_lut_smooth_lin;
865 +               break;
866 +       }
867 +       return ret_val;
868 +}
869 +
870 +/*
871 + * Fills in scale factors and MI configuration for the main path.
872 + * Note that only self path related settings will be written into
873 + * the MI configuration struct, so this routine can be used for
874 + * both ISP and DMA originated data path setups.
875 + *
876 + * Following fields are being filled in:
877 + * scale_main: [all fields]
878 + * mrv_mi_ctrl: mrv_mif_mp_pic_form main_path
879 + */
880 +static int ci_calc_main_path_settings(const struct ci_isp_datapath_desc *source,
881 +                                     const struct ci_isp_datapath_desc  *main,
882 +                                     struct ci_isp_scale *scale_main,
883 +                                     struct ci_isp_mi_ctrl *mrv_mi_ctrl)
884 +{
885 +       u32 main_flag;
886 +
887 +       WARN_ON(!(source != NULL));
888 +       WARN_ON(!(scale_main != NULL));
889 +       WARN_ON(!(mrv_mi_ctrl != NULL));
890 +
891 +       /* assume datapath deactivation if no selfpath pointer is given) */
892 +       if (main)
893 +               main_flag = main->flags;
894 +       else
895 +               main_flag = 0;
896 +
897 +       /* initialize the given parameters */
898 +       memset(scale_main, 0, sizeof(struct ci_isp_scale));
899 +       scale_main->scale_hy = RSZ_SCALER_BYPASS;
900 +       scale_main->scale_hcb = RSZ_SCALER_BYPASS;
901 +       scale_main->scale_hcr = RSZ_SCALER_BYPASS;
902 +       scale_main->scale_vy = RSZ_SCALER_BYPASS;
903 +       scale_main->scale_vc = RSZ_SCALER_BYPASS;
904 +
905 +       if (main_flag & CI_ISP_DPD_ENABLE) {
906 +               switch (main_flag & CI_ISP_DPD_MODE_MASK) {
907 +               case CI_ISP_DPD_MODE_ISPYC:
908 +               case CI_ISP_DPD_MODE_DMAYC_ISP:
909 +                       mrv_mi_ctrl->main_path = CI_ISP_PATH_ON;
910 +                       break;
911 +               case CI_ISP_DPD_MODE_ISPJPEG:
912 +               case CI_ISP_DPD_MODE_DMAJPEG_DIRECT:
913 +               case CI_ISP_DPD_MODE_DMAJPEG_ISP:
914 +                       mrv_mi_ctrl->main_path = CI_ISP_PATH_JPE;
915 +                       break;
916 +               case CI_ISP_DPD_MODE_ISPRAW:
917 +                       mrv_mi_ctrl->main_path = CI_ISP_PATH_RAW8;
918 +                       break;
919 +               case CI_ISP_DPD_MODE_ISPRAW_16B:
920 +                       mrv_mi_ctrl->main_path = CI_ISP_PATH_RAW816;
921 +                       break;
922 +               default:
923 +                       eprintk("unsupported mode for main path");
924 +                       return CI_STATUS_NOTSUPP;
925 +               }
926 +               if (main_flag & (CI_ISP_DPD_H_FLIP | CI_ISP_DPD_V_FLIP |
927 +                       CI_ISP_DPD_90DEG_CCW)) {
928 +                       eprintk("not supported for main path");
929 +                       return CI_STATUS_NOTSUPP;
930 +               }
931 +               if (main_flag & CI_ISP_DPD_NORESIZE) {
932 +                       if (main_flag & CI_ISP_DPD_CSS_MASK) {
933 +                               eprintk("main path needs rezizer");
934 +                               return CI_STATUS_NOTSUPP;
935 +                       }
936 +                       if (main_flag &
937 +                           (CI_ISP_DPD_LUMA_HSHIFT | CI_ISP_DPD_LUMA_VSHIFT)) {
938 +                               eprintk("main path needs rezizer");
939 +                               return CI_STATUS_NOTSUPP;
940 +                       }
941 +               } else {
942 +                       if ((mrv_mi_ctrl->main_path == CI_ISP_PATH_RAW8)
943 +                           || (mrv_mi_ctrl->main_path == CI_ISP_PATH_RAW8)) {
944 +                               eprintk("scaler not in RAW mode");
945 +                               return CI_STATUS_NOTSUPP;
946 +                       }
947 +                       /* changed to avoid LINT warnings (Warning 613) */
948 +                       if (main != NULL) {
949 +                               if ((((u32) (source->out_w) *
950 +                                     MAIN_UPSCALE_FACTOR_MAX) < main->out_w)
951 +                                   ||
952 +                                   (((u32) (source->out_h) *
953 +                                     MAIN_UPSCALE_FACTOR_MAX) <
954 +                                    main->out_h)) {
955 +                                       eprintk("main upscaling exceeded");
956 +                                       return CI_STATUS_NOTSUPP;
957 +                               }
958 +                               if ((main->out_w >
959 +                                    MAIN_SCALER_WIDTH_MAX)
960 +                                   || (main->out_w < SCALER_MIN)
961 +                                   || (main->out_h < SCALER_MIN)) {
962 +                                       eprintk("main scaler ange exceeded");
963 +                                       return CI_STATUS_NOTSUPP;
964 +                               }
965 +                       } else {
966 +                               WARN_ON(main == NULL);
967 +                       }
968 +
969 +                       if (source->out_w & 0x01) {
970 +                               eprintk("input width must be even!");
971 +                               return CI_STATUS_NOTSUPP;
972 +                       }
973 +
974 +                       /* calculate scale factors. */
975 +                       (void)ci_calc_scale_factors(source, main, scale_main,
976 +                                           MARVIN_FEATURE_MSCALE_FACTORCALC);
977 +               }
978 +       } else {
979 +               mrv_mi_ctrl->main_path = CI_ISP_PATH_OFF;
980 +       }
981 +
982 +       /* hardcoded MI settings */
983 +       dprintk(1, "main_flag is 0x%x", main_flag);
984 +       if (main_flag & CI_ISP_DPD_HWRGB_MASK) {
985 +               switch (main_flag & CI_ISP_DPD_HWRGB_MASK) {
986 +               case CI_ISP_DPD_YUV_420:
987 +               case CI_ISP_DPD_YUV_422:
988 +                       mrv_mi_ctrl->mrv_mif_mp_pic_form =
989 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
990 +                       break;
991 +               case CI_ISP_DPD_YUV_NV12:
992 +                       mrv_mi_ctrl->mrv_mif_mp_pic_form =
993 +                               CI_ISP_MIF_PIC_FORM_SEMI_PLANAR;
994 +                       break;
995 +               case CI_ISP_DPD_YUV_YUYV:
996 +                       mrv_mi_ctrl->mrv_mif_mp_pic_form =
997 +                               CI_ISP_MIF_PIC_FORM_INTERLEAVED;
998 +                       break;
999 +               default:
1000 +                       mrv_mi_ctrl->mrv_mif_mp_pic_form =
1001 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1002 +               }
1003 +       }
1004 +
1005 +       return CI_STATUS_SUCCESS;
1006 +}
1007 +
1008 +/*
1009 + * Fills in scale factors and MI configuration for the self
1010 + * path.  Note that only self path related settings will be written into
1011 + * the MI config struct, so this routine can be used for both ISP and DMA
1012 + * originated datapath setups.
1013 + *
1014 + * Following fields are being filled in:
1015 + *           scale_flag :
1016 + *              [all fields]
1017 + *           mrv_mi_ctrl :
1018 + *              mrv_mif_sp_out_form
1019 + *              mrv_mif_sp_in_form
1020 + *              mrv_mif_sp_pic_form
1021 + *              mrv_mif_sp_mode
1022 + *              self_path
1023 + */
1024 +static int ci_calc_self_path_settings(const struct ci_isp_datapath_desc *source,
1025 +                                     const struct ci_isp_datapath_desc *self,
1026 +                                     struct ci_isp_scale *scale_flag,
1027 +                                     struct ci_isp_mi_ctrl *mrv_mi_ctrl)
1028 +{
1029 +       u32 scaler_out_col_format;
1030 +       u32 self_flag;
1031 +
1032 +       WARN_ON(!(source != NULL));
1033 +       WARN_ON(!(scale_flag != NULL));
1034 +       WARN_ON(!(mrv_mi_ctrl != NULL));
1035 +
1036 +       /* assume datapath deactivation if no selfpath pointer is given) */
1037 +       if (self)
1038 +               self_flag = self->flags;
1039 +       else
1040 +               self_flag = 0;
1041 +
1042 +       /* initialize the given parameters */
1043 +       memset(scale_flag, 0, sizeof(struct ci_isp_scale));
1044 +       scale_flag->scale_hy = RSZ_SCALER_BYPASS;
1045 +       scale_flag->scale_hcb = RSZ_SCALER_BYPASS;
1046 +       scale_flag->scale_hcr = RSZ_SCALER_BYPASS;
1047 +       scale_flag->scale_vy = RSZ_SCALER_BYPASS;
1048 +       scale_flag->scale_vc = RSZ_SCALER_BYPASS;
1049 +
1050 +       if (self_flag & CI_ISP_DPD_ENABLE) {
1051 +
1052 +               switch (self_flag & CI_ISP_DPD_MODE_MASK) {
1053 +               case CI_ISP_DPD_MODE_ISPYC:
1054 +                       mrv_mi_ctrl->self_path = CI_ISP_PATH_ON;
1055 +                       scaler_out_col_format = CI_ISP_DPD_DMA_IN_422;
1056 +                       break;
1057 +               case CI_ISP_DPD_MODE_DMAYC_ISP:
1058 +               case CI_ISP_DPD_MODE_DMAYC_DIRECT:
1059 +                       mrv_mi_ctrl->self_path = CI_ISP_PATH_ON;
1060 +                       scaler_out_col_format =
1061 +                           self_flag & CI_ISP_DPD_DMA_IN_MASK;
1062 +                       break;
1063 +               default:
1064 +                       eprintk("unsupported mode for self path");
1065 +                       return CI_STATUS_NOTSUPP;
1066 +               }
1067 +
1068 +               if (self_flag & CI_ISP_DPD_NORESIZE) {
1069 +                       if (self_flag & CI_ISP_DPD_CSS_MASK) {
1070 +                               eprintk("in self path needs rezizer");
1071 +                               return CI_STATUS_NOTSUPP;
1072 +                       }
1073 +                       if (self_flag &
1074 +                           (CI_ISP_DPD_LUMA_HSHIFT | CI_ISP_DPD_LUMA_VSHIFT)) {
1075 +                               eprintk("n self path needs rezizer");
1076 +                               return CI_STATUS_NOTSUPP;
1077 +                       }
1078 +                       /* changed to avoid LINT warnings (Warning 613) */
1079 +                       if (self != NULL) {
1080 +                               if ((source->out_w != self->out_w) ||
1081 +                                   (source->out_h != self->out_h)) {
1082 +                                       eprintk("sizes needs resizer");
1083 +                                       return CI_STATUS_NOTSUPP;
1084 +                               }
1085 +                       } else {
1086 +                               WARN_ON(self == NULL);
1087 +                       }
1088 +               } else {
1089 +                       /* changed to avoid LINT warnings (Warning 613) */
1090 +                       if (self != NULL) {
1091 +                               /* upscaling only to factor
1092 +                                * SELF_UPSCALE_FACTOR_MAX possible
1093 +                                */
1094 +                               if ((((u32) (source->out_w) *
1095 +                                     SELF_UPSCALE_FACTOR_MAX) <
1096 +                                    self->out_w)
1097 +                                   ||
1098 +                                   (((u32) (source->out_h) *
1099 +                                     SELF_UPSCALE_FACTOR_MAX) <
1100 +                                    self->out_h)) {
1101 +                                       eprintk("apability exceeded");
1102 +                                       return CI_STATUS_NOTSUPP;
1103 +                               }
1104 +                               if ((self->out_w >
1105 +                                    SELF_SCALER_WIDTH_MAX)
1106 +                                   || (self->out_w < SCALER_MIN)
1107 +                                   || (self->out_h < SCALER_MIN)) {
1108 +                                       eprintk("out range exceeded");
1109 +                                       return CI_STATUS_NOTSUPP;
1110 +                               }
1111 +                       } else {
1112 +                               WARN_ON(self == NULL);
1113 +                       }
1114 +                       /* Remember that the input picture width should be
1115 +                        * even if the scaler is used */
1116 +
1117 +                       /* (otherwise the scaler may show unexpected
1118 +                        * behaviour in some rare cases) */
1119 +                       if (source->out_w & 0x01) {
1120 +                               eprintk("width must be even!");
1121 +                               return CI_STATUS_NOTSUPP;
1122 +                       }
1123 +
1124 +                       /* calculate scale factors. */
1125 +                       scaler_out_col_format =
1126 +                           ci_calc_scale_factors(source, self, scale_flag,
1127 +                                         MARVIN_FEATURE_SSCALE_FACTORCALC);
1128 +               }
1129 +
1130 +               dprintk(2, "step1");
1131 +               /* figure out the input format setting */
1132 +               switch (scaler_out_col_format) {
1133 +               case CI_ISP_DPD_DMA_IN_444:
1134 +                       mrv_mi_ctrl->mrv_mif_sp_in_form =
1135 +                           CI_ISP_MIF_COL_FORMAT_YCBCR_444;
1136 +                       break;
1137 +               case CI_ISP_DPD_DMA_IN_422:
1138 +                       mrv_mi_ctrl->mrv_mif_sp_in_form =
1139 +                           CI_ISP_MIF_COL_FORMAT_YCBCR_422;
1140 +                       break;
1141 +               case CI_ISP_DPD_DMA_IN_420:
1142 +                       mrv_mi_ctrl->mrv_mif_sp_in_form =
1143 +                           CI_ISP_MIF_COL_FORMAT_YCBCR_420;
1144 +                       break;
1145 +                       /* no break, does not seem to be supported by HW */
1146 +               case CI_ISP_DPD_DMA_IN_411:
1147 +               default:
1148 +                       eprintk("input color format not supported");
1149 +                       return CI_STATUS_NOTSUPP;
1150 +               }
1151 +
1152 +               /* figure out the output format setting */
1153 +               dprintk(2, "step2, self_flag is 0x%x", self_flag);
1154 +
1155 +               switch (self_flag & CI_ISP_DPD_HWRGB_MASK) {
1156 +               case CI_ISP_DPD_HWRGB_565:
1157 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1158 +                           CI_ISP_MIF_COL_FORMAT_RGB_565;
1159 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1160 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1161 +                       break;
1162 +               case CI_ISP_DPD_HWRGB_666:
1163 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1164 +                           CI_ISP_MIF_COL_FORMAT_RGB_666;
1165 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1166 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1167 +                       break;
1168 +               case CI_ISP_DPD_HWRGB_888:
1169 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1170 +                           CI_ISP_MIF_COL_FORMAT_RGB_888;
1171 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1172 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1173 +                       break;
1174 +               case CI_ISP_DPD_YUV_420:
1175 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1176 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1177 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1178 +                               CI_ISP_MIF_COL_FORMAT_YCBCR_420;
1179 +                       break;
1180 +               case CI_ISP_DPD_YUV_422:
1181 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1182 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1183 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1184 +                               CI_ISP_MIF_COL_FORMAT_YCBCR_422;
1185 +                       break;
1186 +               case CI_ISP_DPD_YUV_NV12:
1187 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1188 +                               CI_ISP_MIF_PIC_FORM_SEMI_PLANAR;
1189 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1190 +                               CI_ISP_MIF_COL_FORMAT_YCBCR_420;
1191 +                       break;
1192 +               case CI_ISP_DPD_YUV_YUYV:
1193 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1194 +                               CI_ISP_MIF_PIC_FORM_INTERLEAVED;
1195 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1196 +                               CI_ISP_MIF_COL_FORMAT_YCBCR_422;
1197 +                       break;
1198 +
1199 +               case CI_ISP_DPD_HWRGB_OFF:
1200 +                       mrv_mi_ctrl->mrv_mif_sp_out_form =
1201 +                           mrv_mi_ctrl->mrv_mif_sp_in_form;
1202 +                       mrv_mi_ctrl->mrv_mif_sp_pic_form =
1203 +                               CI_ISP_MIF_PIC_FORM_PLANAR;
1204 +                       break;
1205 +               default:
1206 +                       eprintk("output color format not supported");
1207 +                       return CI_STATUS_NOTSUPP;
1208 +               }
1209 +
1210 +               /* picture flipping / rotation */
1211 +               dprintk(2, "step3");
1212 +
1213 +               switch (self_flag &
1214 +                       (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_V_FLIP |
1215 +                        CI_ISP_DPD_H_FLIP)) {
1216 +               case (CI_ISP_DPD_H_FLIP):
1217 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1218 +                       CI_ISP_MIF_SP_HORIZONTAL_FLIP;
1219 +                       break;
1220 +               case (CI_ISP_DPD_V_FLIP):
1221 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1222 +                       CI_ISP_MIF_SP_VERTICAL_FLIP;
1223 +                       break;
1224 +               case (CI_ISP_DPD_V_FLIP | CI_ISP_DPD_H_FLIP):
1225 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1226 +                       CI_ISP_MIF_SP_ROTATION_180_DEG;
1227 +                       break;
1228 +               case (CI_ISP_DPD_90DEG_CCW):
1229 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1230 +                       CI_ISP_MIF_SP_ROTATION_090_DEG;
1231 +                       break;
1232 +               case (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_H_FLIP):
1233 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1234 +                       CI_ISP_MIF_SP_ROT_270_V_FLIP;
1235 +                       break;
1236 +               case (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_V_FLIP):
1237 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1238 +                       CI_ISP_MIF_SP_ROT_090_V_FLIP;
1239 +                       break;
1240 +               case (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_V_FLIP |
1241 +                       CI_ISP_DPD_H_FLIP):
1242 +                       mrv_mi_ctrl->mrv_mif_sp_mode =
1243 +                       CI_ISP_MIF_SP_ROTATION_270_DEG;
1244 +                       break;
1245 +               default:
1246 +                       mrv_mi_ctrl->mrv_mif_sp_mode = CI_ISP_MIF_SP_ORIGINAL;
1247 +                       break;
1248 +               }
1249 +
1250 +       } else {
1251 +               mrv_mi_ctrl->self_path = CI_ISP_PATH_OFF;
1252 +       }
1253 +
1254 +       dprintk(2, "step4");
1255 +       /*mrv_mi_ctrl->mrv_mif_sp_pic_form = CI_ISP_MIF_PIC_FORM_PLANAR;*/
1256 +
1257 +       return CI_STATUS_SUCCESS;
1258 +}
1259 +
1260 +/*
1261 + * Translates the given memory interface configuration struct
1262 + * into appropriate values to program the data path multiplexers.
1263 + */
1264 +static int ci_calc_dp_mux_settings(const struct ci_isp_mi_ctrl *mi_ctrl,
1265 +                                  enum ci_isp_ycs_chn_mode *peYcsChnMode,
1266 +                                  enum ci_isp_dp_switch *peDpSwitch)
1267 +{
1268 +       switch (mi_ctrl->main_path) {
1269 +       case CI_ISP_PATH_RAW8:
1270 +       case CI_ISP_PATH_RAW816:
1271 +               *peDpSwitch = CI_ISP_DP_RAW;
1272 +               *peYcsChnMode = CI_ISP_YCS_MVRaw;
1273 +               if (mi_ctrl->self_path != CI_ISP_PATH_OFF) {
1274 +                       eprintk("ombined with RAW mode of main path");
1275 +                       return CI_STATUS_NOTSUPP;
1276 +               }
1277 +               break;
1278 +
1279 +       case CI_ISP_PATH_JPE:
1280 +               *peDpSwitch = CI_ISP_DP_JPEG;
1281 +               if (mi_ctrl->self_path != CI_ISP_PATH_OFF)
1282 +                       *peYcsChnMode = CI_ISP_YCS_MV_SP;
1283 +               else
1284 +                       *peYcsChnMode = CI_ISP_YCS_MV;
1285 +               break;
1286 +
1287 +       case CI_ISP_PATH_ON:
1288 +               *peDpSwitch = CI_ISP_DP_MV;
1289 +               if (mi_ctrl->self_path != CI_ISP_PATH_OFF)
1290 +                       *peYcsChnMode = CI_ISP_YCS_MV_SP;
1291 +               else
1292 +                       *peYcsChnMode = CI_ISP_YCS_MV;
1293 +               break;
1294 +
1295 +       case CI_ISP_PATH_OFF:
1296 +               *peDpSwitch = CI_ISP_DP_MV;
1297 +               if (mi_ctrl->self_path != CI_ISP_PATH_OFF)
1298 +                       *peYcsChnMode = CI_ISP_YCS_SP;
1299 +               else
1300 +                       *peYcsChnMode = CI_ISP_YCS_OFF;
1301 +               break;
1302 +
1303 +       default:
1304 +               return CI_STATUS_NOTSUPP;
1305 +       }
1306 +
1307 +       return CI_STATUS_SUCCESS;
1308 +}
1309 +
1310 +/* the windows to cut away black pixels and to zoom/crop the */
1311 +#define ISPWND_COMBINE_WNDS    0x00000001
1312 +/* image must be combined before they are applyed to the marvin registers */
1313 +/* call of the ci_isp_set_output_formatter() routine necessary */
1314 +#define ISPWND_APPLY_OUTFORM   0x00000002
1315 +/* call of the ci_isp_is_set_config() routine necessary */
1316 +#define ISPWND_APPLY_ISCONF    0x00000004
1317 +/* no cropping supported at all */
1318 +#define ISPWND_NO_CROPPING     0x00000008
1319 +
1320 +/*
1321 + * Returns information about how to combine black pixel and
1322 + * zoom/crop windows for programming the ISP output formatter and the image
1323 + * stabilization unit for the given marvin derivative and ISP path.
1324 + */
1325 +static u32 ci_get_isp_wnd_style(enum ci_isp_path isp_path)
1326 +{
1327 +       u32 res = 0;
1328 +
1329 +       /* output formatter exists at ISP input */
1330 +       /* image stabilization in both bayer and YCbCr paths */
1331 +       if ((isp_path == CI_ISP_PATH_BAYER) ||
1332 +           (isp_path == CI_ISP_PATH_YCBCR))
1333 +               /*we need to program the output formatter with the blackline
1334 +                * window and */
1335 +               res = ISPWND_APPLY_OUTFORM | ISPWND_APPLY_ISCONF;
1336 +       else
1337 +               res = ISPWND_COMBINE_WNDS | ISPWND_APPLY_OUTFORM;
1338 +
1339 +       return res;
1340 +}
1341 +
1342 +/*
1343 + *  the given windows for cutting away blacklines coming from
1344 + *  the image sensor and further cropping of the image for other
1345 + *  purposes like e.g. digital zoom to the output formatter and/or
1346 + *  image stabilisation modules of Marvins ISP.
1347 + */
1348 +static int ci_set_isp_windows(const struct ci_sensor_config *isi_sensor_config,
1349 +                             const struct ci_isp_window *wnd_blackline,
1350 +                             const struct ci_isp_window *wnd_zoom_crop)
1351 +{
1352 +       struct ci_isp_window wnd_out_form;
1353 +       struct ci_isp_is_config is_conf;
1354 +       enum ci_isp_path isp_path;
1355 +       u32 wnd_style;
1356 +
1357 +       memset(&wnd_out_form, 0, sizeof(wnd_out_form));
1358 +       memset(&is_conf, 0, sizeof(is_conf));
1359 +
1360 +       /*
1361 +        * figure out the path through the ISP to process the data from the
1362 +        * image sensor
1363 +        */
1364 +       isp_path = ci_isp_select_path(isi_sensor_config, NULL);
1365 +       if (isp_path == CI_ISP_PATH_UNKNOWN) {
1366 +               eprintk("detect marvin ISP path to use");
1367 +               return CI_STATUS_NOTSUPP;
1368 +       }
1369 +
1370 +       /*
1371 +        * get the recommended way to configure output formatter and/or
1372 +        * image stabilization
1373 +        */
1374 +       wnd_style = ci_get_isp_wnd_style(isp_path);
1375 +       if (wnd_style & ISPWND_NO_CROPPING) {
1376 +               /*
1377 +                * cropping not possible -> make sure that it is *not*
1378 +                * supposed to be used
1379 +                */
1380 +               u16 isiX;
1381 +               u16 isiY;
1382 +               /* changed to avoid LINT warnings (Warning 534) */
1383 +               (void)ci_sensor_res2size(isi_sensor_config->res, &isiX, &isiY);
1384 +               if ((wnd_zoom_crop->hsize != isiX)
1385 +                   || (wnd_zoom_crop->vsize != isiY)
1386 +                   || (wnd_zoom_crop->hoffs != 0)
1387 +                   || (wnd_zoom_crop->voffs != 0)) {
1388 +                       eprintk("in selected ISP data path");
1389 +                       return CI_STATUS_NOTSUPP;
1390 +               }
1391 +               if ((wnd_blackline->hsize != isiX) ||
1392 +                   (wnd_blackline->vsize != isiY) ||
1393 +                   (wnd_blackline->hoffs != 0) ||
1394 +                   (wnd_blackline->voffs != 0)) {
1395 +                       eprintk("supported in selected ISP data path");
1396 +                       return CI_STATUS_NOTSUPP;
1397 +               }
1398 +       }
1399 +
1400 +       /*
1401 +        * The image stabilization is allowed to move the window in both
1402 +        * directions by the same amount of pixels we have calculated for
1403 +        * the offsets. The initial image stabilization window is equal to
1404 +        * the zoom/crop window
1405 +        */
1406 +       is_conf.max_dx = wnd_zoom_crop->hoffs;
1407 +       is_conf.max_dy = wnd_zoom_crop->voffs;
1408 +       is_conf.mrv_is_window = *wnd_zoom_crop;
1409 +
1410 +       /* combine both blackline and zoom/crop window */
1411 +       if (wnd_style & ISPWND_COMBINE_WNDS) {
1412 +               /* combine both blackline and zoom/crop window */
1413 +               wnd_out_form = *wnd_zoom_crop;
1414 +               wnd_out_form.voffs += wnd_blackline->voffs;
1415 +               wnd_out_form.hoffs += wnd_blackline->hoffs;
1416 +               is_conf.mrv_is_window = wnd_out_form;
1417 +               if (wnd_style & ISPWND_APPLY_OUTFORM) {
1418 +                       /*
1419 +                        * if the output formatter is to be used, offsets
1420 +                        * are cut away there, so
1421 +                        * we don't need additional ones in the imags
1422 +                        * stabilization unit
1423 +                        */
1424 +                       is_conf.mrv_is_window.hoffs = 0;
1425 +                       is_conf.mrv_is_window.voffs = 0;
1426 +               }
1427 +       } else {
1428 +               /*
1429 +                * do not combine windows --> blacklines done with output
1430 +                * formatter, zoom/cropping done with image stabilization
1431 +                */
1432 +               wnd_out_form = *wnd_blackline;
1433 +               is_conf.mrv_is_window = *wnd_zoom_crop;
1434 +       }
1435 +
1436 +       /* finally, apply the settings to marvin */
1437 +       if (wnd_style & ISPWND_APPLY_OUTFORM) {
1438 +               ci_isp_set_output_formatter(&wnd_out_form,
1439 +                                           CI_ISP_CFG_UPDATE_IMMEDIATE);
1440 +       }
1441 +       if (wnd_style & ISPWND_APPLY_ISCONF) {
1442 +               int res = ci_isp_is_set_config(&is_conf);
1443 +               if (res != CI_STATUS_SUCCESS) {
1444 +                       eprintk("set image stabilization config");
1445 +                       return res;
1446 +               }
1447 +       }
1448 +
1449 +       /* success - remember our virtual settings */
1450 +       last_isp_wnds.wnd_blacklines = *wnd_blackline;
1451 +       last_isp_wnds.wnd_zoom_crop = *wnd_zoom_crop;
1452 +
1453 +       return CI_STATUS_SUCCESS;
1454 +}
1455 +
1456 +/* sets extended YCbCr mode */
1457 +static int ci_ext_ycb_cr_mode(const struct ci_isp_datapath_desc *path)
1458 +{
1459 +       u32 main_flag;
1460 +
1461 +       WARN_ON(!(path != NULL));
1462 +
1463 +       /* assume datapath deactivation if no selfpath pointer is given) */
1464 +       if (path)
1465 +               main_flag = path->flags;
1466 +       else
1467 +               main_flag = 0;
1468 +
1469 +       /* if flag CI_ISP_DPD_YCBCREXT is set set extended YCbCr mode */
1470 +       if (main_flag & CI_ISP_DPD_ENABLE) {
1471 +               if (main_flag & CI_ISP_DPD_YCBCREXT)
1472 +                       ci_isp_set_ext_ycmode();
1473 +       }
1474 +
1475 +       return CI_STATUS_SUCCESS;
1476 +}
1477 +
1478 +/*
1479 + * Configures main and self data pathes and scaler for data coming from the ISP.
1480 + *
1481 + * Following MARVIN subsystems are programmed:
1482 + * - ISP output formatter
1483 + * - Image stabilization module
1484 + * - YC-Splitter
1485 + * - Self path DMA-read multiplexer
1486 + * - Main path multiplexer
1487 + * - Main & Self path resizer
1488 + * - Small output unit
1489 + * - Memory Interface (MI) input source, en/disable and data format
1490 + *
1491 + * Following MARVIN subsystems are *NOT* programmed:
1492 + * - All ISP functionality but the output formatter & image stabilization module
1493 + * - color Processing block
1494 + * - JPEG encode subsystem (quantisation tables etc.)
1495 + * - Memory Interface (MI) output buffer addresses and sizes
1496 + */
1497 +int ci_datapath_isp(const struct ci_pl_system_config *sys_conf,
1498 +                   const struct ci_sensor_config *isi_config,
1499 +                   const struct ci_isp_datapath_desc *main,
1500 +                   const struct ci_isp_datapath_desc *self, int zoom)
1501 +{
1502 +       int res;
1503 +       /*
1504 +        * copy of flags for main and self path to simplify access (no
1505 +        * pointer de-reference)
1506 +        */
1507 +       u32 main_flag;
1508 +       u32 self_flag;
1509 +       /* resolution from sensor configuration */
1510 +       u16 isiX;
1511 +       u16 isiY;
1512 +       /* things to apply to MARVIN */
1513 +       struct ci_isp_scale scale_main;
1514 +       struct ci_isp_scale scale_flag;
1515 +       enum ci_isp_ycs_chn_mode chn_mode = 0;
1516 +       enum ci_isp_dp_switch dp_switch = 0;
1517 +       struct ci_isp_mi_ctrl mrv_mi_ctrl;
1518 +       struct ci_isp_datapath_desc source;
1519 +       /* ISP windowing because of cutting away blacklines from the sensor */
1520 +       struct ci_isp_window wnd_blackline;
1521 +       /* ISP windowing because of aspect ratio change and/or zoom */
1522 +       struct ci_isp_window wnd_zoom_crop;
1523 +
1524 +       const struct ci_isp_datapath_desc *target = NULL;
1525 +
1526 +       /* assume dapapath deactivation for not provided descriptors */
1527 +       main_flag = 0;
1528 +       self_flag = 0;
1529 +       if (main)
1530 +               main_flag = main->flags;        /* 0x012 */
1531 +
1532 +       if (self)
1533 +               self_flag = self->flags;        /* 0x10015 */
1534 +
1535 +       /* initialize variables on the stack */
1536 +       res = CI_STATUS_SUCCESS;
1537 +       /* changed to avoid LINT warnings (Warning 534) */
1538 +       (void)ci_sensor_res2size(isi_config->res, &isiX, &isiY);
1539 +       memset(&mrv_mi_ctrl, 0, sizeof(struct ci_isp_mi_ctrl));
1540 +       memset(&wnd_blackline, 0, sizeof(wnd_blackline));
1541 +       memset(&wnd_zoom_crop, 0, sizeof(wnd_zoom_crop));
1542 +
1543 +       /*
1544 +        * ISP Windowing - fill in wnd_out_form, apply_out_form, is_conf and
1545 +        * apply_is_conf
1546 +        */
1547 +
1548 +       /*
1549 +        * by default, size of both blackline and zoom/crop window
1550 +        * is what the camera delivers.
1551 +        */
1552 +
1553 +       /* (no cropping, no offset) */
1554 +       wnd_blackline.hsize = isiX;
1555 +       wnd_blackline.vsize = isiY;
1556 +       wnd_zoom_crop = wnd_blackline;
1557 +
1558 +       /*
1559 +        * check if we have to crop because of aspect ratio
1560 +        * preservement of an
1561 +        */
1562 +
1563 +       /* output channel */
1564 +       if ((main_flag & CI_ISP_DPD_ENABLE) &&
1565 +           (main_flag & CI_ISP_DPD_KEEPRATIO)) {
1566 +               target = main;
1567 +       }
1568 +       if ((self_flag & CI_ISP_DPD_ENABLE) &&
1569 +           (self_flag & CI_ISP_DPD_KEEPRATIO)) {
1570 +               if (target) {
1571 +                       eprintk("only allowed for one path");
1572 +                       return CI_STATUS_NOTSUPP;
1573 +               }
1574 +               target = self;
1575 +       }
1576 +
1577 +       /* if so, calculate the cropping */
1578 +       if (target) {
1579 +               u32 aspect_cam = (0x1000 * ((u32) isiX)) / isiY;
1580 +               u32 aspect_target = (0x1000 * ((u32) (target->out_w))) /
1581 +                   target->out_h;
1582 +               if (aspect_cam < aspect_target) {
1583 +                       /*
1584 +                        * camera aspect is more 'portrait-like' as
1585 +                        * target aspect. We have to crop the
1586 +                        * camera picture by cutting off a bit of
1587 +                        * the top & bottom changed to avoid LINT
1588 +                        * warnings (Info 734)
1589 +                        */
1590 +                       wnd_zoom_crop.vsize = (u16) (((u32) isiX *
1591 +                                      (u32) (target->out_h)) / target->out_w);
1592 +               } else  {
1593 +                       /* camera aspect is more 'landscape-like'
1594 +                        * as target aspect. We have to crop the
1595 +                        * camera picture by cutting off a bit of
1596 +                        * the left and right changed to avoid LINT
1597 +                        * warnings (Info 734) */
1598 +                       wnd_zoom_crop.hsize = (u16) (((u32) isiY *
1599 +                                      (u32) (target->out_w)) / target->out_h);
1600 +               }
1601 +       }
1602 +
1603 +       /*
1604 +        * now, we may also want to do digital zoom. If so, we need
1605 +        * to shrink the ISP window by the desired zoom factor.
1606 +        */
1607 +       if (zoom > 0) {
1608 +               /* changed to avoid LINT warnings (Warning 573) */
1609 +               wnd_zoom_crop.vsize = (u16) (((u32) (wnd_zoom_crop.vsize) *
1610 +                              1024) / (1024 + (u32) zoom));
1611 +               /* changed to avoid LINT warnings (Warning 573) */
1612 +               wnd_zoom_crop.hsize = (u16) (((u32) (wnd_zoom_crop.hsize) *
1613 +                              1024) / (1024 + (u32) zoom));
1614 +       }
1615 +       /*
1616 +        * Remember that the output formatter h_size should be
1617 +        * even if the scaler is used
1618 +        * (otherwise the scaler may show unexpected behaviour in
1619 +        * some rare cases)
1620 +        */
1621 +       wnd_zoom_crop.hsize &= ~0x01;
1622 +       /*
1623 +        * At last, we care about the offset of the ISP window. We
1624 +        * want it centered on the image data delivered by the
1625 +        * sensor (not counting possible black lines)
1626 +        */
1627 +       wnd_zoom_crop.hoffs = (isiX - wnd_zoom_crop.hsize) / 2;
1628 +       wnd_zoom_crop.voffs = (isiY - wnd_zoom_crop.vsize) / 2;
1629 +       /*
1630 +        * If the image sensor delivers blacklines, we cut them
1631 +        * away with moving wnd_blackline window by the given
1632 +        * amount of lines
1633 +        */
1634 +       switch (isi_config->bls) {
1635 +       /* no black lines */
1636 +       case SENSOR_BLS_OFF:
1637 +               break;
1638 +       /* two black lines at frame start */
1639 +       case SENSOR_BLS_TWO_LINES:
1640 +               wnd_blackline.voffs += 2;
1641 +               break;
1642 +       /* two black lines at frame start and two at the end */
1643 +       case SENSOR_BLS_FOUR_LINES:
1644 +               wnd_blackline.voffs += 2;
1645 +               break;
1646 +       default:
1647 +               eprintk("config");
1648 +               return CI_STATUS_NOTSUPP;
1649 +       }
1650 +       /*
1651 +        * if we are instructed to show the blacklines and the
1652 +        * sensor generates them,
1653 +        * we have to move the ISP windows to the upper border of
1654 +        * the whole sensor, and deny the image stabilization to
1655 +        * move around the window in vertical direction.
1656 +        */
1657 +       if (isi_config->bls != SENSOR_BLS_OFF) {
1658 +               if (((main_flag & CI_ISP_DPD_ENABLE)
1659 +                    && (main_flag & CI_ISP_DPD_BLACKLINES_TOP))
1660 +                   || ((self_flag & CI_ISP_DPD_ENABLE)
1661 +                       && (self_flag & CI_ISP_DPD_BLACKLINES_TOP))) {
1662 +                       if ((main_flag & CI_ISP_DPD_ENABLE)
1663 +                           && (self_flag & CI_ISP_DPD_ENABLE)
1664 +                           && ((main_flag & CI_ISP_DPD_BLACKLINES_TOP)
1665 +                               != (self_flag & CI_ISP_DPD_BLACKLINES_TOP))) {
1666 +                               eprintk("and self path");
1667 +                               return CI_STATUS_NOTSUPP;
1668 +                       }
1669 +                       wnd_blackline.voffs = 0;
1670 +                       wnd_zoom_crop.voffs = 0;
1671 +               }
1672 +       }
1673 +
1674 +       source.out_w = wnd_zoom_crop.hsize;
1675 +       source.out_h = wnd_zoom_crop.vsize;
1676 +       source.flags = CI_ISP_DPD_DMA_IN_422;
1677 +
1678 +       /*to use crop set crop_flag first*/
1679 +       if (crop_flag) {
1680 +               wnd_zoom_crop.hsize = main->out_w;
1681 +               wnd_zoom_crop.vsize = main->out_h;
1682 +       }
1683 +
1684 +       dprintk(1, "source.out_w %d, source.out_h %d",
1685 +               source.out_w, source.out_h);
1686 +       if (main)
1687 +               dprintk(1, "main.out_w %d, main.out_h %d",
1688 +                       main->out_w, main->out_h);
1689 +       if (self)
1690 +               dprintk(1, "self.out_w %d, self.out_h %d",
1691 +                       self->out_w, self->out_h);
1692 +
1693 +       /*
1694 +        * At this point, wnd_zoom_crop and wnd_blackline contain
1695 +        * the window sizes that reflect the users request. We have
1696 +        * to configure the ISP output formatter and the image
1697 +        * stabilization formatter in order to achieve this, but
1698 +        * how they interact is highly dependant of the curr
1699 +        * marvin derivative and which datapath of the ISP is
1700 +        * activated. Therefore, translating wnd_zoom_crop and
1701 +        * wnd_blackline into marvin register settings is a bit
1702 +        * complicated and will be done by the
1703 +        * ci_set_isp_windows() routine.
1704 +        */
1705 +
1706 +       /* ISP Window */
1707 +       /* MAIN path - fill in main_path, scale_main  and main_rsz_lut */
1708 +       /* basic selfpath settings */
1709 +       res = ci_calc_main_path_settings(&source, main, &scale_main,
1710 +                                        &mrv_mi_ctrl);
1711 +       if (res != CI_STATUS_SUCCESS)
1712 +               return res;
1713 +
1714 +       /* additional settings specific for main path fed from ISP */
1715 +       if (main_flag & CI_ISP_DPD_ENABLE) {
1716 +               switch (main_flag & CI_ISP_DPD_MODE_MASK) {
1717 +               case CI_ISP_DPD_MODE_ISPYC:
1718 +               case CI_ISP_DPD_MODE_ISPRAW:
1719 +               case CI_ISP_DPD_MODE_ISPRAW_16B:
1720 +               case CI_ISP_DPD_MODE_ISPJPEG:
1721 +                       /* allowed cases, just proceed */
1722 +                       break;
1723 +               default:
1724 +                       eprintk("data coming from the ISP");
1725 +                       return CI_STATUS_NOTSUPP;
1726 +               }
1727 +       }
1728 +
1729 +       /* SELF path - fill in self_path & scale_flag */
1730 +       /* basic selfpath settings */
1731 +       res = ci_calc_self_path_settings(&source, self, &scale_flag,
1732 +                                        &mrv_mi_ctrl);
1733 +       if (res != CI_STATUS_SUCCESS)
1734 +               return res;
1735 +
1736 +       if (sys_conf->isp_cfg.flags.ycbcr_non_cosited)
1737 +               mrv_mi_ctrl.mrv_mif_sp_in_phase = mrv_mif_col_phase_non_cosited;
1738 +       else
1739 +               mrv_mi_ctrl.mrv_mif_sp_in_phase = mrv_mif_col_phase_cosited;
1740 +       if (sys_conf->isp_cfg.flags.ycbcr_full_range)
1741 +               mrv_mi_ctrl.mrv_mif_sp_in_range = mrv_mif_col_range_full;
1742 +       else
1743 +               mrv_mi_ctrl.mrv_mif_sp_in_range = mrv_mif_col_range_std;
1744 +       if (self_flag & CI_ISP_DPD_ENABLE) {
1745 +               switch (self_flag & CI_ISP_DPD_MODE_MASK) {
1746 +               case CI_ISP_DPD_MODE_ISPYC:
1747 +                       /* only allowed case, just proceed */
1748 +                       break;
1749 +               default:
1750 +                       eprintk("data coming from the ISP");
1751 +                       return CI_STATUS_NOTSUPP;
1752 +               }
1753 +       }
1754 +
1755 +       /* Datapath multiplexers */
1756 +       res = ci_calc_dp_mux_settings(&mrv_mi_ctrl, &chn_mode, &dp_switch);
1757 +       if (res != CI_STATUS_SUCCESS)
1758 +               return res;
1759 +
1760 +       /* hardcoded global settings of the memory interface */
1761 +       mrv_mi_ctrl.byte_swap_enable = false;
1762 +
1763 +       mrv_mi_ctrl.init_vals = CI_ISP_MIF_INIT_OFFSAndBase;
1764 +
1765 +       /*
1766 +        * If we reach this point, we have collected all values to program
1767 +        * the MARVIN for the requested datapath setup. Now all we've left
1768 +        * to do is apply these to MARVINs register set. For this, we
1769 +        * mostly use the low level MARVIN driver routines.
1770 +        */
1771 +       /*to use crop set crop_flag first*/
1772 +       if (crop_flag) {
1773 +               wnd_blackline.hsize = main->out_w;
1774 +               wnd_blackline.vsize = main->out_h;
1775 +       }
1776 +
1777 +       res = ci_set_isp_windows(isi_config, &wnd_blackline,
1778 +                                &wnd_zoom_crop);
1779 +       if (res != CI_STATUS_SUCCESS) {
1780 +               eprintk("failed to set ISP window configuration");
1781 +               return res;
1782 +       }
1783 +       res = ci_isp_set_data_path(chn_mode, dp_switch);
1784 +       if (res != CI_STATUS_SUCCESS)
1785 +               return res;
1786 +
1787 +       res = ci_isp_set_mipi_smia(isi_config->mode);
1788 +       if (res != CI_STATUS_SUCCESS)
1789 +               return res;
1790 +
1791 +       if (mrv_mi_ctrl.self_path != CI_ISP_PATH_OFF)
1792 +               ci_isp_res_set_self_resize(&scale_flag,
1793 +                                          CI_ISP_CFG_UPDATE_IMMEDIATE,
1794 +                                          ci_get_rsz_lut(self_flag));
1795 +
1796 +       if (mrv_mi_ctrl.main_path != CI_ISP_PATH_OFF)
1797 +               ci_isp_res_set_main_resize(&scale_main,
1798 +                                          CI_ISP_CFG_UPDATE_IMMEDIATE,
1799 +                                          ci_get_rsz_lut(main_flag));
1800 +
1801 +       ci_isp_set_dma_read_mode(CI_ISP_DMA_RD_OFF,
1802 +               CI_ISP_CFG_UPDATE_IMMEDIATE);
1803 +
1804 +       res = ci_isp_mif_set_path_and_orientation(&mrv_mi_ctrl);
1805 +       if (res != CI_STATUS_SUCCESS) {
1806 +               eprintk("failed to set MI path and orientation");
1807 +               return res;
1808 +       }
1809 +
1810 +       /* here the extended YCbCr mode is configured */
1811 +       if (sys_conf->isp_cfg.flags.ycbcr_full_range)
1812 +               res = ci_ext_ycb_cr_mode(main);
1813 +       else
1814 +               (void)ci_isp_set_yc_mode();
1815 +
1816 +       if (res != CI_STATUS_SUCCESS) {
1817 +               eprintk("failed to set ISP YCbCr extended mode");
1818 +               return res;
1819 +       }
1820 +
1821 +       return CI_STATUS_SUCCESS;
1822 +}
1823 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c b/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c
1824 new file mode 100644
1825 index 0000000..56891c1
1826 --- /dev/null
1827 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c
1828 @@ -0,0 +1,1622 @@
1829 +/*
1830 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
1831 + *
1832 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
1833 + *
1834 + * Copyright (c) Silicon Image 2008  www.siliconimage.com
1835 + *
1836 + * This program is free software; you can redistribute it and/or
1837 + * modify it under the terms of the GNU General Public License version
1838 + * 2 as published by the Free Software Foundation.
1839 + *
1840 + * This program is distributed in the hope that it will be useful,
1841 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1842 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1843 + * GNU General Public License for more details.
1844 + *
1845 + * You should have received a copy of the GNU General Public License
1846 + * along with this program; if not, write to the Free Software
1847 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
1848 + * 02110-1301, USA.
1849 + *
1850 + *
1851 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
1852 + */
1853 +
1854 +#include "mrstisp_stdinc.h"
1855 +
1856 +static unsigned long jiffies_start;
1857 +
1858 +void mrst_timer_start(void)
1859 +{
1860 +       jiffies_start = jiffies;
1861 +}
1862 +
1863 +void mrst_timer_stop(void)
1864 +{
1865 +       jiffies_start = 0;
1866 +}
1867 +
1868 +unsigned long mrst_get_micro_sec(void)
1869 +{
1870 +       unsigned long time_diff = 0;
1871 +
1872 +       time_diff = jiffies - jiffies_start;
1873 +
1874 +       return jiffies_to_msecs(time_diff);
1875 +}
1876 +
1877 +/*
1878 + * Returns the ISP hardware ID.
1879 + */
1880 +static u32 ci_isp_get_ci_isp_id(void)
1881 +{
1882 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1883 +       u32 result = 0;
1884 +
1885 +       result = REG_GET_SLICE(mrv_reg->vi_id, MRV_REV_ID);
1886 +
1887 +       return result;
1888 +}
1889 +
1890 +/*
1891 + * Gets the hardware ID and compares it with the expected one.
1892 + */
1893 +static int ci_isp_verify_chip_id(void)
1894 +{
1895 +       u32 mrv_id = ci_isp_get_ci_isp_id();
1896 +       dprintk(1, "HW-Id: 0x%08X", mrv_id);
1897 +
1898 +       if (mrv_id != MARVIN_FEATURE_CHIP_ID) {
1899 +               eprintk("HW-Id does not match! read:0x%08X, expected:0x%08X",
1900 +                       mrv_id, MARVIN_FEATURE_CHIP_ID);
1901 +               return CI_STATUS_FAILURE;
1902 +       }
1903 +       return CI_STATUS_SUCCESS;
1904 +}
1905 +
1906 +/*
1907 + * Triggers an entire reset of MARVIN (equaling an asynchronous
1908 + * hardware reset).
1909 + * Checks the hardware ID. A debug warning is issued if the
1910 + * module ID does not match the expected ID.
1911 + * Enables all clocks of all sub-modules.
1912 + * MARVIN is in idle state afterwards.
1913 + */
1914 +void ci_isp_init(void)
1915 +{
1916 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1917 +
1918 +       /* verify ID, but no consequences if it doesn't match */
1919 +       (void)ci_isp_verify_chip_id();
1920 +
1921 +       /* enable main clock */
1922 +       REG_SET_SLICE(mrv_reg->vi_ccl, MRV_VI_CCLFDIS, MRV_VI_CCLFDIS_ENABLE);
1923 +
1924 +       /*
1925 +        * enable all clocks to make sure that all submodules will be able to
1926 +        * perform the reset correctly
1927 +        */
1928 +       REG_SET_SLICE(mrv_reg->vi_iccl, MRV_VI_ALL_CLK_ENABLE, ENABLE);
1929 +
1930 +       /*
1931 +        * Reset of the entire MARVIN triggered by software. The minimum time
1932 +        * permitted by mdelay ensures enough delay.
1933 +        */
1934 +
1935 +       /* The reset bit will be cleared by the reset itself. */
1936 +
1937 +       /*
1938 +        * The default value of the clock registers is all clocks on. So we
1939 +        * don't have to enable the clocks again afterwards.
1940 +        */
1941 +
1942 +       REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_MARVIN_RST, ON);
1943 +       /*mdelay(CI_ISP_DELAY_AFTER_RESET);*/
1944 +       msleep(CI_ISP_DELAY_AFTER_RESET);
1945 +}
1946 +
1947 +void ci_isp_off(void)
1948 +{
1949 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1950 +
1951 +       /* enable main clock */
1952 +       REG_SET_SLICE(mrv_reg->vi_ccl, MRV_VI_CCLFDIS,
1953 +                     MRV_VI_CCLFDIS_DISABLE);
1954 +
1955 +       /*
1956 +        * enable all clocks to make sure that all submodules will be able to
1957 +        * perform the reset correctly
1958 +        */
1959 +       REG_SET_SLICE(mrv_reg->vi_iccl, MRV_VI_ALL_CLK_ENABLE, DISABLE);
1960 +}
1961 +
1962 +/*
1963 + * Returns the mask for the frame end interrupts, which are
1964 + *             used for Isp.
1965 + */
1966 +u32 ci_isp_get_frame_end_irq_mask_isp(void)
1967 +{
1968 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1969 +
1970 +       switch (REG_GET_SLICE(mrv_reg->vi_dpcl, MRV_VI_DMA_SWITCH)) {
1971 +       /*
1972 +        * 2: path to image effects block (i.e. replacement for data coming
1973 +        * from the ISP)
1974 +        */
1975 +       case MRV_VI_DMA_SWITCH_IE:
1976 +               /* datapath is used by DMA */
1977 +               return 0;
1978 +       /*
1979 +        * 0: direct path to self path mux
1980 +        */
1981 +       case MRV_VI_DMA_SWITCH_SELF:
1982 +       /*
1983 +        * 1: path to superimpose block
1984 +        */
1985 +       case MRV_VI_DMA_SWITCH_SI:
1986 +       /*
1987 +        * 3: direct path to JPEG encoder (R2B-buffer-less encodein mode)
1988 +        */
1989 +       case MRV_VI_DMA_SWITCH_JPG:
1990 +       default:
1991 +               /* main and/or self path depends on the YC-splitter setting */
1992 +               {
1993 +                       switch (REG_GET_SLICE
1994 +                               (mrv_reg->vi_dpcl, MRV_VI_CHAN_MODE)) {
1995 +                       case MRV_VI_CHAN_MODE_MP:
1996 +                               return MRV_MI_MP_FRAME_END_MASK;
1997 +                       case MRV_VI_CHAN_MODE_SP:
1998 +                               return MRV_MI_SP_FRAME_END_MASK;
1999 +                       case MRV_VI_CHAN_MODE_MP_SP:
2000 +                               return MRV_MI_MP_FRAME_END_MASK |
2001 +                                   MRV_MI_SP_FRAME_END_MASK;
2002 +                       default:
2003 +                               return 0;
2004 +                       }
2005 +               }
2006 +       }
2007 +
2008 +}
2009 +
2010 +/*
2011 + * Programs the number of frames to capture. Clears frame end
2012 + * interrupt to allow waiting in ci_isp_wait_for_frame_end().
2013 + * Enables the ISP input acquisition and output formatter.
2014 + * If immediate=false, the hardware assures that enabling is
2015 + * done frame synchronously.
2016 + */
2017 +void ci_isp_start(u16 number_of_frames,
2018 +                 enum ci_isp_conf_update_time update_time)
2019 +{
2020 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2021 +       u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
2022 +       u32 eof_irq_mask = ci_isp_get_frame_end_irq_mask_isp();
2023 +
2024 +       /* max. 10 bits allowed */
2025 +       WARN_ON(!(number_of_frames <= MRV_ISP_ACQ_NR_FRAMES_MAX));
2026 +
2027 +       REG_SET_SLICE(mrv_reg->isp_acq_nr_frames, MRV_ISP_ACQ_NR_FRAMES,
2028 +                     number_of_frames);
2029 +
2030 +       /* clear frame end interrupt */
2031 +       REG_WRITE(mrv_reg->mi_icr, eof_irq_mask);
2032 +
2033 +       /* Enable ISP input Acquisition and output formatter. */
2034 +
2035 +       /*
2036 +        * Input Acquisition is always enabled synchronous to the image sensor
2037 +        * (no configuration update required). As soon as the input
2038 +        * acquisition is started bit in_enable_shd in the register
2039 +        * isp_flags_shd is set by hardware. In the following a frame end
2040 +        * recognized by the input acquisition unit leads to
2041 +        * ris_in_frame_end=1 in isp_ris. However a recognized frame end and
2042 +        * no signaled errors are no guarantee for a valid configuration.
2043 +        */
2044 +
2045 +       /*
2046 +        * The output formatter is enabled frame synchronously according to
2047 +        * the internal sync signals. Bit MRV_GEN_CFG_UPD has to be set. Bit
2048 +        * isp_on_shd in isp_flags_shd is set when the output formatter is
2049 +        * started. A recognized frame end is signaled with ris_out_frame_end
2050 +        * in isp_ris.
2051 +        */
2052 +
2053 +       /*
2054 +        * The configuration of the input acquisition and the output
2055 +        * formatter has to be correct to generate proper internal sync
2056 +        * signals and thus a proper frame-synchronous update signal.
2057 +        */
2058 +
2059 +       /* If the output formatter does not start check the following:
2060 +        * sync polarities
2061 +        * sample edge
2062 +        * mode in register isp_ctrl
2063 +        * sampling window of input acquisition <= picture size of image
2064 +        * sensor
2065 +        * output formatter window <= sampling window of input
2066 +        * acquisition
2067 +        */
2068 +
2069 +       /*
2070 +        * If problems with the window sizes are suspected preferably add some
2071 +        * offsets and reduce the window sizes, so that the above relations
2072 +        * are true by all means.
2073 +        */
2074 +
2075 +       switch (update_time) {
2076 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
2077 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ENABLE);
2078 +               break;
2079 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
2080 +               /*
2081 +                * MRV_ISP_ISP_CFG_UPD is used instead of
2082 +                * MRV_ISP_ISP_GEN_CFG_UPD. This updates the configuration
2083 +                * right away and MARVIN is ready to aquire the next incoming
2084 +                * frame.
2085 +                */
2086 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CFG_UPD, ENABLE);
2087 +               break;
2088 +       case CI_ISP_CFG_UPDATE_LATER:
2089 +               /* no update from within this function
2090 +                * but enable ISP and Input */
2091 +               break;
2092 +       default:
2093 +               break;
2094 +       }
2095 +
2096 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_INFORM_ENABLE, ENABLE);
2097 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_ENABLE, ENABLE);
2098 +       REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl);
2099 +
2100 +       dprintk(3, "ISP_CTRL  = 0x%08X", mrv_reg->isp_ctrl);
2101 +}
2102 +
2103 +/*
2104 + * Clear frame end interrupt to allow waiting in
2105 + * ci_isp_wait_for_frame_end(). Disable output formatter (frame
2106 + * synchronously).
2107 + */
2108 +void ci_isp_stop(enum ci_isp_conf_update_time update_time)
2109 +{
2110 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2111 +       u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
2112 +       u32 eof_irq_mask = ci_isp_get_frame_end_irq_mask_isp();
2113 +
2114 +       /* clear frame end interrupt */
2115 +       REG_WRITE(mrv_reg->mi_icr, eof_irq_mask);
2116 +       /* disable output formatter */
2117 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_ENABLE, DISABLE);
2118 +
2119 +       switch (update_time) {
2120 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
2121 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ENABLE);
2122 +               break;
2123 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
2124 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CFG_UPD, ENABLE);
2125 +               break;
2126 +       case CI_ISP_CFG_UPDATE_LATER:
2127 +               break;
2128 +       default:
2129 +               break;
2130 +       }
2131 +
2132 +       REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl);
2133 +}
2134 +
2135 +/*
2136 + * Changes the data path settings.
2137 + */
2138 +int ci_isp_set_data_path(enum ci_isp_ycs_chn_mode ycs_chn_mode,
2139 +                        enum ci_isp_dp_switch dp_switch)
2140 +{
2141 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2142 +       u32 vi_dpcl = REG_READ(mrv_reg->vi_dpcl);
2143 +       u32 vi_chan_mode;
2144 +       u32 vi_mp_mux;
2145 +
2146 +       /* get desired setting for ycs_chan_mode (or vi_chan_mode) bits */
2147 +       switch (ycs_chn_mode) {
2148 +       case CI_ISP_YCS_OFF:
2149 +               vi_chan_mode = MRV_VI_CHAN_MODE_OFF;
2150 +               break;
2151 +       case CI_ISP_YCS_Y:
2152 +               vi_chan_mode = MRV_VI_CHAN_MODE_Y;
2153 +               break;
2154 +       case CI_ISP_YCS_MVRaw:
2155 +               vi_chan_mode = MRV_VI_CHAN_MODE_MP_RAW;
2156 +               break;
2157 +       case CI_ISP_YCS_MV:
2158 +               vi_chan_mode = MRV_VI_CHAN_MODE_MP;
2159 +               break;
2160 +       case CI_ISP_YCS_SP:
2161 +               vi_chan_mode = MRV_VI_CHAN_MODE_SP;
2162 +               break;
2163 +       case CI_ISP_YCS_MV_SP:
2164 +               vi_chan_mode = MRV_VI_CHAN_MODE_MP_SP;
2165 +               break;
2166 +       default:
2167 +               eprintk("unknown value for ycs_chn_mode");
2168 +               return CI_STATUS_NOTSUPP;
2169 +       }
2170 +
2171 +       if (vi_chan_mode & ~(MRV_VI_CHAN_MODE_MASK >> MRV_VI_CHAN_MODE_SHIFT)) {
2172 +               eprintk("enum ci_isp_ycs_chn_mode not supported");
2173 +               return CI_STATUS_NOTSUPP;
2174 +       }
2175 +
2176 +       /* get desired setting for vi_dp_switch (or vi_dp_mux) bits */
2177 +       switch (dp_switch) {
2178 +       case CI_ISP_DP_RAW:
2179 +               vi_mp_mux = MRV_VI_MP_MUX_RAW;
2180 +               break;
2181 +       case CI_ISP_DP_JPEG:
2182 +               vi_mp_mux = MRV_VI_MP_MUX_JPEG;
2183 +               break;
2184 +       case CI_ISP_DP_MV:
2185 +               vi_mp_mux = MRV_VI_MP_MUX_MP;
2186 +               break;
2187 +       default:
2188 +               eprintk("unknown value for dp_switch");
2189 +               return CI_STATUS_NOTSUPP;
2190 +       }
2191 +
2192 +       if (vi_mp_mux & ~MRV_VI_MP_MUX_MASK) {
2193 +               eprintk("dp_switch value not supported");
2194 +               return CI_STATUS_NOTSUPP;
2195 +       }
2196 +
2197 +       /* program settings into MARVIN vi_dpcl register */
2198 +       REG_SET_SLICE(vi_dpcl, MRV_VI_CHAN_MODE, vi_chan_mode);
2199 +       REG_SET_SLICE(vi_dpcl, MRV_VI_MP_MUX, vi_mp_mux);
2200 +       REG_WRITE(mrv_reg->vi_dpcl, vi_dpcl);
2201 +
2202 +       return CI_STATUS_SUCCESS;
2203 +}
2204 +
2205 +/*
2206 + * Changes the data path settings to SMIA or MIPI.
2207 + */
2208 +int ci_isp_set_mipi_smia(u32 mode)
2209 +{
2210 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2211 +       u32 if_select;
2212 +
2213 +       /* get desired setting for if_select bits */
2214 +       switch (mode) {
2215 +       case SENSOR_MODE_SMIA:
2216 +               if_select = MRV_IF_SELECT_SMIA;
2217 +               break;
2218 +       case SENSOR_MODE_MIPI:
2219 +               if_select = MRV_IF_SELECT_MIPI;
2220 +               break;
2221 +       case SENSOR_MODE_BAYER:
2222 +       case SENSOR_MODE_BT601:
2223 +       case SENSOR_MODE_BT656:
2224 +       case SENSOR_MODE_PICT:
2225 +       case SENSOR_MODE_DATA:
2226 +       case SENSOR_MODE_BAY_BT656:
2227 +       case SENSOR_MODE_RAW_BT656:
2228 +               if_select = MRV_IF_SELECT_PAR;
2229 +               break;
2230 +       default:
2231 +               eprintk("unknown value for mode");
2232 +               return CI_STATUS_NOTSUPP;
2233 +       }
2234 +
2235 +       /* program settings into MARVIN vi_dpcl register */
2236 +       REG_SET_SLICE(mrv_reg->vi_dpcl, MRV_IF_SELECT, if_select);
2237 +
2238 +       if (if_select == MRV_IF_SELECT_MIPI) {
2239 +               REG_WRITE(mrv_reg->mipi_ctrl, 0x1001); /*XXX FLUSH_FIFO? */
2240 +               /* REG_WRITE(mrv_reg->mipi_ctrl, 0x0001); FLUSH_FIFO? */
2241 +       }
2242 +
2243 +       return CI_STATUS_SUCCESS;
2244 +}
2245 +
2246 +/*
2247 + * Waits until the specified bits becomes signaled in the mi_ris
2248 + * register.
2249 + */
2250 +static int ci_isp_wait_for_mi(struct mrst_isp_device *intel, u32 bit_mask)
2251 +{
2252 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2253 +#if 0
2254 +       int ret = 0;
2255 +       INIT_COMPLETION(intel->mi_complete);
2256 +       ret = wait_for_completion_interruptible_timeout(&intel->mi_complete,
2257 +                                                       10*HZ);
2258 +       if (ret == 0) {
2259 +               eprintk("time out in wait for mi");
2260 +               /*
2261 +                * Try to recover. Softreset of submodules (but not
2262 +                * entire marvin) resets processing and status
2263 +                * information, but not configuration register
2264 +                * content. Bits are sticky. So we have to clear them.
2265 +                * Reset affects the MARVIN 1..2 clock cycles after
2266 +                * the bits are set to high. So we don't have to wait
2267 +                * in software before clearing them.
2268 +                */
2269 +
2270 +               /*
2271 +                * Note that only modules with clock enabled will be
2272 +                * affected.
2273 +                */
2274 +               REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_ALL_SOFT_RST, ON);
2275 +               REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_ALL_SOFT_RST, OFF);
2276 +               mdelay(CI_ISP_DELAY_AFTER_RESET);
2277 +               /*
2278 +                * isp config update, neccessary to update v/h_size
2279 +                * into shadow registers
2280 +                */
2281 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_CFG_UPD, ON);
2282 +               return CI_STATUS_FAILURE;
2283 +       }
2284 +       return CI_STATUS_SUCCESS;
2285 +#endif
2286 +       u32 irq;
2287 +       static int err_frame_cnt;
2288 +       mrst_timer_start();
2289 +       /*
2290 +        * Wait for the curr BitMask. If the BitMask is zero, then it's no
2291 +        * waiting.
2292 +        */
2293 +       while ((mrv_reg->mi_ris & bit_mask) != bit_mask) {
2294 +
2295 +               irq = REG_READ(mrv_reg->isp_ris);
2296 +               if (irq & (MRV_ISP_RIS_DATA_LOSS_MASK
2297 +                          | MRV_ISP_RIS_PIC_SIZE_ERR_MASK)){
2298 +                       err_frame_cnt++;
2299 +                       dprintk(1, "irq = 0x%x, err rumber = %d", irq,
2300 +                               err_frame_cnt);
2301 +               }
2302 +               if (mrst_get_micro_sec() > 1000) {
2303 +                       /*
2304 +                        * Note: Don't use REG_READ because content of
2305 +                        * registers would be already printed here.
2306 +                        */
2307 +                       dprintk(1, "time out");
2308 +                       mrst_timer_stop();
2309 +                       /*
2310 +                        * Try to recover. Softreset of submodules (but not
2311 +                        * entire marvin) resets processing and status
2312 +                        * information, but not configuration register
2313 +                        * content. Bits are sticky. So we have to clear them.
2314 +                        * Reset affects the MARVIN 1..2 clock cycles after
2315 +                        * the bits are set to high. So we don't have to wait
2316 +                        * in software before clearing them.
2317 +                        */
2318 +
2319 +                       /*
2320 +                        * Note that only modules with clock enabled will be
2321 +                        * affected.
2322 +                        */
2323 +                       REG_SET_SLICE(mrv_reg->vi_ircl,
2324 +                                     MRV_VI_ALL_SOFT_RST, ON);
2325 +                       REG_SET_SLICE(mrv_reg->vi_ircl,
2326 +                                     MRV_VI_ALL_SOFT_RST, OFF);
2327 +                       /*mdelay(CI_ISP_DELAY_AFTER_RESET);*/
2328 +                       msleep(CI_ISP_DELAY_AFTER_RESET);
2329 +                       /*
2330 +                        * isp config update, neccessary to update v/h_size
2331 +                        * into shadow registers
2332 +                        */
2333 +                       REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_CFG_UPD,
2334 +                                     ON);
2335 +                       return CI_STATUS_FAILURE;
2336 +               }
2337 +       }
2338 +
2339 +       mrst_timer_stop();
2340 +       if (REG_GET_SLICE(mrv_reg->isp_ris, MRV_ISP_RIS_DATA_LOSS))
2341 +               dprintk(1, "no failure, but MRV_ISPINT_DATA_LOSS");
2342 +
2343 +       return CI_STATUS_SUCCESS;
2344 +}
2345 +
2346 +/*
2347 + * Waits until a frame is written to memory (frame end
2348 + * interrupt occurs).
2349 + * Waits for the frame end interrupt of the memory
2350 + * interface.
2351 + */
2352 +int ci_isp_wait_for_frame_end(struct mrst_isp_device *intel)
2353 +{
2354 +       return ci_isp_wait_for_mi(intel, ci_isp_get_frame_end_irq_mask_isp());
2355 +}
2356 +
2357 +/*
2358 + * Writes '0xFFFFFFFF' into all *_icr registers to clear all
2359 + * interrupts.
2360 + */
2361 +void ci_isp_reset_interrupt_status(void)
2362 +{
2363 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2364 +
2365 +       /* ISP interrupt clear register */
2366 +       REG_SET_SLICE(mrv_reg->isp_icr, MRV_ISP_ICR_ALL, ON);
2367 +       REG_SET_SLICE(mrv_reg->isp_err_clr, MRV_ISP_ALL_ERR, ON);
2368 +       REG_SET_SLICE(mrv_reg->mi_icr, MRV_MI_ALLIRQS, ON);
2369 +       /* JPEG error interrupt clear register */
2370 +       REG_SET_SLICE(mrv_reg->jpe_error_icr, MRV_JPE_ALL_ERR, ON);
2371 +       /* JPEG status interrupt clear register */
2372 +       REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ALL_STAT, ON);
2373 +
2374 +       REG_WRITE(mrv_reg->mipi_icr, 0xffffffff); /*XXX replace by a macro */
2375 +}
2376 +
2377 +void mrst_isp_disable_interrupt(struct mrst_isp_device *isp)
2378 +{
2379 +       struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE;
2380 +       REG_SET_SLICE(mrv_reg->isp_imsc, MRV_ISP_IMSC_ALL, OFF);
2381 +       REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_ALLIRQS, OFF);
2382 +       REG_SET_SLICE(mrv_reg->jpe_error_imr, MRV_JPE_ALL_ERR, OFF);
2383 +       REG_SET_SLICE(mrv_reg->jpe_status_imr, MRV_JPE_ALL_STAT, OFF);
2384 +       REG_WRITE(mrv_reg->mipi_imsc, 0x00000000);
2385 +}
2386 +
2387 +void mrst_isp_enable_interrupt(struct mrst_isp_device *isp)
2388 +{
2389 +       struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE;
2390 +
2391 +       REG_SET_SLICE(mrv_reg->isp_imsc, MRV_ISP_IMSC_DATA_LOSS, ON);
2392 +       REG_SET_SLICE(mrv_reg->isp_imsc, MRV_ISP_IMSC_PIC_SIZE_ERR, ON);
2393 +
2394 +       REG_WRITE(mrv_reg->mi_imsc, MRV_MI_MP_FRAME_END_MASK);
2395 +
2396 +       REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON);
2397 +
2398 +       REG_SET_SLICE(mrv_reg->jpe_error_imr, MRV_JPE_ALL_ERR, ON);
2399 +       REG_SET_SLICE(mrv_reg->jpe_status_imr, MRV_JPE_ALL_STAT, ON);
2400 +
2401 +       REG_WRITE(mrv_reg->mipi_imsc, 0x00f00000);
2402 +
2403 +       ci_isp_reset_interrupt_status();
2404 +}
2405 +
2406 +/*
2407 + * Selects DMA read mode (i.e. sink of the data read from  system
2408 + * memory by the DMA-read block).
2409 + * update_time is only used on Marvin3plus,
2410 + * on all other Marvin derivates immediate update is made
2411 + */
2412 +void ci_isp_set_dma_read_mode(enum ci_isp_dma_read_mode mode,
2413 +                             enum ci_isp_conf_update_time update_time)
2414 +{
2415 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2416 +       /* added to avoid LINT warnings (Info 530) */
2417 +       u32 vi_dma_switch = 0;
2418 +       /* added to avoid LINT warnings (Info 530) */
2419 +       u32 vi_dma_spmux = 0;
2420 +       /* added to avoid LINT warnings (Info 530) */
2421 +       u32 vi_dma_iemux = 0;
2422 +       /* added to avoid LINT warnings (Info 530) */
2423 +       int dma_jpeg_select = false;
2424 +
2425 +       u32 vi_dpcl = REG_READ(mrv_reg->vi_dpcl);
2426 +
2427 +       /*
2428 +        * DMA-read feature connected through a dedicated DMA-read
2429 +        * multiplexer.
2430 +        */
2431 +
2432 +       /* Programming is done via vi_dpcl register only */
2433 +#define DMA_READ_MODE_PROGRAMMING_VI_SPMCL 0
2434 +#define DMA_READ_MODE_PROGRAMMING_VI_DPCL  1
2435 +       WARN_ON(!((mode == CI_ISP_DMA_RD_OFF) ||
2436 +              (mode == CI_ISP_DMA_RD_SELF_PATH) ||
2437 +              (mode == CI_ISP_DMA_RD_IE_PATH) ||
2438 +              (mode == CI_ISP_DMA_RD_SUPERIMPOSE)));
2439 +
2440 +       switch (mode) {
2441 +       case CI_ISP_DMA_RD_OFF:
2442 +               vi_dma_switch = MRV_VI_DMA_SWITCH_SELF;
2443 +               vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM;
2444 +               vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM;
2445 +               dma_jpeg_select = false;
2446 +               break;
2447 +       case CI_ISP_DMA_RD_SELF_PATH:
2448 +               vi_dma_switch = MRV_VI_DMA_SWITCH_SELF;
2449 +               vi_dma_spmux = MRV_VI_DMA_SPMUX_DMA;
2450 +               vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM;
2451 +               dma_jpeg_select = false;
2452 +               break;
2453 +       case CI_ISP_DMA_RD_IE_PATH:
2454 +               vi_dma_switch = MRV_VI_DMA_SWITCH_IE;
2455 +               vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM;
2456 +               vi_dma_iemux = MRV_VI_DMA_IEMUX_DMA;
2457 +               dma_jpeg_select = false;
2458 +               break;
2459 +       case CI_ISP_DMA_RD_JPG_ENC:
2460 +               vi_dma_switch = MRV_VI_DMA_SWITCH_JPG;
2461 +               vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM;
2462 +               vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM;
2463 +               dma_jpeg_select = true;
2464 +               break;
2465 +       case CI_ISP_DMA_RD_SUPERIMPOSE:
2466 +               vi_dma_switch = MRV_VI_DMA_SWITCH_SI;
2467 +               vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM;
2468 +               vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM;
2469 +               dma_jpeg_select = false;
2470 +               break;
2471 +       default:
2472 +               /* unknown DMA-read mode */
2473 +               WARN_ON(1);
2474 +       }
2475 +
2476 +       REG_SET_SLICE(vi_dpcl, MRV_VI_DMA_SWITCH, vi_dma_switch);
2477 +       REG_SET_SLICE(vi_dpcl, MRV_VI_DMA_SPMUX, vi_dma_spmux);
2478 +       REG_SET_SLICE(vi_dpcl, MRV_VI_DMA_IEMUX, vi_dma_iemux);
2479 +#if ((MRV_VI_MP_MUX_JPGDIRECT & \
2480 +~(MRV_VI_MP_MUX_MASK >> MRV_VI_MP_MUX_SHIFT)) == 0)
2481 +       if (dma_jpeg_select) {
2482 +               REG_SET_SLICE(vi_dpcl, MRV_VI_MP_MUX,
2483 +                             MRV_VI_MP_MUX_JPGDIRECT);
2484 +       }
2485 +#else
2486 +       /* direct DMA to JPEG not supported */
2487 +       UNUSED_PARAM(dma_jpeg_select);
2488 +#endif
2489 +       REG_WRITE(mrv_reg->vi_dpcl, vi_dpcl);
2490 +}
2491 +
2492 +/*
2493 + * Set extended mode with unrestricted values for YCbCr
2494 + * Y (0-255) CbCr (0-255)
2495 + */
2496 +void ci_isp_set_ext_ycmode(void)
2497 +{
2498 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2499 +       u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
2500 +
2501 +       /* modify isp_ctrl register */
2502 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_C_RANGE,
2503 +                     MRV_ISP_ISP_CSM_C_RANGE_FULL);
2504 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_Y_RANGE,
2505 +                     MRV_ISP_ISP_CSM_Y_RANGE_FULL);
2506 +       REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl);
2507 +
2508 +       /* program RGB to YUV color conversion with extended range */
2509 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_0, MRV_ISP_CC_COEFF_0, 0x0026);
2510 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_1, MRV_ISP_CC_COEFF_1, 0x004B);
2511 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_2, MRV_ISP_CC_COEFF_2, 0x000F);
2512 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_3, MRV_ISP_CC_COEFF_3, 0x01EA);
2513 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_4, MRV_ISP_CC_COEFF_4, 0x01D6);
2514 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_5, MRV_ISP_CC_COEFF_5, 0x0040);
2515 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_6, MRV_ISP_CC_COEFF_6, 0x0040);
2516 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_7, MRV_ISP_CC_COEFF_7, 0x01CA);
2517 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_8, MRV_ISP_CC_COEFF_8, 0x01F6);
2518 +}
2519 +
2520 +void ci_isp_set_yc_mode(void)
2521 +{
2522 +       struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE;
2523 +       u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
2524 +
2525 +       /* modify isp_ctrl register */
2526 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_C_RANGE,
2527 +               MRV_ISP_ISP_CSM_Y_RANGE_BT601);
2528 +       REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_Y_RANGE,
2529 +               MRV_ISP_ISP_CSM_Y_RANGE_BT601);
2530 +       REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl);
2531 +
2532 +       /* program RGB to YUV color conversion with extended range */
2533 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_0, MRV_ISP_CC_COEFF_0, 0x0021);
2534 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_1, MRV_ISP_CC_COEFF_1, 0x0040);
2535 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_2, MRV_ISP_CC_COEFF_2, 0x000D);
2536 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_3, MRV_ISP_CC_COEFF_3, 0x01ED);
2537 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_4, MRV_ISP_CC_COEFF_4, 0x01DB);
2538 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_5, MRV_ISP_CC_COEFF_5, 0x0038);
2539 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_6, MRV_ISP_CC_COEFF_6, 0x0038);
2540 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_7, MRV_ISP_CC_COEFF_7, 0x01D1);
2541 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_8, MRV_ISP_CC_COEFF_8, 0x01F7);
2542 +}
2543 +
2544 +/*
2545 + * writes the color values for contrast, brightness,
2546 + * saturation and hue into the appropriate Marvin
2547 + * registers
2548 + */
2549 +void ci_isp_col_set_color_processing(
2550 +       const struct ci_isp_color_settings *col)
2551 +{
2552 +       struct isp_register *mrv_reg =
2553 +           (struct isp_register *) MEM_MRV_REG_BASE;
2554 +
2555 +       if (col == NULL) {
2556 +               /* disable color processing (bypass) */
2557 +               mrv_reg->c_proc_ctrl = 0;
2558 +       } else {
2559 +               mrv_reg->c_proc_contrast = col->contrast;
2560 +               mrv_reg->c_proc_brightness = col->brightness;
2561 +               mrv_reg->c_proc_saturation = col->saturation;
2562 +               mrv_reg->c_proc_hue = col->hue;
2563 +
2564 +               /* modify color processing registers */
2565 +
2566 +               if (col->flags & CI_ISP_CPROC_C_OUT_RANGE) {
2567 +                       mrv_reg->c_proc_ctrl =
2568 +                           mrv_reg->c_proc_ctrl | CI_ISP_CPROC_C_OUT_RANGE;
2569 +               }
2570 +
2571 +               if (col->flags & CI_ISP_CPROC_Y_IN_RANGE) {
2572 +                       mrv_reg->c_proc_ctrl =
2573 +                           mrv_reg->c_proc_ctrl | CI_ISP_CPROC_Y_IN_RANGE;
2574 +               }
2575 +
2576 +               if (col->flags & CI_ISP_CPROC_Y_OUT_RANGE) {
2577 +                       mrv_reg->c_proc_ctrl =
2578 +                           mrv_reg->c_proc_ctrl | CI_ISP_CPROC_Y_OUT_RANGE;
2579 +               }
2580 +
2581 +               if (col->flags & CI_ISP_CPROC_ENABLE) {
2582 +                       mrv_reg->c_proc_ctrl =
2583 +                           mrv_reg->c_proc_ctrl | CI_ISP_CPROC_ENABLE;
2584 +               }
2585 +       }
2586 +}
2587 +
2588 +/*
2589 + * Translates a chrominance component value from usual
2590 + * representation (range 16..240, 128=neutral grey)
2591 + * to the one used by the ie_tint register
2592 + * The value is returned as 32 bit unsigned to support shift
2593 + * operation without explicit cast.
2594 + * The translation formular implemented here is taken from
2595 + * the image effects functional specification document,
2596 + * Doc-ID 30-001-481.130, revision 1.1 from november, 21st. 2005
2597 + */
2598 +static u32 ci_isp_ie_tint_cx2_reg_val(u8 cx)
2599 +{
2600 +       s32 temp;
2601 +       u32 reg_val;
2602 +
2603 +       /*
2604 +        * apply scaling as specified in the image effects functional
2605 +        * specification
2606 +        */
2607 +       temp = 128 - (s32) cx;
2608 +       temp = ((temp * 64) / 110);
2609 +
2610 +       /* convert from two's complement to sign/value */
2611 +       if (temp < 0) {
2612 +               reg_val = 0x80;
2613 +               temp *= (-1);
2614 +       } else
2615 +               reg_val = 0;
2616 +
2617 +       /* saturate at 7 bits */
2618 +       if (temp > 0x7F)
2619 +               temp = 0x7F;
2620 +
2621 +       /* combine sign and value to build the regiter value */
2622 +       reg_val |= (u32) temp;
2623 +
2624 +       return reg_val;
2625 +}
2626 +
2627 +/*
2628 + * Translates usual (decimal) matrix coefficient into the
2629 + * 4 bit  register representation (used in the ie_mat_X registers).
2630 + * for unsupported decimal numbers, a supported replacement is
2631 + * selected automatically.
2632 + * The value is returned as 32 bit unsigned to support shift
2633 + * operation without explicit cast.
2634 + * The translation formular implemented here is taken from
2635 + * the image effects functional specification document,
2636 + * Doc-ID 30-001-481.130, revision 1.1 from november, 21st. 2005
2637 + */
2638 +static u32 ci_isp_ie_mx_dec2_reg_val(s8 dec)
2639 +{
2640 +       if (dec <= (-6)) {
2641 +               /* equivlent to -8 */
2642 +               return 0x0f;
2643 +       } else if (dec <= (-3)) {
2644 +               /* equivlent to -4 */
2645 +               return 0x0e;
2646 +       } else if (dec == (-2)) {
2647 +               /* equivlent to -2 */
2648 +               return 0x0d;
2649 +       } else if (dec == (-1)) {
2650 +               /* equivlent to -1 */
2651 +               return 0x0c;
2652 +       } else if (dec == 0) {
2653 +               /* equivlent to 0 (entry not used) */
2654 +               return 0x00;
2655 +       } else if (dec == 1) {
2656 +               /* equivlent to 1 */
2657 +               return 0x08;
2658 +       } else if (dec == 2) {
2659 +               /* equivlent to 2 */
2660 +               return 0x09;
2661 +       } else if (dec < 6) {
2662 +               /* equivlent to 4 */
2663 +               return 0x0a;
2664 +       } else {
2665 +               /* equivlent to 8 */
2666 +               return 0x0b;
2667 +       }
2668 +}
2669 +
2670 +/*
2671 + * translates the values of the given configuration
2672 + * structure into register settings for the image effects
2673 + * submodule and loads the registers.
2674 + */
2675 +int ci_isp_ie_set_config(const struct ci_isp_ie_config *ie_config)
2676 +{
2677 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2678 +
2679 +       if (!ie_config) {
2680 +               /* just disable the module, i.e. put it in bypass mode */
2681 +               REG_SET_SLICE(mrv_reg->img_eff_ctrl, MRV_IMGEFF_BYPASS_MODE,
2682 +                             MRV_IMGEFF_BYPASS_MODE_BYPASS);
2683 +       } else {
2684 +               /* apply the given settings */
2685 +               u32 ul_ie_ctrl = REG_READ(mrv_reg->img_eff_ctrl);
2686 +               u32 ul_ie_csel = REG_READ(mrv_reg->img_eff_color_sel);
2687 +               u32 ul_ie_tint = REG_READ(mrv_reg->img_eff_tint);
2688 +               u32 ul_ie_mat1 = REG_READ(mrv_reg->img_eff_mat_1);
2689 +               u32 ul_ie_mat2 = REG_READ(mrv_reg->img_eff_mat_2);
2690 +               u32 ul_ie_mat3 = REG_READ(mrv_reg->img_eff_mat_3);
2691 +               u32 ul_ie_mat4 = REG_READ(mrv_reg->img_eff_mat_4);
2692 +               u32 ul_ie_mat5 = REG_READ(mrv_reg->img_eff_mat_5);
2693 +
2694 +               /* overall operation mode */
2695 +               switch (ie_config->mode) {
2696 +               case CI_ISP_IE_MODE_OFF:
2697 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2698 +                                     MRV_IMGEFF_BYPASS_MODE_BYPASS);
2699 +                       break;
2700 +               case CI_ISP_IE_MODE_GRAYSCALE:
2701 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE,
2702 +                                     MRV_IMGEFF_EFFECT_MODE_GRAY);
2703 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2704 +                                     MRV_IMGEFF_BYPASS_MODE_PROCESS);
2705 +                       break;
2706 +               case CI_ISP_IE_MODE_NEGATIVE:
2707 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE,
2708 +                                     MRV_IMGEFF_EFFECT_MODE_NEGATIVE);
2709 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2710 +                                     MRV_IMGEFF_BYPASS_MODE_PROCESS);
2711 +                       break;
2712 +               case CI_ISP_IE_MODE_SEPIA:
2713 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE,
2714 +                                     MRV_IMGEFF_EFFECT_MODE_SEPIA);
2715 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2716 +                                     MRV_IMGEFF_BYPASS_MODE_PROCESS);
2717 +                       break;
2718 +               case CI_ISP_IE_MODE_COLOR_SEL:
2719 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE,
2720 +                                     MRV_IMGEFF_EFFECT_MODE_COLOR_SEL);
2721 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2722 +                                     MRV_IMGEFF_BYPASS_MODE_PROCESS);
2723 +                       break;
2724 +               case CI_ISP_IE_MODE_EMBOSS:
2725 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE,
2726 +                                     MRV_IMGEFF_EFFECT_MODE_EMBOSS);
2727 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2728 +                                     MRV_IMGEFF_BYPASS_MODE_PROCESS);
2729 +                       break;
2730 +               case CI_ISP_IE_MODE_SKETCH:
2731 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE,
2732 +                                     MRV_IMGEFF_EFFECT_MODE_SKETCH);
2733 +                       REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE,
2734 +                                     MRV_IMGEFF_BYPASS_MODE_PROCESS);
2735 +                       break;
2736 +               default:
2737 +                       return CI_STATUS_OUTOFRANGE;
2738 +               }
2739 +
2740 +               /* use next frame sync update */
2741 +               REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_CFG_UPD, ON);
2742 +
2743 +               /* color selection settings */
2744 +               REG_SET_SLICE(ul_ie_csel, MRV_IMGEFF_COLOR_THRESHOLD,
2745 +                             (u32) (ie_config->color_thres));
2746 +               REG_SET_SLICE(ul_ie_csel, MRV_IMGEFF_COLOR_SELECTION,
2747 +                             (u32) (ie_config->color_sel));
2748 +
2749 +               /* tint color settings */
2750 +               REG_SET_SLICE(ul_ie_tint, MRV_IMGEFF_INCR_CB,
2751 +                             ci_isp_ie_tint_cx2_reg_val(ie_config->tint_cb));
2752 +               REG_SET_SLICE(ul_ie_tint, MRV_IMGEFF_INCR_CR,
2753 +                             ci_isp_ie_tint_cx2_reg_val(ie_config->tint_cr));
2754 +
2755 +               /* matrix coefficients */
2756 +               REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_11_4,
2757 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2758 +                   coeff_11));
2759 +               REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_12_4,
2760 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2761 +                   coeff_12));
2762 +               REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_13_4,
2763 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2764 +                   coeff_13));
2765 +               REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_21_4,
2766 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2767 +                   coeff_21));
2768 +               REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_22_4,
2769 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2770 +                   coeff_22));
2771 +               REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_23_4,
2772 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2773 +                   coeff_23));
2774 +               REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_31_4,
2775 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2776 +                   coeff_31));
2777 +               REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_32_4,
2778 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2779 +                   coeff_32));
2780 +               REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_EMB_COEF_33_4,
2781 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss.
2782 +                   coeff_33));
2783 +               REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_SKET_COEF_11_4,
2784 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2785 +                   coeff_11));
2786 +               REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_SKET_COEF_12_4,
2787 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2788 +                   coeff_12));
2789 +               REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_SKET_COEF_13_4,
2790 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2791 +                   coeff_13));
2792 +               REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_21_4,
2793 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2794 +                   coeff_21));
2795 +               REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_22_4,
2796 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2797 +                   coeff_22));
2798 +               REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_23_4,
2799 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2800 +                   coeff_23));
2801 +               REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_31_4,
2802 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2803 +                   coeff_31));
2804 +               REG_SET_SLICE(ul_ie_mat5, MRV_IMGEFF_SKET_COEF_32_4,
2805 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2806 +                   coeff_32));
2807 +               REG_SET_SLICE(ul_ie_mat5, MRV_IMGEFF_SKET_COEF_33_4,
2808 +                   ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch.
2809 +                   coeff_33));
2810 +
2811 +               /* write changed values back to registers */
2812 +               REG_WRITE(mrv_reg->img_eff_ctrl, ul_ie_ctrl);
2813 +               REG_WRITE(mrv_reg->img_eff_color_sel, ul_ie_csel);
2814 +               REG_WRITE(mrv_reg->img_eff_tint, ul_ie_tint);
2815 +               REG_WRITE(mrv_reg->img_eff_mat_1, ul_ie_mat1);
2816 +               REG_WRITE(mrv_reg->img_eff_mat_2, ul_ie_mat2);
2817 +               REG_WRITE(mrv_reg->img_eff_mat_3, ul_ie_mat3);
2818 +               REG_WRITE(mrv_reg->img_eff_mat_4, ul_ie_mat4);
2819 +               REG_WRITE(mrv_reg->img_eff_mat_5, ul_ie_mat5);
2820 +
2821 +               /* frame synchronous update of shadow registers */
2822 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON);
2823 +       }
2824 +
2825 +       return CI_STATUS_SUCCESS;
2826 +}
2827 +
2828 +/*
2829 + * Applies the new image stabilisation settings to the module.
2830 + */
2831 +int ci_isp_is_set_config(const struct ci_isp_is_config *is_config)
2832 +{
2833 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2834 +
2835 +       if (!is_config) {
2836 +               eprintk("is_config NULL");
2837 +               return CI_STATUS_NULL_POINTER;
2838 +       }
2839 +
2840 +       /* set maximal margin distance for X */
2841 +       if (is_config->max_dx > MRV_IS_IS_MAX_DX_MAX) {
2842 +               REG_SET_SLICE(mrv_reg->isp_is_max_dx, MRV_IS_IS_MAX_DX,
2843 +                             (u32) (MRV_IS_IS_MAX_DX_MAX));
2844 +       } else {
2845 +               REG_SET_SLICE(mrv_reg->isp_is_max_dx, MRV_IS_IS_MAX_DX,
2846 +                             (u32) (is_config->max_dx));
2847 +       }
2848 +
2849 +       /* set maximal margin distance for Y */
2850 +       if (is_config->max_dy > MRV_IS_IS_MAX_DY_MAX) {
2851 +               REG_SET_SLICE(mrv_reg->isp_is_max_dy, MRV_IS_IS_MAX_DY,
2852 +                             (u32) (MRV_IS_IS_MAX_DY_MAX));
2853 +       } else {
2854 +               REG_SET_SLICE(mrv_reg->isp_is_max_dy, MRV_IS_IS_MAX_DY,
2855 +                             (u32) (is_config->max_dy));
2856 +       }
2857 +
2858 +       /* set H offset */
2859 +       REG_SET_SLICE(mrv_reg->isp_is_h_offs, MRV_IS_IS_H_OFFS,
2860 +                     (u32) (is_config->mrv_is_window.hoffs));
2861 +       /* set V offset */
2862 +       REG_SET_SLICE(mrv_reg->isp_is_v_offs, MRV_IS_IS_V_OFFS,
2863 +                     (u32) (is_config->mrv_is_window.voffs));
2864 +       /* set H size */
2865 +       REG_SET_SLICE(mrv_reg->isp_is_h_size, MRV_IS_IS_H_SIZE,
2866 +                     (u32) (is_config->mrv_is_window.hsize));
2867 +       /* set V size */
2868 +       REG_SET_SLICE(mrv_reg->isp_is_v_size, MRV_IS_IS_V_SIZE,
2869 +                     (u32) (is_config->mrv_is_window.vsize));
2870 +
2871 +       return CI_STATUS_SUCCESS;
2872 +}
2873 +
2874 +static int ci_isp_bls_set_fixed_values(const struct ci_isp_bls_subtraction
2875 +                                      *bls_subtraction)
2876 +{
2877 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2878 +
2879 +       if (!bls_subtraction)
2880 +               return CI_STATUS_NULL_POINTER;
2881 +
2882 +       if ((bls_subtraction->fixed_a > MRV_ISP_BLS_FIX_SUB_MAX) ||
2883 +           (bls_subtraction->fixed_b > MRV_ISP_BLS_FIX_SUB_MAX) ||
2884 +           (bls_subtraction->fixed_c > MRV_ISP_BLS_FIX_SUB_MAX) ||
2885 +           (bls_subtraction->fixed_d > MRV_ISP_BLS_FIX_SUB_MAX) ||
2886 +           (bls_subtraction->fixed_a < (s16) MRV_ISP_BLS_FIX_SUB_MIN) ||
2887 +           (bls_subtraction->fixed_b < (s16) MRV_ISP_BLS_FIX_SUB_MIN) ||
2888 +           (bls_subtraction->fixed_c < (s16) MRV_ISP_BLS_FIX_SUB_MIN) ||
2889 +           (bls_subtraction->fixed_d < (s16) MRV_ISP_BLS_FIX_SUB_MIN)) {
2890 +               return CI_STATUS_OUTOFRANGE;
2891 +       } else {
2892 +               /* we are in this path  */
2893 +               REG_SET_SLICE(mrv_reg->isp_bls_a_fixed, MRV_BLS_BLS_A_FIXED,
2894 +                             bls_subtraction->fixed_a);
2895 +               REG_SET_SLICE(mrv_reg->isp_bls_b_fixed, MRV_BLS_BLS_B_FIXED, \
2896 +                             bls_subtraction->fixed_b);
2897 +               REG_SET_SLICE(mrv_reg->isp_bls_c_fixed, MRV_BLS_BLS_C_FIXED,
2898 +                             bls_subtraction->fixed_c);
2899 +               REG_SET_SLICE(mrv_reg->isp_bls_d_fixed, MRV_BLS_BLS_D_FIXED,
2900 +                             bls_subtraction->fixed_d);
2901 +       }
2902 +
2903 +       return CI_STATUS_SUCCESS;
2904 +}
2905 +
2906 +/*
2907 + * Sets the desired configuration values to the BLS registers,
2908 + * if possible. In the case the parameter (bls_config == NULL)
2909 + * the BLS module will be deactivated.
2910 + */
2911 +int ci_isp_bls_set_config(const struct ci_isp_bls_config *bls_config)
2912 +{
2913 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2914 +       u32 isp_bls_ctrl = 0;
2915 +
2916 +       int error = CI_STATUS_FAILURE;
2917 +
2918 +       if (!bls_config) {
2919 +               /* disable the BLS module */
2920 +               REG_SET_SLICE(mrv_reg->isp_bls_ctrl,
2921 +                       MRV_BLS_BLS_ENABLE, DISABLE);
2922 +               return CI_STATUS_SUCCESS;
2923 +       }
2924 +
2925 +       /* measurement window 2, enable_window =0 */
2926 +       if (bls_config->isp_bls_window2.enable_window) {
2927 +               if ((bls_config->isp_bls_window2.start_h >
2928 +                    MRV_BLS_BLS_H2_START_MAX)
2929 +                   || (bls_config->isp_bls_window2.stop_h >
2930 +                       MRV_BLS_BLS_H2_STOP_MAX)
2931 +                   || (bls_config->isp_bls_window2.start_v >
2932 +                       MRV_BLS_BLS_V2_START_MAX)
2933 +                   || (bls_config->isp_bls_window2.stop_v >
2934 +                       MRV_BLS_BLS_V2_STOP_MAX)) {
2935 +                       return CI_STATUS_OUTOFRANGE;
2936 +               } else {
2937 +                       REG_SET_SLICE(mrv_reg->isp_bls_h2_start,
2938 +                                     MRV_BLS_BLS_H2_START,
2939 +                                     bls_config->isp_bls_window2.start_h);
2940 +                       REG_SET_SLICE(mrv_reg->isp_bls_h2_stop,
2941 +                                     MRV_BLS_BLS_H2_STOP,
2942 +                                     bls_config->isp_bls_window2.stop_h);
2943 +                       REG_SET_SLICE(mrv_reg->isp_bls_v2_start,
2944 +                                     MRV_BLS_BLS_V2_START,
2945 +                                     bls_config->isp_bls_window2.start_v);
2946 +                       REG_SET_SLICE(mrv_reg->isp_bls_v2_stop,
2947 +                                     MRV_BLS_BLS_V2_STOP,
2948 +                                     bls_config->isp_bls_window2.stop_v);
2949 +               }
2950 +       }
2951 +
2952 +       /* measurement window 1, enable_window=0 */
2953 +       if (bls_config->isp_bls_window1.enable_window) {
2954 +               if ((bls_config->isp_bls_window1.start_h >
2955 +                    MRV_BLS_BLS_H1_START_MAX)
2956 +                   || (bls_config->isp_bls_window1.stop_h >
2957 +                       MRV_BLS_BLS_H1_STOP_MAX)
2958 +                   || (bls_config->isp_bls_window1.start_v >
2959 +                       MRV_BLS_BLS_V1_START_MAX)
2960 +                   || (bls_config->isp_bls_window1.stop_v >
2961 +                       MRV_BLS_BLS_V1_STOP_MAX)) {
2962 +                       return CI_STATUS_OUTOFRANGE;
2963 +               } else {
2964 +                       REG_SET_SLICE(mrv_reg->isp_bls_h1_start,
2965 +                                     MRV_BLS_BLS_H1_START,
2966 +                                     bls_config->isp_bls_window1.start_h);
2967 +                       REG_SET_SLICE(mrv_reg->isp_bls_h1_stop,
2968 +                                     MRV_BLS_BLS_H1_STOP,
2969 +                                     bls_config->isp_bls_window1.stop_h);
2970 +                       REG_SET_SLICE(mrv_reg->isp_bls_v1_start,
2971 +                                     MRV_BLS_BLS_V1_START,
2972 +                                     bls_config->isp_bls_window1.start_v);
2973 +                       REG_SET_SLICE(mrv_reg->isp_bls_v1_stop,
2974 +                                     MRV_BLS_BLS_V1_STOP,
2975 +                                     bls_config->isp_bls_window1.stop_v);
2976 +               }
2977 +       }
2978 +
2979 +       if (bls_config->bls_samples > MRV_BLS_BLS_SAMPLES_MAX) {
2980 +               return CI_STATUS_OUTOFRANGE;
2981 +       } else {
2982 +               REG_SET_SLICE(mrv_reg->isp_bls_samples, MRV_BLS_BLS_SAMPLES,
2983 +                             bls_config->bls_samples);
2984 +       }
2985 +
2986 +       /* fixed subtraction values, enable_automatic=0 */
2987 +       if (!bls_config->enable_automatic) {
2988 +               error = ci_isp_bls_set_fixed_values(
2989 +                   &(bls_config->bls_subtraction));
2990 +               if (error != CI_STATUS_SUCCESS)
2991 +                       return error;
2992 +       }
2993 +
2994 +       if ((bls_config->disable_h) || (bls_config->disable_v))
2995 +               return CI_STATUS_OUTOFRANGE;
2996 +
2997 +       isp_bls_ctrl = REG_READ(mrv_reg->isp_bls_ctrl);
2998 +
2999 +       /* enable measurement window(s) */
3000 +       REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_WINDOW_ENABLE,
3001 +                     ((bls_config->isp_bls_window1.enable_window)
3002 +                     ? MRV_BLS_WINDOW_ENABLE_WND1 : 0) |
3003 +                     ((bls_config->isp_bls_window2.enable_window)
3004 +                     ? MRV_BLS_WINDOW_ENABLE_WND2 : 0));
3005 +
3006 +       /* set Mode */
3007 +       REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_BLS_MODE,
3008 +                     (bls_config->enable_automatic) ? MRV_BLS_BLS_MODE_MEAS :
3009 +                     MRV_BLS_BLS_MODE_FIX);
3010 +
3011 +       /* enable module */
3012 +       REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_BLS_ENABLE, ENABLE);
3013 +
3014 +       /* write into register */
3015 +       REG_WRITE(mrv_reg->isp_bls_ctrl, isp_bls_ctrl);
3016 +
3017 +       return CI_STATUS_SUCCESS;
3018 +}
3019 +
3020 +#define RSZ_FLAGS_MASK (RSZ_UPSCALE_ENABLE | RSZ_SCALER_BYPASS)
3021 +
3022 +/*
3023 + * writes the scaler values to the appropriate Marvin registers.
3024 + */
3025 +void ci_isp_res_set_main_resize(const struct ci_isp_scale *scale,
3026 +                               enum ci_isp_conf_update_time update_time,
3027 +                               const struct ci_isp_rsz_lut *rsz_lut)
3028 +{
3029 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
3030 +       u32 mrsz_ctrl = REG_READ(mrv_reg->mrsz_ctrl);
3031 +       u32 i;
3032 +       int upscaling = false;
3033 +
3034 +       /* flags must be "outside" scaler value */
3035 +       WARN_ON(!((RSZ_FLAGS_MASK & MRV_RSZ_SCALE_MASK) == 0));
3036 +       WARN_ON(!((scale->scale_hy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3037 +       WARN_ON(!((scale->scale_hcb & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3038 +       WARN_ON(!((scale->scale_hcr & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3039 +       WARN_ON(!((scale->scale_vy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3040 +       WARN_ON(!((scale->scale_vc & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3041 +
3042 +       /* horizontal luminance scale factor */
3043 +       dprintk(1, "scale_hy = %d( %x )", scale->scale_hy, scale->scale_hy);
3044 +
3045 +       if (scale->scale_hy & RSZ_SCALER_BYPASS) {
3046 +               /* disable (bypass) scaler */
3047 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_ENABLE, DISABLE);
3048 +       } else {
3049 +               /* enable scaler */
3050 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_ENABLE, ENABLE);
3051 +               /* program scale factor and phase */
3052 +               REG_SET_SLICE(mrv_reg->mrsz_scale_hy, MRV_MRSZ_SCALE_HY,
3053 +                             (u32) scale->scale_hy);
3054 +               REG_SET_SLICE(mrv_reg->mrsz_phase_hy, MRV_MRSZ_PHASE_HY,
3055 +                             (u32) scale->phase_hy);
3056 +
3057 +               if (scale->scale_hy & RSZ_UPSCALE_ENABLE) {
3058 +                       /* enable upscaling mode */
3059 +                       dprintk(1, "enable up scale");
3060 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_UP,
3061 +                                     MRV_MRSZ_SCALE_HY_UP_UPSCALE);
3062 +                       /* scaler and upscaling enabled */
3063 +                       upscaling = true;
3064 +               } else
3065 +                       /* disable upscaling mode */
3066 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_UP,
3067 +                                     MRV_MRSZ_SCALE_HY_UP_DOWNSCALE);
3068 +       }
3069 +
3070 +       /* horizontal chrominance scale factors */
3071 +       WARN_ON(!((scale->scale_hcb & RSZ_FLAGS_MASK) == (scale->scale_hcr &
3072 +                                                         RSZ_FLAGS_MASK)));
3073 +       dprintk(1, "scale_hcb  = %d( %x )", scale->scale_hcb, scale->scale_hcb);
3074 +
3075 +       if (scale->scale_hcb & RSZ_SCALER_BYPASS) {
3076 +               /* disable (bypass) scaler */
3077 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_ENABLE, DISABLE);
3078 +       } else {
3079 +               /* enable scaler */
3080 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_ENABLE, ENABLE);
3081 +               /* program scale factor and phase */
3082 +               REG_SET_SLICE(mrv_reg->mrsz_scale_hcb, MRV_MRSZ_SCALE_HCB,
3083 +                             (u32) scale->scale_hcb);
3084 +               REG_SET_SLICE(mrv_reg->mrsz_scale_hcr, MRV_MRSZ_SCALE_HCB,
3085 +                             (u32) scale->scale_hcr);
3086 +               REG_SET_SLICE(mrv_reg->mrsz_phase_hc, MRV_MRSZ_PHASE_HC,
3087 +                             (u32) scale->phase_hc);
3088 +
3089 +               if (scale->scale_hcb & RSZ_UPSCALE_ENABLE) {
3090 +                       /* enable upscaling mode */
3091 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_UP,
3092 +                                     MRV_MRSZ_SCALE_HC_UP_UPSCALE);
3093 +                       /* scaler and upscaling enabled */
3094 +                       upscaling = true;
3095 +               } else {
3096 +                       /* disable upscaling mode */
3097 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_UP,
3098 +                                     MRV_MRSZ_SCALE_HC_UP_DOWNSCALE);
3099 +               }
3100 +       }
3101 +
3102 +       /* vertical luminance scale factor */
3103 +       dprintk(1, "scale_vy = %d ( %x )", scale->scale_vy, scale->scale_vy);
3104 +
3105 +       if (scale->scale_vy & RSZ_SCALER_BYPASS) {
3106 +               /* disable (bypass) scaler */
3107 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_ENABLE,
3108 +                             DISABLE);
3109 +       } else {
3110 +               /* enable scaler */
3111 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_ENABLE, ENABLE);
3112 +               /* program scale factor and phase */
3113 +               REG_SET_SLICE(mrv_reg->mrsz_scale_vy, MRV_MRSZ_SCALE_VY,
3114 +                   (u32) scale->scale_vy);
3115 +               REG_SET_SLICE(mrv_reg->mrsz_phase_vy, MRV_MRSZ_PHASE_VY,
3116 +                   (u32) scale->phase_vy);
3117 +
3118 +               if (scale->scale_vy & RSZ_UPSCALE_ENABLE) {
3119 +                       /* enable upscaling mode */
3120 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_UP,
3121 +                                     MRV_MRSZ_SCALE_VY_UP_UPSCALE);
3122 +                       /* scaler and upscaling enabled */
3123 +                       upscaling = true;
3124 +               } else {
3125 +                       /* disable upscaling mode */
3126 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_UP,
3127 +                                     MRV_MRSZ_SCALE_VY_UP_DOWNSCALE);
3128 +               }
3129 +       }
3130 +
3131 +       /* vertical chrominance scale factor */
3132 +       dprintk(1, "scale_vc = %d( %x )", scale->scale_vc, scale->scale_vc);
3133 +
3134 +       if (scale->scale_vc & RSZ_SCALER_BYPASS) {
3135 +               /* disable (bypass) scaler */
3136 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_ENABLE,
3137 +                             DISABLE);
3138 +       } else {
3139 +               /* enable scaler */
3140 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_ENABLE, ENABLE);
3141 +               /* program scale factor and phase */
3142 +               REG_SET_SLICE(mrv_reg->mrsz_scale_vc, MRV_MRSZ_SCALE_VC,
3143 +                             (u32) scale->scale_vc);
3144 +               REG_SET_SLICE(mrv_reg->mrsz_phase_vc, MRV_MRSZ_PHASE_VC,
3145 +                             (u32) scale->phase_vc);
3146 +
3147 +               if (scale->scale_vc & RSZ_UPSCALE_ENABLE) {
3148 +                       /* enable upscaling mode */
3149 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_UP,
3150 +                                     MRV_MRSZ_SCALE_VC_UP_UPSCALE);
3151 +                       /* scaler and upscaling enabled */
3152 +                       upscaling = true;
3153 +               } else {
3154 +                       /* disable upscaling mode */
3155 +                       REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_UP,
3156 +                                     MRV_MRSZ_SCALE_VC_UP_DOWNSCALE);
3157 +               }
3158 +       }
3159 +
3160 +       /* apply upscaling lookup table */
3161 +       if (rsz_lut) {
3162 +               for (i = 0; i <= MRV_MRSZ_SCALE_LUT_ADDR_MASK; i++) {
3163 +                       REG_SET_SLICE(mrv_reg->mrsz_scale_lut_addr,
3164 +                                     MRV_MRSZ_SCALE_LUT_ADDR, i);
3165 +                       REG_SET_SLICE(mrv_reg->mrsz_scale_lut,
3166 +                                     MRV_MRSZ_SCALE_LUT,
3167 +                                     rsz_lut->rsz_lut[i]);
3168 +               }
3169 +       } else if (upscaling) {
3170 +               eprintk("Upscaling requires lookup table!");
3171 +               WARN_ON(1);
3172 +       }
3173 +
3174 +       /* handle immediate update flag and write mrsz_ctrl */
3175 +       switch (update_time) {
3176 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
3177 +               /* frame synchronous update of shadow registers */
3178 +               REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl);
3179 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON);
3180 +               break;
3181 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
3182 +               /* immediate update of shadow registers */
3183 +               REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_CFG_UPD, ON);
3184 +               REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl);
3185 +               break;
3186 +       case CI_ISP_CFG_UPDATE_LATER:
3187 +       default:
3188 +               /* no update from within this function */
3189 +               REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl);
3190 +               break;
3191 +       }
3192 +}
3193 +
3194 +/*
3195 + * writes the scaler values to the appropriate Marvin registers.
3196 + */
3197 +void ci_isp_res_set_self_resize(const struct ci_isp_scale *scale,
3198 +                               enum ci_isp_conf_update_time update_time,
3199 +                               const struct ci_isp_rsz_lut *rsz_lut)
3200 +{
3201 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
3202 +       u32 srsz_ctrl = REG_READ(mrv_reg->srsz_ctrl);
3203 +       u32 i;
3204 +       int upscaling = false;
3205 +
3206 +       /* flags must be "outside" scaler value */
3207 +       WARN_ON(!((RSZ_FLAGS_MASK & MRV_RSZ_SCALE_MASK) == 0));
3208 +       WARN_ON(!((scale->scale_hy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3209 +       WARN_ON(!((scale->scale_hcb & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3210 +       WARN_ON(!((scale->scale_hcr & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3211 +       WARN_ON(!((scale->scale_vy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3212 +       WARN_ON(!((scale->scale_vc & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX));
3213 +
3214 +       /* horizontal luminance scale factor */
3215 +       dprintk(1, "scale_hy = %d,%x", scale->scale_hy, scale->scale_hy);
3216 +
3217 +       if (scale->scale_hy & RSZ_SCALER_BYPASS) {
3218 +               /* disable (bypass) scaler */
3219 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_ENABLE,
3220 +                             DISABLE);
3221 +       } else {
3222 +               /* enable scaler */
3223 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_ENABLE, ENABLE);
3224 +               /* program scale factor and phase */
3225 +               REG_SET_SLICE(mrv_reg->srsz_scale_hy, MRV_SRSZ_SCALE_HY,
3226 +                             (u32) scale->scale_hy);
3227 +               REG_SET_SLICE(mrv_reg->srsz_phase_hy, MRV_SRSZ_PHASE_HY,
3228 +                             (u32) scale->phase_hy);
3229 +
3230 +               if (scale->scale_hy & RSZ_UPSCALE_ENABLE) {
3231 +                       /* enable upscaling mode */
3232 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_UP,
3233 +                                     MRV_SRSZ_SCALE_HY_UP_UPSCALE);
3234 +                       /* scaler and upscaling enabled */
3235 +                       upscaling = true;
3236 +               } else {
3237 +                       /* disable upscaling mode */
3238 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_UP,
3239 +                                     MRV_SRSZ_SCALE_HY_UP_DOWNSCALE);
3240 +               }
3241 +       }
3242 +
3243 +       /* horizontal chrominance scale factors */
3244 +       WARN_ON(!((scale->scale_hcb & RSZ_FLAGS_MASK) == (scale->scale_hcr &
3245 +                                                         RSZ_FLAGS_MASK)));
3246 +
3247 +       dprintk(1, "scale_hcb  = %d,%x", scale->scale_hcb, scale->scale_hcb);
3248 +
3249 +       if (scale->scale_hcb & RSZ_SCALER_BYPASS) {
3250 +               /* disable (bypass) scaler */
3251 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_ENABLE,
3252 +                             DISABLE);
3253 +       } else {
3254 +               /* enable scaler */
3255 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_ENABLE, ENABLE);
3256 +               /* program scale factor and phase */
3257 +               REG_SET_SLICE(mrv_reg->srsz_scale_hcb, MRV_SRSZ_SCALE_HCB,
3258 +                             (u32) scale->scale_hcb);
3259 +               REG_SET_SLICE(mrv_reg->srsz_scale_hcr, MRV_SRSZ_SCALE_HCB,
3260 +                             (u32) scale->scale_hcr);
3261 +
3262 +               REG_SET_SLICE(mrv_reg->srsz_phase_hc, MRV_SRSZ_PHASE_HC,
3263 +                   (u32) scale->phase_hc);
3264 +
3265 +               if (scale->scale_hcb & RSZ_UPSCALE_ENABLE) {
3266 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_UP,
3267 +                                     MRV_SRSZ_SCALE_HC_UP_UPSCALE);
3268 +                       /* scaler and upscaling enabled */
3269 +                       upscaling = true;
3270 +               } else {
3271 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_UP,
3272 +                                     MRV_SRSZ_SCALE_HC_UP_DOWNSCALE);
3273 +               }
3274 +       }
3275 +
3276 +       /* vertical luminance scale factor */
3277 +       dprintk(1, "scale_vy = %d,%x", scale->scale_vy, scale->scale_vy);
3278 +
3279 +       if (scale->scale_vy & RSZ_SCALER_BYPASS) {
3280 +               /* disable (bypass) scaler */
3281 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_ENABLE,
3282 +                             DISABLE);
3283 +       } else {
3284 +               /* enable scaler */
3285 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_ENABLE, ENABLE);
3286 +               /* program scale factor and phase */
3287 +               REG_SET_SLICE(mrv_reg->srsz_scale_vy, MRV_SRSZ_SCALE_VY,
3288 +                             (u32) scale->scale_vy);
3289 +               REG_SET_SLICE(mrv_reg->srsz_phase_vy, MRV_SRSZ_PHASE_VY,
3290 +                             (u32) scale->phase_vy);
3291 +
3292 +               if (scale->scale_vy & RSZ_UPSCALE_ENABLE) {
3293 +                       /* enable upscaling mode */
3294 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_UP,
3295 +                                     MRV_SRSZ_SCALE_VY_UP_UPSCALE);
3296 +                       /* scaler and upscaling enabled */
3297 +                       upscaling = true;
3298 +               } else {
3299 +                       /* disable upscaling mode */
3300 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_UP,
3301 +                                     MRV_SRSZ_SCALE_VY_UP_DOWNSCALE);
3302 +               }
3303 +       }
3304 +
3305 +       /* vertical chrominance scale factor */
3306 +       dprintk(1, "scale_vc = %d,%x", scale->scale_vc, scale->scale_vc);
3307 +
3308 +       if (scale->scale_vc & RSZ_SCALER_BYPASS) {
3309 +               /* disable (bypass) scaler */
3310 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_ENABLE,
3311 +                             DISABLE);
3312 +       } else {
3313 +               /* enable scaler */
3314 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_ENABLE, ENABLE);
3315 +               /* program scale factor and phase */
3316 +               REG_SET_SLICE(mrv_reg->srsz_scale_vc, MRV_SRSZ_SCALE_VC,
3317 +                             (u32) scale->scale_vc);
3318 +               REG_SET_SLICE(mrv_reg->srsz_phase_vc, MRV_SRSZ_PHASE_VC,
3319 +                             (u32) scale->phase_vc);
3320 +
3321 +               if (scale->scale_vc & RSZ_UPSCALE_ENABLE) {
3322 +                       /* enable upscaling mode */
3323 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_UP,
3324 +                                     MRV_SRSZ_SCALE_VC_UP_UPSCALE);
3325 +                       /* scaler and upscaling enabled */
3326 +                       upscaling = true;
3327 +               } else {
3328 +                       /* disable upscaling mode */
3329 +                       REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_UP,
3330 +                                     MRV_SRSZ_SCALE_VC_UP_DOWNSCALE);
3331 +               }
3332 +       }
3333 +
3334 +       /* apply upscaling lookup table */
3335 +       if (rsz_lut) {
3336 +               for (i = 0; i <= MRV_SRSZ_SCALE_LUT_ADDR_MASK; i++) {
3337 +                       REG_SET_SLICE(mrv_reg->srsz_scale_lut_addr,
3338 +                                     MRV_SRSZ_SCALE_LUT_ADDR, i);
3339 +                       REG_SET_SLICE(mrv_reg->srsz_scale_lut,
3340 +                                     MRV_SRSZ_SCALE_LUT,
3341 +                                     rsz_lut->rsz_lut[i]);
3342 +               }
3343 +       } else if (upscaling) {
3344 +               eprintk("Upscaling requires lookup table!");
3345 +               WARN_ON(1);
3346 +       }
3347 +
3348 +       /* handle immediate update flag and write mrsz_ctrl */
3349 +       switch (update_time) {
3350 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
3351 +               /* frame synchronous update of shadow registers */
3352 +               REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl);
3353 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD,
3354 +                             ON);
3355 +               break;
3356 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
3357 +               /* immediate update of shadow registers */
3358 +               REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_CFG_UPD, ON);
3359 +               REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl);
3360 +               break;
3361 +       case CI_ISP_CFG_UPDATE_LATER:
3362 +       default:
3363 +               /* no update from within this function */
3364 +               REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl);
3365 +               break;
3366 +       }
3367 +}
3368 +
3369 +#if MRV_SUPPORT_SL
3370 +
3371 +/* bad pixel table */
3372 +static struct ci_sensor_bp_table bp_table = { 0 };
3373 +
3374 +/*
3375 + * Initialization of the Bad Pixel Detection and Correction.
3376 + */
3377 +int ci_bp_init(const struct ci_isp_bp_corr_config *bp_corr_config,
3378 +              const struct ci_isp_bp_det_config *bp_det_config)
3379 +{
3380 +       int error = CI_STATUS_SUCCESS;
3381 +
3382 +       /* number of table elements */
3383 +       /* number of table elements */
3384 +#define MRVSLS_BPINIT_MAX_TABLE 2048
3385 +
3386 +       /* check the parameters */
3387 +       if (!bp_corr_config || !bp_det_config)
3388 +               return CI_STATUS_NULL_POINTER;
3389 +
3390 +       if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_TABLE) {
3391 +               /* set badpixel correction */
3392 +               error |= ci_isp_set_bp_correction(bp_corr_config);
3393 +               /* set badpixel detection */
3394 +               error |= ci_isp_set_bp_detection(bp_det_config);
3395 +               /* zero element inside */
3396 +               bp_table.bp_number = 0;
3397 +               if (!bp_table.bp_table_elem) {
3398 +                       /* allocate mem space for the table */
3399 +                       bp_table.bp_table_elem =
3400 +                           (struct ci_sensor_bp_table_elem *)
3401 +                           kmalloc((sizeof(struct ci_sensor_bp_table_elem)*
3402 +                                    MRVSLS_BPINIT_MAX_TABLE), GFP_KERNEL);
3403 +                       if (!bp_table.bp_table_elem)
3404 +                               error |= CI_STATUS_FAILURE;
3405 +               }
3406 +               /* max count of elements */
3407 +               bp_table.bp_table_elem_num = MRVSLS_BPINIT_MAX_TABLE;
3408 +               /* Clear Interrupt Status */
3409 +               error |= ci_isp_clear_bp_int();
3410 +       } else {
3411 +               if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_DIRECT) {
3412 +                       /* set badpixel correction */
3413 +                       error |= ci_isp_set_bp_correction(bp_corr_config);
3414 +                       /* set badpixel detection */
3415 +                       error |= ci_isp_set_bp_detection(NULL);
3416 +               } else {
3417 +                       return CI_STATUS_NOTSUPP;
3418 +               }
3419 +       }
3420 +       return error;
3421 +}
3422 +
3423 +/*
3424 + *  Disable the Bad Pixel Detection and Correction.
3425 + */
3426 +int ci_bp_end(const struct ci_isp_bp_corr_config *bp_corr_config)
3427 +{
3428 +       int uiResult = CI_STATUS_SUCCESS;
3429 +
3430 +       /* check the parameter */
3431 +       if (!bp_corr_config)
3432 +               return CI_STATUS_NULL_POINTER;
3433 +
3434 +       /* disable badpixel correction */
3435 +       uiResult |= ci_isp_set_bp_correction(NULL);
3436 +
3437 +       /* disable badpixel detection */
3438 +       uiResult |= ci_isp_set_bp_detection(NULL);
3439 +
3440 +       if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_TABLE) {
3441 +               /* Clear Interrupt Status */
3442 +               uiResult |= ci_isp_clear_bp_int();
3443 +
3444 +               /* deallocate BP Table */
3445 +               kfree(bp_table.bp_table_elem);
3446 +               bp_table.bp_table_elem = NULL;
3447 +       }
3448 +       return uiResult;
3449 +}
3450 +#endif
3451 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c b/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c
3452 new file mode 100644
3453 index 0000000..7c96bc4
3454 --- /dev/null
3455 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c
3456 @@ -0,0 +1,1993 @@
3457 +/*
3458 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
3459 + *
3460 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
3461 + *
3462 + * Copyright (c) Silicon Image 2008  www.siliconimage.com
3463 + *
3464 + * This program is free software; you can redistribute it and/or
3465 + * modify it under the terms of the GNU General Public License version
3466 + * 2 as published by the Free Software Foundation.
3467 + *
3468 + * This program is distributed in the hope that it will be useful,
3469 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3470 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3471 + * GNU General Public License for more details.
3472 + *
3473 + * You should have received a copy of the GNU General Public License
3474 + * along with this program; if not, write to the Free Software
3475 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
3476 + * 02110-1301, USA.
3477 + *
3478 + *
3479 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
3480 + */
3481 +
3482 +#include "mrstisp_stdinc.h"
3483 +
3484 +int mrst_isp_set_color_conversion_ex(void)
3485 +{
3486 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
3487 +
3488 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_0, MRV_ISP_CC_COEFF_0, 0x00001021);
3489 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_1, MRV_ISP_CC_COEFF_1, 0x00001040);
3490 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_2, MRV_ISP_CC_COEFF_2, 0x0000100D);
3491 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_3, MRV_ISP_CC_COEFF_3, 0x00000FED);
3492 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_4, MRV_ISP_CC_COEFF_4, 0x00000FDB);
3493 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_5, MRV_ISP_CC_COEFF_5, 0x00001038);
3494 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_6, MRV_ISP_CC_COEFF_6, 0x00001038);
3495 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_7, MRV_ISP_CC_COEFF_7, 0x00000FD1);
3496 +       REG_SET_SLICE(mrv_reg->isp_cc_coeff_8, MRV_ISP_CC_COEFF_8, 0x00000FF7);
3497 +
3498 +       return CI_STATUS_SUCCESS;
3499 +}
3500 +
3501 +/*
3502 + * Selects the ISP path that will become active while processing
3503 + * data coming from an image sensor configured by the given ISI
3504 + * configuration struct.
3505 + */
3506 +enum ci_isp_path ci_isp_select_path(const struct ci_sensor_config *isi_cfg,
3507 +                                   u8 *words_per_pixel)
3508 +{
3509 +       u8 words;
3510 +       enum ci_isp_path ret_val;
3511 +
3512 +       switch (isi_cfg->mode) {
3513 +       case SENSOR_MODE_DATA:
3514 +               ret_val = CI_ISP_PATH_RAW;
3515 +               words = 1;
3516 +               break;
3517 +       case SENSOR_MODE_PICT:
3518 +               ret_val = CI_ISP_PATH_RAW;
3519 +               words = 1;
3520 +               break;
3521 +       case SENSOR_MODE_RGB565:
3522 +               ret_val = CI_ISP_PATH_RAW;
3523 +               words = 2;
3524 +               break;
3525 +       case SENSOR_MODE_BT601:
3526 +               ret_val = CI_ISP_PATH_YCBCR;
3527 +               words = 2;
3528 +               break;
3529 +       case SENSOR_MODE_BT656:
3530 +               ret_val = CI_ISP_PATH_YCBCR;
3531 +               words = 2;
3532 +               break;
3533 +       case SENSOR_MODE_BAYER:
3534 +               ret_val = CI_ISP_PATH_BAYER;
3535 +               words = 1;
3536 +               break;
3537 +
3538 +       case SENSOR_MODE_SMIA:
3539 +               switch (isi_cfg->smia_mode) {
3540 +               case SENSOR_SMIA_MODE_RAW_12:
3541 +               case SENSOR_SMIA_MODE_RAW_10:
3542 +               case SENSOR_SMIA_MODE_RAW_8:
3543 +               case SENSOR_SMIA_MODE_RAW_8_TO_10_DECOMP:
3544 +                       ret_val = CI_ISP_PATH_BAYER;
3545 +                       words = 1;
3546 +                       break;
3547 +               case SENSOR_SMIA_MODE_YUV_422:
3548 +                       ret_val = CI_ISP_PATH_YCBCR;
3549 +                       words = 2;
3550 +                       break;
3551 +               case SENSOR_SMIA_MODE_YUV_420:
3552 +               case SENSOR_SMIA_MODE_RGB_444:
3553 +               case SENSOR_SMIA_MODE_RGB_565:
3554 +               case SENSOR_SMIA_MODE_RGB_888:
3555 +               case SENSOR_SMIA_MODE_COMPRESSED:
3556 +               case SENSOR_SMIA_MODE_RAW_7:
3557 +               case SENSOR_SMIA_MODE_RAW_6:
3558 +               default:
3559 +                       ret_val = CI_ISP_PATH_RAW;
3560 +                       words = 1;
3561 +                       break;
3562 +               }
3563 +               break;
3564 +
3565 +       case SENSOR_MODE_MIPI:
3566 +               switch (isi_cfg->mipi_mode) {
3567 +               case SENSOR_MIPI_MODE_RAW_12:
3568 +               case SENSOR_MIPI_MODE_RAW_10:
3569 +               case SENSOR_MIPI_MODE_RAW_8:
3570 +                       ret_val = CI_ISP_PATH_BAYER;
3571 +                       words = 1;
3572 +                       break;
3573 +               case SENSOR_MIPI_MODE_YUV422_8:
3574 +               case SENSOR_MIPI_MODE_YUV422_10:
3575 +                       ret_val = CI_ISP_PATH_YCBCR;
3576 +                       words = 2;
3577 +                       break;
3578 +               case SENSOR_MIPI_MODE_YUV420_8:
3579 +               case SENSOR_MIPI_MODE_YUV420_10:
3580 +               case SENSOR_MIPI_MODE_LEGACY_YUV420_8:
3581 +               case SENSOR_MIPI_MODE_YUV420_CSPS_8:
3582 +               case SENSOR_MIPI_MODE_YUV420_CSPS_10:
3583 +               case SENSOR_MIPI_MODE_RGB444:
3584 +               case SENSOR_MIPI_MODE_RGB555:
3585 +               case SENSOR_MIPI_MODE_RGB565:
3586 +               case SENSOR_MIPI_MODE_RGB666:
3587 +               case SENSOR_MIPI_MODE_RGB888:
3588 +               case SENSOR_MIPI_MODE_RAW_7:
3589 +               case SENSOR_MIPI_MODE_RAW_6:
3590 +               default:
3591 +                       ret_val = CI_ISP_PATH_RAW;
3592 +                       words = 1;
3593 +                       break;
3594 +               }
3595 +               break;
3596 +       case SENSOR_MODE_BAY_BT656:
3597 +               ret_val = CI_ISP_PATH_BAYER;
3598 +               words = 1;
3599 +               break;
3600 +       case SENSOR_MODE_RAW_BT656:
3601 +               ret_val = CI_ISP_PATH_RAW;
3602 +               words = 1;
3603 +               break;
3604 +       default:
3605 +               ret_val = CI_ISP_PATH_UNKNOWN;
3606 +               words = 1;
3607 +       }
3608 +
3609 +       if (words_per_pixel)
3610 +               *words_per_pixel = words ;
3611 +       return ret_val;
3612 +}
3613 +
3614 +/*
3615 + * configures the input acquisition according to the
3616 + * given config structure
3617 + */
3618 +int ci_isp_set_input_aquisition(const struct ci_sensor_config *isi_cfg)
3619 +{
3620 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
3621 +       u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
3622 +       u32 isp_acq_prop = REG_READ(mrv_reg->isp_acq_prop);
3623 +       /* factor between pixel count and amount of bytes to sample */
3624 +       u8 sample_factor;
3625 +       /* number of additional black lines at frame start */
3626 +       u8 black_lines;
3627 +
3628 +       if (ci_isp_select_path(isi_cfg, &sample_factor)
3629 +           == CI_ISP_PATH_UNKNOWN) {
3630 +               eprintk("failed to select path");
3631 +               return CI_STATUS_NOTSUPP;
3632 +       }
3633 +
3634 +       switch (isi_cfg->mode) {
3635 +       case SENSOR_MODE_DATA:
3636 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3637 +                             MRV_ISP_ISP_MODE_DATA);
3638 +               break;
3639 +       case SENSOR_MODE_PICT:
3640 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3641 +                             MRV_ISP_ISP_MODE_RAW);
3642 +               break;
3643 +       case SENSOR_MODE_RGB565:
3644 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3645 +                             MRV_ISP_ISP_MODE_RAW);
3646 +               break;
3647 +       case SENSOR_MODE_BT601:
3648 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3649 +                             MRV_ISP_ISP_MODE_601);
3650 +               break;
3651 +       case SENSOR_MODE_BT656:
3652 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3653 +                             MRV_ISP_ISP_MODE_656);
3654 +               break;
3655 +       case SENSOR_MODE_BAYER:
3656 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3657 +                             MRV_ISP_ISP_MODE_RGB);
3658 +               break;
3659 +       case SENSOR_MODE_BAY_BT656:
3660 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3661 +                             MRV_ISP_ISP_MODE_RGB656);
3662 +               break;
3663 +       case SENSOR_MODE_RAW_BT656:
3664 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3665 +                             MRV_ISP_ISP_MODE_RAW656);
3666 +               break;
3667 +
3668 +       case SENSOR_MODE_SMIA:
3669 +               switch (isi_cfg->smia_mode) {
3670 +               case SENSOR_SMIA_MODE_RAW_12:
3671 +               case SENSOR_SMIA_MODE_RAW_10:
3672 +               case SENSOR_SMIA_MODE_RAW_8:
3673 +               case SENSOR_SMIA_MODE_RAW_8_TO_10_DECOMP:
3674 +               case SENSOR_SMIA_MODE_RAW_7:
3675 +               case SENSOR_SMIA_MODE_RAW_6:
3676 +               case SENSOR_SMIA_MODE_YUV_422:
3677 +               case SENSOR_SMIA_MODE_YUV_420:
3678 +               case SENSOR_SMIA_MODE_RGB_888:
3679 +               case SENSOR_SMIA_MODE_RGB_565:
3680 +               case SENSOR_SMIA_MODE_RGB_444:
3681 +               case SENSOR_SMIA_MODE_COMPRESSED:
3682 +                       return CI_STATUS_SUCCESS;
3683 +                       break;
3684 +               default:
3685 +                       return CI_STATUS_NOTSUPP;
3686 +               }
3687 +               break;
3688 +
3689 +       case SENSOR_MODE_MIPI:
3690 +               REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3691 +                             MRV_ISP_ISP_MODE_RGB);
3692 +               REG_WRITE(mrv_reg->mipi_img_data_sel, 0x02b);
3693 +               break;
3694 +
3695 +       default:
3696 +               return CI_STATUS_NOTSUPP;
3697 +       }
3698 +
3699 +       switch (isi_cfg->bus_width) {
3700 +       case SENSOR_BUSWIDTH_12BIT:
3701 +               /* 000- 12Bit external Interface */
3702 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION,
3703 +                             MRV_ISP_INPUT_SELECTION_12EXT);
3704 +               break;
3705 +       case SENSOR_BUSWIDTH_10BIT_ZZ:
3706 +               /* 001- 10Bit Interface, append 2 zeroes as LSBs */
3707 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION,
3708 +                             MRV_ISP_INPUT_SELECTION_10ZERO);
3709 +               break;
3710 +       case SENSOR_BUSWIDTH_10BIT_EX:
3711 +               /* 010- 10Bit Interface, append 2 MSBs as LSBs */
3712 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION,
3713 +                             MRV_ISP_INPUT_SELECTION_10MSB);
3714 +               break;
3715 +       case SENSOR_BUSWIDTH_8BIT_ZZ:
3716 +               /* 011- 8Bit Interface, append 4 zeroes as LSBs */
3717 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION,
3718 +                             MRV_ISP_INPUT_SELECTION_8ZERO);
3719 +               break;
3720 +       case SENSOR_BUSWIDTH_8BIT_EX:
3721 +               /* 100- 8Bit Interface, append 4 MSBs as LSBs */
3722 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION,
3723 +                             MRV_ISP_INPUT_SELECTION_8MSB);
3724 +               break;
3725 +               /* 101...111 reserved */
3726 +       default:
3727 +               return CI_STATUS_NOTSUPP;
3728 +       }
3729 +
3730 +       switch (isi_cfg->field_sel) {
3731 +       case SENSOR_FIELDSEL_ODD:
3732 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION,
3733 +                             MRV_ISP_FIELD_SELECTION_ODD);
3734 +               break;
3735 +       case SENSOR_FIELDSEL_EVEN:
3736 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION,
3737 +                             MRV_ISP_FIELD_SELECTION_EVEN);
3738 +               break;
3739 +       case SENSOR_FIELDSEL_BOTH:
3740 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION,
3741 +                             MRV_ISP_FIELD_SELECTION_BOTH);
3742 +               break;
3743 +       default:
3744 +               return CI_STATUS_NOTSUPP;
3745 +       }
3746 +
3747 +       switch (isi_cfg->ycseq) {
3748 +       case SENSOR_YCSEQ_CRYCBY:
3749 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3750 +                             MRV_ISP_CCIR_SEQ_CRYCBY);
3751 +               break;
3752 +       case SENSOR_YCSEQ_CBYCRY:
3753 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3754 +                             MRV_ISP_CCIR_SEQ_CBYCRY);
3755 +               break;
3756 +       case SENSOR_YCSEQ_YCRYCB:
3757 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3758 +                             MRV_ISP_CCIR_SEQ_YCRYCB);
3759 +               break;
3760 +       case SENSOR_YCSEQ_YCBYCR:
3761 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3762 +                             MRV_ISP_CCIR_SEQ_YCBYCR);
3763 +               break;
3764 +       default:
3765 +               return CI_STATUS_NOTSUPP;
3766 +       }
3767 +
3768 +       switch (isi_cfg->conv422) {
3769 +       case SENSOR_CONV422_INTER:
3770 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422,
3771 +                       MRV_ISP_CONV_422_INTER);
3772 +               break;
3773 +
3774 +       case SENSOR_CONV422_NOCOSITED:
3775 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422,
3776 +                     MRV_ISP_CONV_422_NONCO);
3777 +               break;
3778 +       case SENSOR_CONV422_COSITED:
3779 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422,
3780 +                     MRV_ISP_CONV_422_CO);
3781 +               break;
3782 +       default:
3783 +       return CI_STATUS_NOTSUPP;
3784 +       }
3785 +
3786 +       switch (isi_cfg->bpat) {
3787 +       case SENSOR_BPAT_BGBGGRGR:
3788 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3789 +                     MRV_ISP_BAYER_PAT_BG);
3790 +               break;
3791 +       case SENSOR_BPAT_GBGBRGRG:
3792 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3793 +                     MRV_ISP_BAYER_PAT_GB);
3794 +               break;
3795 +       case SENSOR_BPAT_GRGRBGBG:
3796 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3797 +                     MRV_ISP_BAYER_PAT_GR);
3798 +               break;
3799 +       case SENSOR_BPAT_RGRGGBGB:
3800 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3801 +                     MRV_ISP_BAYER_PAT_RG);
3802 +               break;
3803 +       default:
3804 +               return CI_STATUS_NOTSUPP;
3805 +       }
3806 +
3807 +       switch (isi_cfg->vpol) {
3808 +       case SENSOR_VPOL_POS:
3809 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_VSYNC_POL, 1);
3810 +               break;
3811 +       case SENSOR_VPOL_NEG:
3812 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_VSYNC_POL, 0);
3813 +               break;
3814 +       default:
3815 +               return CI_STATUS_NOTSUPP;
3816 +       }
3817 +
3818 +       switch (isi_cfg->hpol) {
3819 +       /* The trigger edge differs for vsync_pol and hsync_pol. */
3820 +       /* vsync_pol = 1 triggers on positive edge whereas */
3821 +       /* hsync_pol = 1 triggers on negative edge and vice versa */
3822 +       case SENSOR_HPOL_SYNCPOS:
3823 +               /* trigger on negative edge */
3824 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 1);
3825 +               break;
3826 +       case SENSOR_HPOL_SYNCNEG:
3827 +               /* trigger on positive edge */
3828 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 0);
3829 +               break;
3830 +       case SENSOR_HPOL_REFPOS:
3831 +               /* trigger on positive edge */
3832 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 0);
3833 +               break;
3834 +       case SENSOR_HPOL_REFNEG:
3835 +               /* trigger on negative edge */
3836 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 1);
3837 +               break;
3838 +       default:
3839 +               return CI_STATUS_NOTSUPP;
3840 +       }
3841 +
3842 +       switch (isi_cfg->edge) {
3843 +       case SENSOR_EDGE_RISING:
3844 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_SAMPLE_EDGE, 1);
3845 +               break;
3846 +       case SENSOR_EDGE_FALLING:
3847 +               REG_SET_SLICE(isp_acq_prop, MRV_ISP_SAMPLE_EDGE, 0);
3848 +               break;
3849 +       default:
3850 +               return CI_STATUS_NOTSUPP;
3851 +       }
3852 +       dprintk(2, "isp_acq_prop = 0x%x", isp_acq_prop);
3853 +
3854 +       /* now write values to registers */
3855 +       REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl);
3856 +       REG_WRITE(mrv_reg->isp_acq_prop, isp_acq_prop);
3857 +
3858 +       /* number of additional black lines at frame start */
3859 +       switch (isi_cfg->bls) {
3860 +       case SENSOR_BLS_OFF:
3861 +               black_lines = 0;
3862 +               break;
3863 +       case SENSOR_BLS_TWO_LINES:
3864 +               black_lines = 2;
3865 +               break;
3866 +       case SENSOR_BLS_FOUR_LINES:
3867 +               black_lines = 4;
3868 +               break;
3869 +       default:
3870 +               return CI_STATUS_NOTSUPP;
3871 +       }
3872 +
3873 +       REG_SET_SLICE(mrv_reg->isp_acq_h_offs, MRV_ISP_ACQ_H_OFFS,
3874 +                     0 * sample_factor);
3875 +       REG_SET_SLICE(mrv_reg->isp_acq_v_offs, MRV_ISP_ACQ_V_OFFS, 0);
3876 +
3877 +       dprintk(2, "res = %x", isi_cfg->res);
3878 +       switch (isi_cfg->res) {
3879 +       /* 88x72 */
3880 +       case SENSOR_RES_QQCIF:
3881 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3882 +                             QQCIF_SIZE_H * sample_factor);
3883 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3884 +                             QQCIF_SIZE_V + black_lines);
3885 +               break;
3886 +       /* 160x120 */
3887 +       case SENSOR_RES_QQVGA:
3888 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3889 +                             QQVGA_SIZE_H * sample_factor);
3890 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3891 +                             QQVGA_SIZE_V + black_lines);
3892 +               break;
3893 +       /* 176x144 */
3894 +       case SENSOR_RES_QCIF:
3895 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3896 +                             QCIF_SIZE_H * sample_factor);
3897 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3898 +                             QCIF_SIZE_V + black_lines);
3899 +               break;
3900 +       /* 320x240 */
3901 +       case SENSOR_RES_QVGA:
3902 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3903 +                             QVGA_SIZE_H * sample_factor);
3904 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3905 +                             QVGA_SIZE_V + black_lines);
3906 +               break;
3907 +       /* 352x288 */
3908 +       case SENSOR_RES_CIF:
3909 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3910 +                             CIF_SIZE_H * sample_factor);
3911 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3912 +                             CIF_SIZE_V + black_lines);
3913 +               break;
3914 +       /* 640x480 */
3915 +       case SENSOR_RES_VGA:
3916 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3917 +                             VGA_SIZE_H * sample_factor);
3918 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3919 +                             VGA_SIZE_V + black_lines);
3920 +               break;
3921 +       /* 800x600 */
3922 +       case SENSOR_RES_SVGA:
3923 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3924 +                             SVGA_SIZE_H * sample_factor);
3925 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3926 +                             SVGA_SIZE_V + black_lines);
3927 +               break;
3928 +       /* 1024x768 */
3929 +       case SENSOR_RES_XGA:
3930 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3931 +                             XGA_SIZE_H * sample_factor);
3932 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3933 +                             XGA_SIZE_V + black_lines);
3934 +               break;
3935 +       case SENSOR_RES_720P:
3936 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3937 +                             RES_720P_SIZE_H * sample_factor);
3938 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3939 +                             RES_720P_SIZE_V + black_lines);
3940 +               break;
3941 +       /* 1280x960 */
3942 +       case SENSOR_RES_XGA_PLUS:
3943 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3944 +                             XGA_PLUS_SIZE_H * sample_factor);
3945 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3946 +                             XGA_PLUS_SIZE_V + black_lines);
3947 +               break;
3948 +       /* 1280x1024 */
3949 +       case SENSOR_RES_SXGA:
3950 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3951 +                             SXGA_SIZE_H * sample_factor);
3952 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3953 +                             SXGA_SIZE_V + black_lines);
3954 +               break;
3955 +       /* 1600x1200 */
3956 +       case SENSOR_RES_UXGA:
3957 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3958 +                             QSVGA_SIZE_H * sample_factor);
3959 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3960 +                             QSVGA_SIZE_V + black_lines);
3961 +               break;
3962 +       /* 1920x1280 */
3963 +       case SENSOR_RES_1080P:
3964 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3965 +                             1920 * sample_factor);
3966 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3967 +                             1080 + black_lines);
3968 +               break;
3969 +       /* 2048x1536 */
3970 +       case SENSOR_RES_QXGA:
3971 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3972 +                             QXGA_SIZE_H * sample_factor);
3973 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3974 +                             QXGA_SIZE_V + black_lines);
3975 +               break;
3976 +       /* 2586x2048 */
3977 +       case SENSOR_RES_QSXGA:
3978 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3979 +                             QSXGA_SIZE_H * sample_factor);
3980 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3981 +                             QSXGA_SIZE_V + black_lines);
3982 +               break;
3983 +       /* 2600x2048 */
3984 +       case SENSOR_RES_QSXGA_PLUS:
3985 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3986 +                             QSXGA_PLUS_SIZE_H * sample_factor);
3987 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3988 +                             QSXGA_PLUS_SIZE_V + black_lines);
3989 +               break;
3990 +       /* 2600x1950 */
3991 +       case SENSOR_RES_QSXGA_PLUS2:
3992 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
3993 +                             QSXGA_PLUS2_SIZE_H * sample_factor);
3994 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
3995 +                             QSXGA_PLUS2_SIZE_V + black_lines);
3996 +               break;
3997 +       /* 2686x2048,  5.30M */
3998 +       case SENSOR_RES_QSXGA_PLUS3:
3999 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4000 +                             QSXGA_PLUS3_SIZE_V * sample_factor);
4001 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4002 +                             QSXGA_PLUS3_SIZE_V + black_lines);
4003 +               break;
4004 +       /* 2592*1944 5M */
4005 +       case SENSOR_RES_QXGA_PLUS:
4006 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4007 +                               QXGA_PLUS_SIZE_H * sample_factor);
4008 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4009 +                             QXGA_PLUS_SIZE_V + black_lines);
4010 +               break;
4011 +       /* 3200x2048,  6.56M */
4012 +       case SENSOR_RES_WQSXGA:
4013 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4014 +                             WQSXGA_SIZE_H * sample_factor);
4015 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4016 +                             WQSXGA_SIZE_V + black_lines);
4017 +               break;
4018 +       /* 3200x2400,  7.68M */
4019 +       case SENSOR_RES_QUXGA:
4020 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4021 +                             QUXGA_SIZE_H * sample_factor);
4022 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4023 +                             QUXGA_SIZE_V + black_lines);
4024 +               break;
4025 +       /* 3840x2400,  9.22M */
4026 +       case SENSOR_RES_WQUXGA:
4027 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4028 +                             WQUXGA_SIZE_H * sample_factor);
4029 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4030 +                             WQUXGA_SIZE_V + black_lines);
4031 +               break;
4032 +       /* 4096x3072, 12.59M */
4033 +       case SENSOR_RES_HXGA:
4034 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4035 +                             HXGA_SIZE_H * sample_factor);
4036 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4037 +                             HXGA_SIZE_V + black_lines);
4038 +               break;
4039 +       /* 4080x1024 */
4040 +       case SENSOR_RES_YUV_HMAX:
4041 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4042 +                             YUV_HMAX_SIZE_H * sample_factor);
4043 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4044 +                             YUV_HMAX_SIZE_V);
4045 +               break;
4046 +       /* 1024x4080 */
4047 +       case SENSOR_RES_YUV_VMAX:
4048 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4049 +                             YUV_VMAX_SIZE_H * sample_factor);
4050 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4051 +                             YUV_VMAX_SIZE_V);
4052 +               break;
4053 +       /* 4096x2048 */
4054 +       case SENSOR_RES_RAWMAX:
4055 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4056 +                             RAWMAX_SIZE_H);
4057 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4058 +                             RAWMAX_SIZE_V);
4059 +               break;
4060 +       /* 352x240 */
4061 +       case SENSOR_RES_BP1:
4062 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4063 +                             BP1_SIZE_H * sample_factor);
4064 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4065 +                             BP1_SIZE_V);
4066 +               break;
4067 +       /* 720x480 */
4068 +       case SENSOR_RES_L_AFM:
4069 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4070 +                             L_AFM_SIZE_H * sample_factor);
4071 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4072 +                             L_AFM_SIZE_V);
4073 +               break;
4074 +       /* 128x96 */
4075 +       case SENSOR_RES_M_AFM:
4076 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4077 +                             M_AFM_SIZE_H * sample_factor);
4078 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4079 +                             M_AFM_SIZE_V);
4080 +               break;
4081 +       /* 64x32 */
4082 +       case SENSOR_RES_S_AFM:
4083 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4084 +                             S_AFM_SIZE_H * sample_factor);
4085 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4086 +                             S_AFM_SIZE_V);
4087 +               break;
4088 +       /* 1304x980 */
4089 +       case SENSOR_RES_VGA_PLUS:
4090 +               REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4091 +                             VGA_PLUS_SIZE_H * sample_factor);
4092 +               REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
4093 +                             VGA_PLUS_SIZE_V);
4094 +               break;
4095 +
4096 +       default:
4097 +               return CI_STATUS_NOTSUPP;
4098 +       }
4099 +
4100 +       return CI_STATUS_SUCCESS;
4101 +}
4102 +
4103 +/*
4104 + * sets output window
4105 + */
4106 +void ci_isp_set_output_formatter(const struct ci_isp_window *window,
4107 +                                enum ci_isp_conf_update_time update_time)
4108 +{
4109 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4110 +
4111 +       if (window) {
4112 +               /* set output window */
4113 +               REG_SET_SLICE(mrv_reg->isp_out_h_offs, MRV_IS_IS_H_OFFS,
4114 +                       window->hoffs);
4115 +               REG_SET_SLICE(mrv_reg->isp_out_v_offs, MRV_IS_IS_V_OFFS,
4116 +                       window->voffs);
4117 +               REG_SET_SLICE(mrv_reg->isp_out_h_size, MRV_IS_IS_H_SIZE,
4118 +                       window->hsize);
4119 +               REG_SET_SLICE(mrv_reg->isp_out_v_size, MRV_IS_IS_V_SIZE,
4120 +                       window->vsize);
4121 +
4122 +               REG_SET_SLICE(mrv_reg->isp_is_h_offs, MRV_IS_IS_H_OFFS, 0);
4123 +               REG_SET_SLICE(mrv_reg->isp_is_v_offs, MRV_IS_IS_V_OFFS, 0);
4124 +               REG_SET_SLICE(mrv_reg->isp_is_h_size, MRV_IS_IS_H_SIZE,
4125 +                       window->hsize);
4126 +               REG_SET_SLICE(mrv_reg->isp_is_v_size, MRV_IS_IS_V_SIZE,
4127 +                       window->vsize);
4128 +
4129 +               switch (update_time) {
4130 +               case CI_ISP_CFG_UPDATE_FRAME_SYNC:
4131 +                       /* frame synchronous update of shadow registers */
4132 +                       REG_SET_SLICE(mrv_reg->isp_ctrl,
4133 +                               MRV_ISP_ISP_GEN_CFG_UPD, ON);
4134 +                       break;
4135 +               case CI_ISP_CFG_UPDATE_IMMEDIATE:
4136 +                       /* immediate update of shadow registers */
4137 +                       REG_SET_SLICE(mrv_reg->isp_ctrl,
4138 +                               MRV_ISP_ISP_CFG_UPD, ON);
4139 +                       break;
4140 +               case CI_ISP_CFG_UPDATE_LATER:
4141 +                       /* no update from within this function */
4142 +                       break;
4143 +               default:
4144 +                       break;
4145 +               }
4146 +       }
4147 +}
4148 +
4149 +/*
4150 + * programs the given Bayer pattern demosaic parameters
4151 + */
4152 +void ci_isp_set_demosaic(enum ci_isp_demosaic_mode demosaic_mode,
4153 +                        u8 demosaic_th)
4154 +{
4155 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4156 +       u32 isp_demosaic = REG_READ(mrv_reg->isp_demosaic);
4157 +
4158 +       /* set demosaic mode */
4159 +       switch (demosaic_mode) {
4160 +       case CI_ISP_DEMOSAIC_STANDARD:
4161 +               REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_MODE,
4162 +                             MRV_ISP_DEMOSAIC_MODE_STD);
4163 +               break;
4164 +       case CI_ISP_DEMOSAIC_ENHANCED:
4165 +               REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_MODE,
4166 +                             MRV_ISP_DEMOSAIC_MODE_ENH);
4167 +               break;
4168 +       default:
4169 +               WARN_ON(!(false));
4170 +       }
4171 +
4172 +       /* set demosaic threshold */
4173 +       REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_TH, demosaic_th);
4174 +       REG_WRITE(mrv_reg->isp_demosaic, isp_demosaic);
4175 +}
4176 +
4177 +/*
4178 + * Sets the dedicated AWB block mode.
4179 + */
4180 +int ci_isp_set_wb_mode(enum ci_isp_awb_mode wb_mode)
4181 +{
4182 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4183 +
4184 +       switch (wb_mode) {
4185 +       case CI_ISP_AWB_COMPLETELY_OFF:
4186 +               /* manual WB, no measurements*/
4187 +               REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE,
4188 +                             MRV_ISP_AWB_MODE_NOMEAS);
4189 +               /* switch ABW block off */
4190 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE,
4191 +                             DISABLE);
4192 +               break;
4193 +       case CI_ISP_AWB_MAN_MEAS:
4194 +       case CI_ISP_AWB_AUTO:
4195 +       case CI_ISP_AWB_MAN_PUSH_AUTO:
4196 +       case CI_ISP_AWB_ONLY_MEAS:
4197 +               /* manual white balance, measure YCbCr means */
4198 +               REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE,
4199 +                       MRV_ISP_AWB_MODE_MEAS);
4200 +               /* switch ABW block on */
4201 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE,
4202 +                       ENABLE);
4203 +               break;
4204 +       case CI_ISP_AWB_MAN_NOMEAS:
4205 +               /* manual white balance, no measurements */
4206 +               REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE,
4207 +                       MRV_ISP_AWB_MODE_NOMEAS);
4208 +               /* switch ABW block on */
4209 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE,
4210 +                             ENABLE);
4211 +               break;
4212 +       default:
4213 +               /* to be sure that a regular value is set: */
4214 +               /* manual white balance, no measurements */
4215 +               REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE,
4216 +                       MRV_ISP_AWB_MODE_NOMEAS);
4217 +               /* switch ABW block off */
4218 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE,
4219 +                       DISABLE);
4220 +               return CI_STATUS_FAILURE;
4221 +       }
4222 +
4223 +       return CI_STATUS_SUCCESS;
4224 +}
4225 +
4226 +int ci_isp_get_wb_mode(enum ci_isp_awb_mode *wb_mode)
4227 +{
4228 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4229 +
4230 +       if (!wb_mode)
4231 +               return CI_STATUS_NULL_POINTER;
4232 +
4233 +       if (REG_GET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE) ==
4234 +               DISABLE) {
4235 +               *wb_mode = CI_ISP_AWB_COMPLETELY_OFF;
4236 +       } else {
4237 +
4238 +               switch (REG_GET_SLICE(mrv_reg->isp_awb_prop,
4239 +                       MRV_ISP_AWB_MODE)) {
4240 +               case MRV_ISP_AWB_MODE_MEAS:
4241 +                       *wb_mode = CI_ISP_AWB_MAN_MEAS;
4242 +                       break;
4243 +               case MRV_ISP_AWB_MODE_NOMEAS:
4244 +                       *wb_mode = CI_ISP_AWB_MAN_NOMEAS;
4245 +                       break;
4246 +               default:
4247 +                       *wb_mode = CI_ISP_AWB_COMPLETELY_OFF;
4248 +                       return CI_STATUS_FAILURE;
4249 +               }
4250 +       }
4251 +       return CI_STATUS_SUCCESS;
4252 +}
4253 +int ci_isp_set_wb_meas_config(const struct ci_isp_wb_meas_config
4254 +                             *wb_meas_config)
4255 +{
4256 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4257 +       u32 isp_awb_thresh = REG_READ(mrv_reg->isp_awb_thresh);
4258 +
4259 +       if (!wb_meas_config)
4260 +               return CI_STATUS_NULL_POINTER;
4261 +
4262 +       /* measurement window */
4263 +       REG_SET_SLICE(mrv_reg->isp_awb_h_size, MRV_ISP_AWB_H_SIZE,
4264 +               (u32) wb_meas_config->awb_window.hsize);
4265 +       REG_SET_SLICE(mrv_reg->isp_awb_v_size, MRV_ISP_AWB_V_SIZE,
4266 +               (u32) wb_meas_config->awb_window.vsize);
4267 +       REG_SET_SLICE(mrv_reg->isp_awb_h_offs, MRV_ISP_AWB_H_OFFS,
4268 +               (u32) wb_meas_config->awb_window.hoffs);
4269 +       REG_SET_SLICE(mrv_reg->isp_awb_v_offs, MRV_ISP_AWB_V_OFFS,
4270 +               (u32) wb_meas_config->awb_window.voffs);
4271 +
4272 +       /* adjust awb properties (Y_MAX compare) */
4273 +       if (wb_meas_config->max_y == 0) {
4274 +               REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN,
4275 +                       DISABLE);
4276 +       } else {
4277 +               REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN,
4278 +                       ENABLE);
4279 +       }
4280 +
4281 +       /* measurement thresholds */
4282 +       REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MAX_Y,
4283 +                     (u32) wb_meas_config->max_y);
4284 +       REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MIN_Y__MAX_G,
4285 +                     (u32) wb_meas_config->minY_MaxG);
4286 +       REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MAX_CSUM,
4287 +                     (u32) wb_meas_config->max_csum);
4288 +       REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MIN_C,
4289 +                     (u32) wb_meas_config->min_c);
4290 +       REG_WRITE(mrv_reg->isp_awb_thresh, isp_awb_thresh);
4291 +       REG_SET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CR__MAX_R,
4292 +                     (u32)(wb_meas_config->ref_cr_MaxR));
4293 +       REG_SET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CB__MAX_B,
4294 +                     (u32)(wb_meas_config->ref_cb_MaxB));
4295 +
4296 +       /* amount of measurement frames */
4297 +       REG_SET_SLICE(mrv_reg->isp_awb_frames, MRV_ISP_AWB_FRAMES,
4298 +                     (u32) wb_meas_config->frames);
4299 +
4300 +       /* set measurement mode */
4301 +       REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MEAS_MODE,
4302 +                     (u32)(wb_meas_config->meas_mode));
4303 +
4304 +       return CI_STATUS_SUCCESS;
4305 +}
4306 +
4307 +int ci_isp_get_wb_meas_config(struct ci_isp_wb_meas_config *wb_meas_config)
4308 +{
4309 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4310 +
4311 +       if (!wb_meas_config)
4312 +               return CI_STATUS_NULL_POINTER;
4313 +
4314 +       /* measurement window */
4315 +       wb_meas_config->awb_window.hsize =
4316 +           (u16) REG_GET_SLICE(mrv_reg->isp_awb_h_size, MRV_ISP_AWB_H_SIZE);
4317 +       wb_meas_config->awb_window.vsize =
4318 +           (u16) REG_GET_SLICE(mrv_reg->isp_awb_v_size, MRV_ISP_AWB_V_SIZE);
4319 +       wb_meas_config->awb_window.hoffs =
4320 +           (u16) REG_GET_SLICE(mrv_reg->isp_awb_h_offs, MRV_ISP_AWB_H_OFFS);
4321 +       wb_meas_config->awb_window.voffs =
4322 +           (u16) REG_GET_SLICE(mrv_reg->isp_awb_v_offs, MRV_ISP_AWB_V_OFFS);
4323 +
4324 +       /* measurement thresholds */
4325 +       wb_meas_config->min_c =
4326 +           (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, MRV_ISP_AWB_MIN_C);
4327 +       wb_meas_config->max_csum =
4328 +           (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, MRV_ISP_AWB_MAX_CSUM);
4329 +       wb_meas_config->minY_MaxG =
4330 +           (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh,
4331 +                              MRV_ISP_AWB_MIN_Y__MAX_G);
4332 +       wb_meas_config->max_y =
4333 +           (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, MRV_ISP_AWB_MAX_Y);
4334 +       wb_meas_config->ref_cb_MaxB =
4335 +           (u8)REG_GET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CB__MAX_B);
4336 +       wb_meas_config->ref_cr_MaxR =
4337 +           (u8)REG_GET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CR__MAX_R);
4338 +
4339 +       /* amount of measurement frames */
4340 +       wb_meas_config->frames =
4341 +           (u8) REG_GET_SLICE(mrv_reg->isp_awb_frames, MRV_ISP_AWB_FRAMES);
4342 +
4343 +       /* overwrite max_y if the feature is disabled */
4344 +       if (REG_GET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN) ==
4345 +           DISABLE) {
4346 +               wb_meas_config->max_y = 0;
4347 +       }
4348 +
4349 +       /* get measurement mode */
4350 +       wb_meas_config->meas_mode = REG_GET_SLICE(mrv_reg->isp_awb_prop,
4351 +                                                 MRV_ISP_AWB_MEAS_MODE);
4352 +       return CI_STATUS_SUCCESS;
4353 +}
4354 +
4355 +int ci_isp_get_wb_meas(struct ci_sensor_awb_mean *awb_mean)
4356 +{
4357 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4358 +
4359 +       if (awb_mean == NULL)
4360 +               return CI_STATUS_NULL_POINTER;
4361 +
4362 +       awb_mean->white = REG_GET_SLICE(mrv_reg->isp_awb_white_cnt,
4363 +                                       MRV_ISP_AWB_WHITE_CNT);
4364 +       awb_mean->mean_Y__G = (u8) REG_GET_SLICE(mrv_reg->isp_awb_mean,
4365 +                                                MRV_ISP_AWB_MEAN_Y__G);
4366 +       awb_mean->mean_cb__B = (u8) REG_GET_SLICE(mrv_reg->isp_awb_mean,
4367 +                                                 MRV_ISP_AWB_MEAN_CB__B);
4368 +       awb_mean->mean_cr__R = (u8) REG_GET_SLICE(mrv_reg->isp_awb_mean,
4369 +                                                 MRV_ISP_AWB_MEAN_CR__R);
4370 +       return CI_STATUS_SUCCESS;
4371 +}
4372 +
4373 +/*
4374 + * calculates left-top and right-bottom register values
4375 + * for a given AF measurement window
4376 + */
4377 +static int ci_isp_afm_wnd2_regs(const struct ci_isp_window *wnd, u32 *lt,
4378 +                               u32 *rb)
4379 +{
4380 +       WARN_ON(!((wnd != NULL) && (lt != NULL) && (rb != NULL)));
4381 +
4382 +       if (wnd->hsize && wnd->vsize) {
4383 +               u32 left = wnd->hoffs;
4384 +               u32 top = wnd->voffs;
4385 +               u32 right = left + wnd->hsize - 1;
4386 +               u32 bottom = top + wnd->vsize - 1;
4387 +
4388 +               if ((left < MRV_AFM_A_H_L_MIN)
4389 +                   || (left > MRV_AFM_A_H_L_MAX)
4390 +                   || (top < MRV_AFM_A_V_T_MIN)
4391 +                   || (top > MRV_AFM_A_V_T_MAX)
4392 +                   || (right < MRV_AFM_A_H_R_MIN)
4393 +                   || (right > MRV_AFM_A_H_R_MAX)
4394 +                   || (bottom < MRV_AFM_A_V_B_MIN)
4395 +                   || (bottom > MRV_AFM_A_V_B_MAX)) {
4396 +                       return CI_STATUS_OUTOFRANGE;
4397 +               }
4398 +
4399 +               /* combine the values and return */
4400 +               REG_SET_SLICE(*lt, MRV_AFM_A_H_L, left);
4401 +               REG_SET_SLICE(*lt, MRV_AFM_A_V_T, top);
4402 +               REG_SET_SLICE(*rb, MRV_AFM_A_H_R, right);
4403 +               REG_SET_SLICE(*rb, MRV_AFM_A_V_B, bottom);
4404 +       } else {
4405 +               *lt = 0;
4406 +               *rb = 0;
4407 +       }
4408 +
4409 +       return CI_STATUS_SUCCESS;
4410 +}
4411 +
4412 +int ci_isp_set_auto_focus(const struct ci_isp_af_config *af_config)
4413 +{
4414 +
4415 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4416 +       u32 result = CI_STATUS_SUCCESS;
4417 +
4418 +       /* disable measurement module */
4419 +       REG_SET_SLICE(mrv_reg->isp_afm_ctrl, MRV_AFM_AFM_EN, DISABLE);
4420 +
4421 +       if (af_config) {
4422 +               u32 lt;
4423 +               u32 rb;
4424 +               result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_a),
4425 +                                             &lt, &rb);
4426 +               /* set measurement window boundaries */
4427 +               if (result != CI_STATUS_SUCCESS)
4428 +                       return result;
4429 +
4430 +               REG_WRITE(mrv_reg->isp_afm_lt_a, lt);
4431 +               REG_WRITE(mrv_reg->isp_afm_rb_a, rb);
4432 +
4433 +               result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_b),
4434 +                                             &lt, &rb);
4435 +
4436 +               if (result != CI_STATUS_SUCCESS)
4437 +                       return result;
4438 +
4439 +               REG_WRITE(mrv_reg->isp_afm_lt_b, lt);
4440 +               REG_WRITE(mrv_reg->isp_afm_rb_b, rb);
4441 +
4442 +               result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_c),
4443 +                                             &lt, &rb);
4444 +
4445 +               if (result != CI_STATUS_SUCCESS)
4446 +                       return result;
4447 +
4448 +               REG_WRITE(mrv_reg->isp_afm_lt_c, lt);
4449 +               REG_WRITE(mrv_reg->isp_afm_rb_c, rb);
4450 +
4451 +               /* set other af measurement paraneters */
4452 +               REG_SET_SLICE(mrv_reg->isp_afm_thres, MRV_AFM_AFM_THRES,
4453 +                             af_config->threshold);
4454 +               REG_SET_SLICE(mrv_reg->isp_afm_var_shift, MRV_AFM_LUM_VAR_SHIFT,
4455 +                       (af_config->var_shift >> 16));
4456 +               REG_SET_SLICE(mrv_reg->isp_afm_var_shift, MRV_AFM_AFM_VAR_SHIFT,
4457 +                       (af_config->var_shift >> 0));
4458 +
4459 +               /* enable measurement module */
4460 +               REG_SET_SLICE(mrv_reg->isp_afm_ctrl, MRV_AFM_AFM_EN, ENABLE);
4461 +       }
4462 +
4463 +       return result;
4464 +}
4465 +
4466 +
4467 +void ci_isp_get_auto_focus_meas(struct ci_isp_af_meas *af_meas)
4468 +{
4469 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4470 +
4471 +       WARN_ON(!(af_meas != NULL));
4472 +
4473 +       af_meas->afm_sum_a =
4474 +           REG_GET_SLICE(mrv_reg->isp_afm_sum_a, MRV_AFM_AFM_SUM_A);
4475 +       af_meas->afm_sum_b =
4476 +           REG_GET_SLICE(mrv_reg->isp_afm_sum_b, MRV_AFM_AFM_SUM_B);
4477 +       af_meas->afm_sum_c =
4478 +           REG_GET_SLICE(mrv_reg->isp_afm_sum_c, MRV_AFM_AFM_SUM_C);
4479 +       af_meas->afm_lum_a =
4480 +           REG_GET_SLICE(mrv_reg->isp_afm_lum_a, MRV_AFM_AFM_LUM_A);
4481 +       af_meas->afm_lum_b =
4482 +           REG_GET_SLICE(mrv_reg->isp_afm_lum_b, MRV_AFM_AFM_LUM_B);
4483 +       af_meas->afm_lum_c =
4484 +           REG_GET_SLICE(mrv_reg->isp_afm_lum_c, MRV_AFM_AFM_LUM_C);
4485 +}
4486 +
4487 +int ci_isp_set_ls_correction(struct ci_sensor_ls_corr_config *ls_corr_config)
4488 +{
4489 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4490 +       u32 i, n;
4491 +       u32 data = 0;
4492 +       int enabled = false;
4493 +
4494 +       if (!ls_corr_config) {
4495 +               /* disable lens shading module */
4496 +               REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, DISABLE);
4497 +       } else {
4498 +               /* test if lens shading correction is enabled */
4499 +               if (REG_GET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN)) {
4500 +                       /* switch off lens shading correction */
4501 +                       REG_SET_SLICE(mrv_reg->isp_lsc_ctrl,
4502 +                                     MRV_LSC_LSC_EN, DISABLE);
4503 +                       /* wait 1ms to make sure that
4504 +                       * the LSC have time enough to switch off */
4505 +                       /* wait over 1 ms */
4506 +                       /*mdelay(1000);*/
4507 +                       msleep(1000);
4508 +                       enabled = true;
4509 +               }
4510 +
4511 +               /* clear address counters */
4512 +               REG_WRITE(mrv_reg->isp_lsc_r_table_addr, 0);
4513 +               REG_WRITE(mrv_reg->isp_lsc_g_table_addr, 0);
4514 +               REG_WRITE(mrv_reg->isp_lsc_b_table_addr, 0);
4515 +
4516 +               /* program data tables (table size is 9 * 17 = 153;
4517 +               * see also MRV_LSC_?_RAM_ADDR_MAX) */
4518 +               WARN_ON(!(((CI_ISP_MAX_LSC_SECTORS + 1) *
4519 +                       ((CI_ISP_MAX_LSC_SECTORS + 2) / 2)) ==
4520 +                       (MRV_LSC_R_RAM_ADDR_MAX + 1)));
4521 +
4522 +               /* 17 steps */
4523 +               for (n = 0;
4524 +               n < ((CI_ISP_MAX_LSC_SECTORS + 1) *
4525 +                    (CI_ISP_MAX_LSC_SECTORS + 1));
4526 +               n += CI_ISP_MAX_LSC_SECTORS + 1) {
4527 +                       dprintk(2, "set ls correct step n = %d", n);
4528 +                       /* 17 sectors with 2 values in one DWORD = 9
4529 +                       * DWORDs (8 steps + 1 outside loop) */
4530 +                       for (i = 0; i < (CI_ISP_MAX_LSC_SECTORS); i += 2) {
4531 +                               REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_0,
4532 +                                       ls_corr_config->ls_rdata_tbl[n + i]);
4533 +                               REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_1,
4534 +                                       ls_corr_config->ls_rdata_tbl
4535 +                                       [n + i + 1]);
4536 +                               REG_WRITE(mrv_reg->isp_lsc_r_table_data, data);
4537 +                               REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_0,
4538 +                                       ls_corr_config->ls_gdata_tbl
4539 +                                       [n + i]);
4540 +                               REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_1,
4541 +                                       ls_corr_config->ls_gdata_tbl
4542 +                                       [n + i + 1]);
4543 +                               REG_WRITE(mrv_reg->isp_lsc_g_table_data, data);
4544 +                               REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_0,
4545 +                                       ls_corr_config->ls_bdata_tbl[n + i]);
4546 +                               REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_1,
4547 +                                       ls_corr_config->ls_bdata_tbl
4548 +                                       [n + i + 1]);
4549 +                               REG_WRITE(mrv_reg->isp_lsc_b_table_data, data);
4550 +                       }
4551 +                       REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_0,
4552 +                               ls_corr_config->ls_rdata_tbl
4553 +                               [n + CI_ISP_MAX_LSC_SECTORS]);
4554 +                       REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_1, 0);
4555 +                       REG_WRITE(mrv_reg->isp_lsc_r_table_data, data);
4556 +                       REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_0,
4557 +                               ls_corr_config->ls_gdata_tbl
4558 +                               [n + CI_ISP_MAX_LSC_SECTORS]);
4559 +                       REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_1, 0);
4560 +                       REG_WRITE(mrv_reg->isp_lsc_g_table_data, data);
4561 +                       REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_0,
4562 +                               ls_corr_config->ls_bdata_tbl
4563 +                               [n + CI_ISP_MAX_LSC_SECTORS]);
4564 +                       REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_1, 0);
4565 +                       REG_WRITE(mrv_reg->isp_lsc_b_table_data, data);
4566 +               }
4567 +
4568 +               /* program x size tables */
4569 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_01, MRV_LSC_X_SECT_SIZE_0,
4570 +                             ls_corr_config->ls_xsize_tbl[0]);
4571 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_01, MRV_LSC_X_SECT_SIZE_1,
4572 +                             ls_corr_config->ls_xsize_tbl[1]);
4573 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_23, MRV_LSC_X_SECT_SIZE_2,
4574 +                             ls_corr_config->ls_xsize_tbl[2]);
4575 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_23, MRV_LSC_X_SECT_SIZE_3,
4576 +                             ls_corr_config->ls_xsize_tbl[3]);
4577 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_45, MRV_LSC_X_SECT_SIZE_4,
4578 +                             ls_corr_config->ls_xsize_tbl[4]);
4579 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_45, MRV_LSC_X_SECT_SIZE_5,
4580 +                             ls_corr_config->ls_xsize_tbl[5]);
4581 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_67, MRV_LSC_X_SECT_SIZE_6,
4582 +                             ls_corr_config->ls_xsize_tbl[6]);
4583 +               REG_SET_SLICE(mrv_reg->isp_lsc_xsize_67, MRV_LSC_X_SECT_SIZE_7,
4584 +                             ls_corr_config->ls_xsize_tbl[7]);
4585 +
4586 +               /* program y size tables */
4587 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_01, MRV_LSC_Y_SECT_SIZE_0,
4588 +                             ls_corr_config->ls_ysize_tbl[0]);
4589 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_01, MRV_LSC_Y_SECT_SIZE_1,
4590 +                             ls_corr_config->ls_ysize_tbl[1]);
4591 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_23, MRV_LSC_Y_SECT_SIZE_2,
4592 +                             ls_corr_config->ls_ysize_tbl[2]);
4593 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_23, MRV_LSC_Y_SECT_SIZE_3,
4594 +                             ls_corr_config->ls_ysize_tbl[3]);
4595 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_45, MRV_LSC_Y_SECT_SIZE_4,
4596 +                             ls_corr_config->ls_ysize_tbl[4]);
4597 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_45, MRV_LSC_Y_SECT_SIZE_5,
4598 +                             ls_corr_config->ls_ysize_tbl[5]);
4599 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_67, MRV_LSC_Y_SECT_SIZE_6,
4600 +                             ls_corr_config->ls_ysize_tbl[6]);
4601 +               REG_SET_SLICE(mrv_reg->isp_lsc_ysize_67, MRV_LSC_Y_SECT_SIZE_7,
4602 +                             ls_corr_config->ls_ysize_tbl[7]);
4603 +
4604 +               /* program x grad tables */
4605 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_01, MRV_LSC_XGRAD_0,
4606 +                             ls_corr_config->ls_xgrad_tbl[0]);
4607 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_01, MRV_LSC_XGRAD_1,
4608 +                             ls_corr_config->ls_xgrad_tbl[1]);
4609 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_23, MRV_LSC_XGRAD_2,
4610 +                             ls_corr_config->ls_xgrad_tbl[2]);
4611 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_23, MRV_LSC_XGRAD_3,
4612 +                             ls_corr_config->ls_xgrad_tbl[3]);
4613 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_45, MRV_LSC_XGRAD_4,
4614 +                             ls_corr_config->ls_xgrad_tbl[4]);
4615 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_45, MRV_LSC_XGRAD_5,
4616 +                             ls_corr_config->ls_xgrad_tbl[5]);
4617 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_67, MRV_LSC_XGRAD_6,
4618 +                             ls_corr_config->ls_xgrad_tbl[6]);
4619 +               REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_67, MRV_LSC_XGRAD_7,
4620 +                             ls_corr_config->ls_xgrad_tbl[7]);
4621 +
4622 +               /* program y grad tables */
4623 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_01, MRV_LSC_YGRAD_0,
4624 +                             ls_corr_config->ls_ygrad_tbl[0]);
4625 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_01, MRV_LSC_YGRAD_1,
4626 +                             ls_corr_config->ls_ygrad_tbl[1]);
4627 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_23, MRV_LSC_YGRAD_2,
4628 +                             ls_corr_config->ls_ygrad_tbl[2]);
4629 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_23, MRV_LSC_YGRAD_3,
4630 +                             ls_corr_config->ls_ygrad_tbl[3]);
4631 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_45, MRV_LSC_YGRAD_4,
4632 +                             ls_corr_config->ls_ygrad_tbl[4]);
4633 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_45, MRV_LSC_YGRAD_5,
4634 +                             ls_corr_config->ls_ygrad_tbl[5]);
4635 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_67, MRV_LSC_YGRAD_6,
4636 +                             ls_corr_config->ls_ygrad_tbl[6]);
4637 +               REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_67, MRV_LSC_YGRAD_7,
4638 +                             ls_corr_config->ls_ygrad_tbl[7]);
4639 +
4640 +               if (enabled) {
4641 +                       /* switch on lens chading correction */
4642 +                       REG_SET_SLICE(mrv_reg->isp_lsc_ctrl,
4643 +                                     MRV_LSC_LSC_EN, ENABLE);
4644 +               }
4645 +       }
4646 +
4647 +       return CI_STATUS_SUCCESS;
4648 +}
4649 +
4650 +int ci_isp_ls_correction_on_off(int ls_corr_on_off)
4651 +{
4652 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4653 +
4654 +       if (ls_corr_on_off) {
4655 +               /* switch on lens chading correction */
4656 +               REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, ENABLE);
4657 +       } else {
4658 +               /* switch off lens chading correction */
4659 +               REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, DISABLE);
4660 +       }
4661 +
4662 +       return CI_STATUS_SUCCESS;
4663 +}
4664 +
4665 +/*
4666 + * Sets the Bad Pixel Correction configuration
4667 + */
4668 +int ci_isp_set_bp_correction(const struct ci_isp_bp_corr_config
4669 +                             *bp_corr_config)
4670 +{
4671 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4672 +       u32 isp_bp_ctrl = REG_READ(mrv_reg->isp_bp_ctrl);
4673 +
4674 +       if (!bp_corr_config) {
4675 +               /* disable correction module */
4676 +               REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, DISABLE);
4677 +               REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, DISABLE);
4678 +       } else {
4679 +               /* set bad pixel configuration */
4680 +               if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_DIRECT) {
4681 +                       /* direct detection */
4682 +                       u32 isp_bp_cfg1 = REG_READ(mrv_reg->isp_bp_cfg1);
4683 +                       u32 isp_bp_cfg2 = REG_READ(mrv_reg->isp_bp_cfg2);
4684 +
4685 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_COR_TYPE,
4686 +                                     MRV_BP_COR_TYPE_DIRECT);
4687 +
4688 +                       WARN_ON(!(!REG_GET_SLICE(mrv_reg->isp_bp_ctrl,
4689 +                                                MRV_BP_BP_DET_EN)));
4690 +
4691 +                       /* threshold register only used for direct mode */
4692 +                       REG_SET_SLICE(isp_bp_cfg1, MRV_BP_HOT_THRES,
4693 +                                     bp_corr_config->bp_abs_hot_thres);
4694 +                       REG_SET_SLICE(isp_bp_cfg1, MRV_BP_DEAD_THRES,
4695 +                                     bp_corr_config->bp_abs_dead_thres);
4696 +                       REG_WRITE(mrv_reg->isp_bp_cfg1, isp_bp_cfg1);
4697 +                       REG_SET_SLICE(isp_bp_cfg2, MRV_BP_DEV_HOT_THRES,
4698 +                                     bp_corr_config->bp_dev_hot_thres);
4699 +                       REG_SET_SLICE(isp_bp_cfg2, MRV_BP_DEV_DEAD_THRES,
4700 +                                     bp_corr_config->bp_dev_dead_thres);
4701 +                       REG_WRITE(mrv_reg->isp_bp_cfg2, isp_bp_cfg2);
4702 +               } else {
4703 +                       /* use bad pixel table */
4704 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_COR_TYPE,
4705 +                                     MRV_BP_COR_TYPE_TABLE);
4706 +               }
4707 +
4708 +               if (bp_corr_config->bp_corr_rep == CI_ISP_BP_CORR_REP_LIN) {
4709 +                       /* use linear approch */
4710 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_REP_APPR,
4711 +                                     MRV_BP_REP_APPR_INTERPOL);
4712 +               } else {
4713 +                       /* use best neighbour */
4714 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_REP_APPR,
4715 +                                     MRV_BP_REP_APPR_NEAREST);
4716 +               }
4717 +
4718 +               switch (bp_corr_config->bp_corr_mode) {
4719 +               case CI_ISP_BP_CORR_HOT_EN:
4720 +                       /* enable Hot */
4721 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, ENABLE);
4722 +                       /* disable Dead */
4723 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, DISABLE);
4724 +                       break;
4725 +               case CI_ISP_BP_CORR_DEAD_EN:
4726 +                       /* disable Hot */
4727 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, DISABLE);
4728 +                       /* enable Dead */
4729 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, ENABLE);
4730 +                       break;
4731 +               case CI_ISP_BP_CORR_HOT_DEAD_EN:
4732 +               default:
4733 +                       /* enable Hot */
4734 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, ENABLE);
4735 +                       /* enable Dead */
4736 +                       REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, ENABLE);
4737 +                       break;
4738 +               }
4739 +       }
4740 +
4741 +       REG_WRITE(mrv_reg->isp_bp_ctrl, isp_bp_ctrl);
4742 +
4743 +       return CI_STATUS_SUCCESS;
4744 +
4745 +}
4746 +
4747 +/*
4748 + * Sets the Bad Pixel configuration for detection
4749 + */
4750 +int ci_isp_set_bp_detection(const struct ci_isp_bp_det_config *bp_det_config)
4751 +{
4752 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4753 +
4754 +       if (!bp_det_config) {
4755 +               /* disable measurement module */
4756 +               REG_SET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_BP_DET_EN, DISABLE);
4757 +       } else {
4758 +               WARN_ON(!(REG_GET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_COR_TYPE)
4759 +                         == MRV_BP_COR_TYPE_TABLE));
4760 +
4761 +               /* set dead threshold for bad pixel detection */
4762 +               REG_SET_SLICE(mrv_reg->isp_bp_cfg1, MRV_BP_DEAD_THRES,
4763 +                             bp_det_config->bp_dead_thres);
4764 +
4765 +               /* enable measurement module */
4766 +               REG_SET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_BP_DET_EN, ENABLE);
4767 +       }
4768 +
4769 +       return CI_STATUS_SUCCESS;
4770 +}
4771 +
4772 +int ci_isp_clear_bp_int(void)
4773 +{
4774 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4775 +
4776 +       /* clear bp_det irq (only if it is signalled to prevent loss of irqs) */
4777 +       if (REG_GET_SLICE(mrv_reg->isp_ris, MRV_ISP_RIS_BP_DET))
4778 +               REG_SET_SLICE(mrv_reg->isp_icr, MRV_ISP_ICR_BP_DET, 1);
4779 +
4780 +       return CI_STATUS_SUCCESS;
4781 +}
4782 +
4783 +/*
4784 + * Initializes Isp filter registers with default reset values.
4785 + */
4786 +static int ci_isp_initialize_filter_registers(void)
4787 +{
4788 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4789 +
4790 +       mrv_reg->isp_filt_mode = 0x00000000;
4791 +       mrv_reg->isp_filt_fac_sh1 = 0x00000010;
4792 +       mrv_reg->isp_filt_fac_sh0 = 0x0000000C;
4793 +       mrv_reg->isp_filt_fac_mid = 0x0000000A;
4794 +       mrv_reg->isp_filt_fac_bl0 = 0x00000006;
4795 +       mrv_reg->isp_filt_fac_bl1 = 0x00000002;
4796 +       mrv_reg->isp_filt_thresh_bl0 = 0x0000000D;
4797 +       mrv_reg->isp_filt_thresh_bl1 = 0x00000005;
4798 +       mrv_reg->isp_filt_thresh_sh0 = 0x0000001A;
4799 +       mrv_reg->isp_filt_thresh_sh1 = 0x0000002C;
4800 +       mrv_reg->isp_filt_lum_weight = 0x00032040;
4801 +
4802 +       return CI_STATUS_SUCCESS;
4803 +}
4804 +
4805 +int ci_isp_activate_filter(int activate_filter)
4806 +{
4807 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4808 +       int retval = CI_STATUS_SUCCESS;
4809 +
4810 +       /* Initialize ISP filter control registers first */
4811 +       retval = ci_isp_initialize_filter_registers();
4812 +       if (retval != CI_STATUS_SUCCESS)
4813 +               return retval;
4814 +
4815 +       /* Activate or deactivate filter algorythm */
4816 +       REG_SET_SLICE(mrv_reg->isp_filt_mode, MRV_FILT_FILT_ENABLE,
4817 +               (activate_filter) ? ENABLE : DISABLE);
4818 +
4819 +       return retval;
4820 +}
4821 +
4822 +/*
4823 + * Write coefficient and threshold values into Isp filter
4824 + * registers for noise, sharpness and blurring filtering.
4825 + */
4826 +int ci_isp_set_filter_params(u8 noise_reduc_level, u8 sharp_level)
4827 +{
4828 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4829 +       u32 isp_filt_mode = 0;
4830 +
4831 +       if (!REG_GET_SLICE(mrv_reg->isp_filt_mode, MRV_FILT_FILT_ENABLE))
4832 +               return CI_STATUS_CANCELED;
4833 +
4834 +       REG_WRITE(mrv_reg->isp_filt_mode, isp_filt_mode);
4835 +
4836 +       if (((noise_reduc_level <= 10) || (noise_reduc_level == 99))
4837 +           && (sharp_level <= 10)) {
4838 +               switch (noise_reduc_level) {
4839 +               /* Test Mode */
4840 +               case 99:
4841 +                       /* 10 bit max value */
4842 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4843 +                                     MRV_FILT_FILT_THRESH_SH1, 0x000003FF);
4844 +                       /* 10 bit max value */
4845 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4846 +                                     MRV_FILT_FILT_THRESH_SH0, 0x000003FF);
4847 +                       /* 10 bit max value */
4848 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4849 +                                     MRV_FILT_FILT_THRESH_BL0, 0x000003FF);
4850 +                       /* 10 bit max value */
4851 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4852 +                                     MRV_FILT_FILT_THRESH_BL1, 0x000003FF);
4853 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 0
4854 +                               /* MRV_FILT_STAGE1_SELECT_MAX_BLUR */);
4855 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4856 +                                     MRV_FILT_FILT_CHR_V_MODE_BYPASS);
4857 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4858 +                                     MRV_FILT_FILT_CHR_H_MODE_BYPASS);
4859 +                       break;
4860 +
4861 +               case 0:
4862 +               /* NoiseReductionLevel = 0 */
4863 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4864 +                                     MRV_FILT_FILT_THRESH_SH1, 0x000000);
4865 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4866 +                                     MRV_FILT_FILT_THRESH_SH0, 0x000000);
4867 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4868 +                                     MRV_FILT_FILT_THRESH_BL0, 0x000000);
4869 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4870 +                                     MRV_FILT_FILT_THRESH_BL1, 0x000000);
4871 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 6);
4872 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4873 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC8);
4874 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4875 +                                     MRV_FILT_FILT_CHR_H_MODE_BYPASS);
4876 +                       break;
4877 +
4878 +               case 1:
4879 +               /* NoiseReductionLevel = 1; */
4880 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4881 +                                     MRV_FILT_FILT_THRESH_SH1, 33);
4882 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4883 +                                     MRV_FILT_FILT_THRESH_SH0, 18);
4884 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4885 +                                     MRV_FILT_FILT_THRESH_BL0, 8);
4886 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4887 +                                     MRV_FILT_FILT_THRESH_BL1, 2);
4888 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 6);
4889 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4890 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4891 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4892 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4893 +                       break;
4894 +
4895 +               case 2:
4896 +               /* NoiseReductionLevel = 2; */
4897 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4898 +                                     MRV_FILT_FILT_THRESH_SH1, 44);
4899 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4900 +                                     MRV_FILT_FILT_THRESH_SH0, 26);
4901 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4902 +                                     MRV_FILT_FILT_THRESH_BL0, 13);
4903 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4904 +                                     MRV_FILT_FILT_THRESH_BL1, 5);
4905 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 4
4906 +                               /* MRV_FILT_STAGE1_SELECT_DEFAULT */);
4907 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4908 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4909 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4910 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4911 +                       break;
4912 +
4913 +               case 3:
4914 +               /* NoiseReductionLevel = 3; */
4915 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4916 +                                     MRV_FILT_FILT_THRESH_SH1, 51);
4917 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4918 +                                     MRV_FILT_FILT_THRESH_SH0, 36);
4919 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4920 +                                     MRV_FILT_FILT_THRESH_BL0, 23);
4921 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4922 +                                     MRV_FILT_FILT_THRESH_BL1, 10);
4923 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 4
4924 +                               /* MRV_FILT_STAGE1_SELECT_DEFAULT */);
4925 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4926 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4927 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4928 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4929 +                       break;
4930 +
4931 +               case 4:
4932 +               /* NoiseReductionLevel = 4; */
4933 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4934 +                                     MRV_FILT_FILT_THRESH_SH1, 67);
4935 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4936 +                                     MRV_FILT_FILT_THRESH_SH0, 41);
4937 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4938 +                                     MRV_FILT_FILT_THRESH_BL0, 26);
4939 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4940 +                                     MRV_FILT_FILT_THRESH_BL1, 15);
4941 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 3);
4942 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4943 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4944 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4945 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4946 +                       break;
4947 +
4948 +               case 5:
4949 +               /* NoiseReductionLevel = 5; */
4950 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4951 +                                     MRV_FILT_FILT_THRESH_SH1, 100);
4952 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4953 +                                     MRV_FILT_FILT_THRESH_SH0, 75);
4954 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4955 +                                     MRV_FILT_FILT_THRESH_BL0, 50);
4956 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4957 +                                     MRV_FILT_FILT_THRESH_BL1, 20);
4958 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 3);
4959 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4960 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4961 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4962 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4963 +                       break;
4964 +
4965 +               case 6:
4966 +               /* NoiseReductionLevel = 6; */
4967 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4968 +                                     MRV_FILT_FILT_THRESH_SH1, 120);
4969 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4970 +                                     MRV_FILT_FILT_THRESH_SH0, 90);
4971 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4972 +                                     MRV_FILT_FILT_THRESH_BL0, 60);
4973 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4974 +                                     MRV_FILT_FILT_THRESH_BL1, 26);
4975 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 2);
4976 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4977 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4978 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4979 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4980 +                       break;
4981 +
4982 +               case 7:
4983 +               /* NoiseReductionLevel = 7; */
4984 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
4985 +                                     MRV_FILT_FILT_THRESH_SH1, 150);
4986 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
4987 +                                     MRV_FILT_FILT_THRESH_SH0, 120);
4988 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
4989 +                                     MRV_FILT_FILT_THRESH_BL0, 80);
4990 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
4991 +                                     MRV_FILT_FILT_THRESH_BL1, 51);
4992 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 2);
4993 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
4994 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
4995 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
4996 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
4997 +                       break;
4998 +
4999 +               case 8:
5000 +               /* NoiseReductionLevel = 8; */
5001 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5002 +                                     MRV_FILT_FILT_THRESH_SH1, 200);
5003 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
5004 +                                     MRV_FILT_FILT_THRESH_SH0, 170);
5005 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
5006 +                                     MRV_FILT_FILT_THRESH_BL0, 140);
5007 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
5008 +                                     MRV_FILT_FILT_THRESH_BL1, 100);
5009 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 2);
5010 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
5011 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
5012 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
5013 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
5014 +                       break;
5015 +
5016 +               case 9:
5017 +               /* NoiseReductionLevel = 9; */
5018 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5019 +                                     MRV_FILT_FILT_THRESH_SH1, 300);
5020 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
5021 +                                     MRV_FILT_FILT_THRESH_SH0, 250);
5022 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
5023 +                                     MRV_FILT_FILT_THRESH_BL0, 180);
5024 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
5025 +                                     MRV_FILT_FILT_THRESH_BL1, 150);
5026 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT,
5027 +                                     (sharp_level > 3) ? 2 : 1);
5028 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
5029 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
5030 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
5031 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
5032 +                       break;
5033 +
5034 +               case 10:
5035 +               /* NoiseReductionLevel = 10; extrem noise */
5036 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5037 +                                     MRV_FILT_FILT_THRESH_SH1, 1023);
5038 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
5039 +                                     MRV_FILT_FILT_THRESH_SH0, 1023);
5040 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0,
5041 +                                     MRV_FILT_FILT_THRESH_BL0, 1023);
5042 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1,
5043 +                                     MRV_FILT_FILT_THRESH_BL1, 1023);
5044 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT,
5045 +                                     (sharp_level > 5) ? 2 :
5046 +                                     ((sharp_level > 3) ? 1 : 0));
5047 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE,
5048 +                                     MRV_FILT_FILT_CHR_V_MODE_STATIC12);
5049 +                       REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE,
5050 +                                     MRV_FILT_FILT_CHR_H_MODE_DYN_2);
5051 +                       break;
5052 +
5053 +               default:
5054 +                       return CI_STATUS_OUTOFRANGE;
5055 +               }
5056 +
5057 +               switch (sharp_level) {
5058 +               /* SharpLevel = 0; no sharp enhancement */
5059 +               case 0:
5060 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5061 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000004);
5062 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5063 +                                     MRV_FILT_FILT_FAC_SH0, 0x00000004);
5064 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5065 +                                     MRV_FILT_FILT_FAC_MID, 0x00000004);
5066 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5067 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000002);
5068 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5069 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000000);
5070 +                       break;
5071 +
5072 +               /* SharpLevel = 1; */
5073 +               case 1:
5074 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5075 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000008);
5076 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5077 +                                     MRV_FILT_FILT_FAC_SH0, 0x00000007);
5078 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5079 +                                     MRV_FILT_FILT_FAC_MID, 0x00000006);
5080 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5081 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000002);
5082 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5083 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000000);
5084 +                       break;
5085 +
5086 +               /* SharpLevel = 2; */
5087 +               case 2:
5088 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5089 +                                     MRV_FILT_FILT_FAC_SH1, 0x0000000C);
5090 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5091 +                                     MRV_FILT_FILT_FAC_SH0, 0x0000000A);
5092 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5093 +                                     MRV_FILT_FILT_FAC_MID, 0x00000008);
5094 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5095 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000004);
5096 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5097 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000000);
5098 +                       break;
5099 +
5100 +               /* SharpLevel = 3; */
5101 +               case 3:
5102 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5103 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000010);
5104 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5105 +                                     MRV_FILT_FILT_FAC_SH0, 0x0000000C);
5106 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5107 +                                     MRV_FILT_FILT_FAC_MID, 0x0000000A);
5108 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5109 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000006);
5110 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5111 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000002);
5112 +                       break;
5113 +
5114 +               /* SharpLevel = 4; */
5115 +               case 4:
5116 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5117 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000016);
5118 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5119 +                                     MRV_FILT_FILT_FAC_SH0, 0x00000010);
5120 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5121 +                                     MRV_FILT_FILT_FAC_MID, 0x0000000C);
5122 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5123 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000008);
5124 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5125 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000004);
5126 +                       break;
5127 +
5128 +               /* SharpLevel = 5; */
5129 +               case 5:
5130 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5131 +                                     MRV_FILT_FILT_FAC_SH1, 0x0000001B);
5132 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5133 +                                     MRV_FILT_FILT_FAC_SH0, 0x00000014);
5134 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5135 +                                     MRV_FILT_FILT_FAC_MID, 0x00000010);
5136 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5137 +                                     MRV_FILT_FILT_FAC_BL0, 0x0000000A);
5138 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5139 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000004);
5140 +                       break;
5141 +
5142 +               /* SharpLevel = 6; */
5143 +               case 6:
5144 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5145 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000020);
5146 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5147 +                                     MRV_FILT_FILT_FAC_SH0, 0x0000001A);
5148 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5149 +                                     MRV_FILT_FILT_FAC_MID, 0x00000013);
5150 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5151 +                                     MRV_FILT_FILT_FAC_BL0, 0x0000000C);
5152 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5153 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000006);
5154 +                       break;
5155 +
5156 +               /* SharpLevel = 7; */
5157 +               case 7:
5158 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5159 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000026);
5160 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5161 +                                     MRV_FILT_FILT_FAC_SH0, 0x0000001E);
5162 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5163 +                                     MRV_FILT_FILT_FAC_MID, 0x00000017);
5164 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5165 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000010);
5166 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5167 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000008);
5168 +                       break;
5169 +
5170 +               /* SharpLevel = 8; */
5171 +               case 8:
5172 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
5173 +                                     MRV_FILT_FILT_THRESH_SH0, 0x00000013);
5174 +                       if (REG_GET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5175 +                            MRV_FILT_FILT_THRESH_SH1) > 0x0000008A) {
5176 +                               REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5177 +                                             MRV_FILT_FILT_THRESH_SH1,
5178 +                                             0x0000008A);
5179 +                       }
5180 +                       /* 43 */
5181 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5182 +                                     MRV_FILT_FILT_FAC_SH1, 0x0000002C);
5183 +                       /* 36 */
5184 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5185 +                                     MRV_FILT_FILT_FAC_SH0, 0x00000024);
5186 +                       /* 29 */
5187 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5188 +                                     MRV_FILT_FILT_FAC_MID, 0x0000001D);
5189 +                       /* 21 */
5190 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5191 +                                     MRV_FILT_FILT_FAC_BL0, 0x00000015);
5192 +                       /* 14 */
5193 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5194 +                                     MRV_FILT_FILT_FAC_BL1, 0x0000000D);
5195 +                       break;
5196 +
5197 +               /* SharpLevel = 9; */
5198 +               case 9:
5199 +                       REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
5200 +                                     MRV_FILT_FILT_THRESH_SH0, 0x00000013);
5201 +                       if (REG_GET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5202 +                               MRV_FILT_FILT_THRESH_SH1) > 0x0000008A) {
5203 +                               REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5204 +                                             MRV_FILT_FILT_THRESH_SH1,
5205 +                                             0x0000008A);
5206 +                       }
5207 +                       /* 48 */
5208 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5209 +                                     MRV_FILT_FILT_FAC_SH1, 0x00000030);
5210 +                       /* 42 */
5211 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5212 +                                     MRV_FILT_FILT_FAC_SH0, 0x0000002A);
5213 +                       /* 34 */
5214 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5215 +                                     MRV_FILT_FILT_FAC_MID, 0x00000022);
5216 +                       /* 26 */
5217 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5218 +                                     MRV_FILT_FILT_FAC_BL0, 0x0000001A);
5219 +                       /* 20 */
5220 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5221 +                                     MRV_FILT_FILT_FAC_BL1, 0x00000014);
5222 +                       break;
5223 +
5224 +               /* SharpLevel = 10; */
5225 +               case 10:
5226 +                       /* REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0,
5227 +                       * MRV_FILT_FILT_THRESH_SH0, 0x00000013); */
5228 +                       /* if (REG_GET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5229 +                       * MRV_FILT_FILT_THRESH_SH1) > 0x0000008A) */
5230 +                       /* { */
5231 +                       /* REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5232 +                       * MRV_FILT_FILT_THRESH_SH1,   0x0000008A); */
5233 +                       /* } */
5234 +
5235 +                       /* 63 */
5236 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5237 +                               MRV_FILT_FILT_FAC_SH1, 0x0000003F);
5238 +                       /* 48 */
5239 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5240 +                               MRV_FILT_FILT_FAC_SH0, 0x00000030);
5241 +                       /* 40 */
5242 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5243 +                               MRV_FILT_FILT_FAC_MID, 0x00000028);
5244 +                       /* 36 */
5245 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5246 +                               MRV_FILT_FILT_FAC_BL0, 0x00000024);
5247 +                       /* 32 */
5248 +                       REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5249 +                               MRV_FILT_FILT_FAC_BL1, 0x00000020);
5250 +                       break;
5251 +
5252 +               default:
5253 +                       return CI_STATUS_OUTOFRANGE;
5254 +               }
5255 +
5256 +               if (noise_reduc_level > 7) {
5257 +                       if (sharp_level > 7) {
5258 +                               u32 filt_fac_bl0 = REG_GET_SLICE
5259 +                                       (mrv_reg->isp_filt_fac_bl0,
5260 +                                       MRV_FILT_FILT_FAC_BL0);
5261 +                               u32 filt_fac_bl1 =
5262 +                                   REG_GET_SLICE(mrv_reg->isp_filt_fac_bl1,
5263 +                                       MRV_FILT_FILT_FAC_BL1);
5264 +                               /* * 0.50 */
5265 +                               REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5266 +                                       MRV_FILT_FILT_FAC_BL0,
5267 +                                       (filt_fac_bl0) >> 1);
5268 +                               /* * 0.25 */
5269 +                               REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5270 +                                       MRV_FILT_FILT_FAC_BL1,
5271 +                                       (filt_fac_bl1) >> 2);
5272 +                       } else if (sharp_level > 4) {
5273 +                               u32 filt_fac_bl0 =
5274 +                                   REG_GET_SLICE(mrv_reg->isp_filt_fac_bl0,
5275 +                                       MRV_FILT_FILT_FAC_BL0);
5276 +                               u32 filt_fac_bl1 =
5277 +                                   REG_GET_SLICE(mrv_reg->
5278 +                                                 isp_filt_fac_bl1,
5279 +                                                 MRV_FILT_FILT_FAC_BL1);
5280 +                               /* * 0.75 */
5281 +                               REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5282 +                                       MRV_FILT_FILT_FAC_BL0,
5283 +                                       (filt_fac_bl0 * 3) >> 2);
5284 +                               /* * 0.50 */
5285 +                               REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5286 +                                       MRV_FILT_FILT_FAC_BL1,
5287 +                                       (filt_fac_bl1) >> 1);
5288 +                       }
5289 +               }
5290 +
5291 +               /* Set ISP filter mode register values */
5292 +               REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_MODE,
5293 +                             MRV_FILT_FILT_MODE_DYNAMIC);
5294 +
5295 +               /* enable filter */
5296 +               REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_ENABLE, ENABLE);
5297 +               REG_WRITE(mrv_reg->isp_filt_mode, isp_filt_mode);
5298 +
5299 +               return CI_STATUS_SUCCESS;
5300 +       } else {
5301 +               /* At least one function parameter is out of range */
5302 +               return CI_STATUS_OUTOFRANGE;
5303 +       }
5304 +}
5305 +
5306 +int ci_isp_meas_exposure_initialize_module(void)
5307 +{
5308 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5309 +
5310 +       REG_SET_SLICE(mrv_reg->isp_exp_h_size, MRV_AE_ISP_EXP_H_SIZE, 0);
5311 +       REG_SET_SLICE(mrv_reg->isp_exp_v_size, MRV_AE_ISP_EXP_V_SIZE, 0);
5312 +       REG_SET_SLICE(mrv_reg->isp_exp_h_offset, MRV_AE_ISP_EXP_H_OFFSET, 0);
5313 +       REG_SET_SLICE(mrv_reg->isp_exp_v_offset, MRV_AE_ISP_EXP_V_OFFSET, 0);
5314 +
5315 +       return CI_STATUS_SUCCESS;
5316 +
5317 +}
5318 +
5319 +/*
5320 + * Configures the exposure measurement module.
5321 + */
5322 +int ci_isp_meas_exposure_set_config(const struct ci_isp_window *wnd,
5323 +                                   const struct ci_isp_exp_ctrl *isp_exp_ctrl)
5324 +{
5325 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5326 +
5327 +       if (!wnd) {
5328 +               /* stop loop if running */
5329 +               REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_AUTOSTOP, ON);
5330 +               /* required? */
5331 +               REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_START, OFF);
5332 +               return CI_STATUS_SUCCESS;
5333 +       }
5334 +
5335 +       /* range check */
5336 +       if ((wnd->hoffs > MRV_AE_ISP_EXP_H_OFFSET_MAX)
5337 +           || (wnd->hsize > MRV_AE_ISP_EXP_H_SIZE_MAX)
5338 +           || (wnd->voffs > MRV_AE_ISP_EXP_V_OFFSET_MAX)
5339 +           || (wnd->vsize > MRV_AE_ISP_EXP_V_SIZE_MAX)
5340 +           || (wnd->vsize & ~MRV_AE_ISP_EXP_V_SIZE_VALID_MASK))
5341 +               return CI_STATUS_OUTOFRANGE;
5342 +
5343 +       /* configure measurement windows */
5344 +       REG_SET_SLICE(mrv_reg->isp_exp_h_size, MRV_AE_ISP_EXP_H_SIZE,
5345 +                     wnd->hsize);
5346 +       REG_SET_SLICE(mrv_reg->isp_exp_v_size, MRV_AE_ISP_EXP_V_SIZE,
5347 +                     wnd->vsize);
5348 +       REG_SET_SLICE(mrv_reg->isp_exp_h_offset, MRV_AE_ISP_EXP_H_OFFSET,
5349 +                     wnd->hoffs);
5350 +       REG_SET_SLICE(mrv_reg->isp_exp_v_offset, MRV_AE_ISP_EXP_V_OFFSET,
5351 +                     wnd->voffs);
5352 +
5353 +       /* set exposure measurement mode */
5354 +       REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_MEAS_MODE,
5355 +               (isp_exp_ctrl->exp_meas_mode) ? ON : OFF);
5356 +
5357 +       /* set or clear AE autostop bit */
5358 +       REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_AUTOSTOP,
5359 +                     (isp_exp_ctrl->auto_stop) ? ON : OFF);
5360 +       REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_START,
5361 +                     (isp_exp_ctrl->exp_start) ? ON : OFF);
5362 +
5363 +       return CI_STATUS_SUCCESS;
5364 +}
5365 +
5366 +/*
5367 + * Programs the given gamma curve for the input gamma
5368 + * block. Enables or disables gamma processing for the
5369 + * input gamma block.
5370 + */
5371 +void ci_isp_set_gamma(const struct ci_sensor_gamma_curve *r,
5372 +                     const struct ci_sensor_gamma_curve *g,
5373 +                     const struct ci_sensor_gamma_curve *b)
5374 +{
5375 +       struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE;
5376 +       /* values stored as 16bit - use MSBs if cambuswidth is smaller */
5377 +       const u8 shift_val = 16 - MARVIN_FEATURE_CAMBUSWIDTH;
5378 +       /* used to round up values */
5379 +       const u16 round_ofs = 0 << (shift_val - 1);
5380 +       s32 i;
5381 +
5382 +       if (r) {
5383 +
5384 +               /*
5385 +                * Note: gamma curve increments are already register conform,
5386 +                * so REG_WRITE is used instead of REG_SET_SLICE
5387 +                */
5388 +
5389 +               /*
5390 +                * better would be split into 16 separate values to be
5391 +                * register independant
5392 +                */
5393 +
5394 +               /* gamma curve dx1..dx16 increments (each nibble of */
5395 +               REG_WRITE(mrv_reg->isp_gamma_dx_lo, r->gamma_dx0);
5396 +               /* the 32bit-values hold 3 valid bits, see register) */
5397 +               REG_WRITE(mrv_reg->isp_gamma_dx_hi, r->gamma_dx1);
5398 +
5399 +               for (i = 0; i < MRV_ISP_GAMMA_R_Y_ARR_SIZE; i++) {
5400 +                       REG_SET_SLICE(mrv_reg->isp_gamma_r_y[i],
5401 +                             MRV_ISP_GAMMA_R_Y,
5402 +                             (r->isp_gamma_y[i] + round_ofs) >> shift_val);
5403 +                       REG_SET_SLICE(mrv_reg->isp_gamma_g_y[i],
5404 +                             MRV_ISP_GAMMA_G_Y,
5405 +                             (g->isp_gamma_y[i] + round_ofs) >> shift_val);
5406 +                       REG_SET_SLICE(mrv_reg->isp_gamma_b_y[i],
5407 +                             MRV_ISP_GAMMA_B_Y,
5408 +                             (b->isp_gamma_y[i] + round_ofs) >> shift_val);
5409 +               }
5410 +
5411 +               REG_SET_SLICE(mrv_reg->isp_ctrl,
5412 +               MRV_ISP_ISP_GAMMA_IN_ENABLE, ENABLE);
5413 +       } else {
5414 +               REG_SET_SLICE(mrv_reg->isp_ctrl,
5415 +               MRV_ISP_ISP_GAMMA_IN_ENABLE, DISABLE);
5416 +       }
5417 +}
5418 +
5419 +/*
5420 + * Programs the given gamma curve for the output gamma
5421 + * block. Enables or disables gamma processing for the
5422 + * output gamma block.
5423 + */
5424 +void ci_isp_set_gamma2(const struct ci_isp_gamma_out_curve *gamma)
5425 +{
5426 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5427 +       s32 i;
5428 +
5429 +       if (gamma) {
5430 +               WARN_ON(!(MRV_ISP_GAMMA_OUT_Y_ARR_SIZE ==
5431 +                       CI_ISP_GAMMA_OUT_CURVE_ARR_SIZE));
5432 +
5433 +               for (i = 0; i < MRV_ISP_GAMMA_OUT_Y_ARR_SIZE; i++) {
5434 +                       REG_SET_SLICE(mrv_reg->isp_gamma_out_y[i],
5435 +                                     MRV_ISP_ISP_GAMMA_OUT_Y,
5436 +                                     gamma->isp_gamma_y[i]);
5437 +               }
5438 +
5439 +               /* gamma curve linear or log */
5440 +               REG_SET_SLICE(mrv_reg->isp_gamma_out_mode, MRV_ISP_EQU_SEGM,
5441 +                             gamma->gamma_segmentation);
5442 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GAMMA_OUT_ENABLE,
5443 +                             ENABLE);
5444 +       } else {
5445 +               REG_SET_SLICE(mrv_reg->isp_ctrl,
5446 +               MRV_ISP_ISP_GAMMA_OUT_ENABLE, DISABLE);
5447 +       }
5448 +
5449 +}
5450 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c b/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c
5451 new file mode 100644
5452 index 0000000..c042e06
5453 --- /dev/null
5454 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c
5455 @@ -0,0 +1,569 @@
5456 +/*
5457 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
5458 + *
5459 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
5460 + *
5461 + * Copyright (c) Silicon Image 2008  www.siliconimage.com
5462 + *
5463 + * This program is free software; you can redistribute it and/or
5464 + * modify it under the terms of the GNU General Public License version
5465 + * 2 as published by the Free Software Foundation.
5466 + *
5467 + * This program is distributed in the hope that it will be useful,
5468 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5469 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5470 + * GNU General Public License for more details.
5471 + *
5472 + * You should have received a copy of the GNU General Public License
5473 + * along with this program; if not, write to the Free Software
5474 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
5475 + * 02110-1301, USA.
5476 + *
5477 + *
5478 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
5479 + */
5480 +
5481 +#include "mrstisp_stdinc.h"
5482 +
5483 +int ci_isp_jpe_init_ex(u16 hsize, u16 vsize, u8 compression_ratio, u8 jpe_scale)
5484 +{
5485 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5486 +
5487 +       /*
5488 +        * Reset JPEG-Encoder. In contrast to other software resets
5489 +        * this triggers the modules asynchronous reset resulting
5490 +        * in loss of all data.
5491 +        */
5492 +
5493 +       REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_JPEG_SOFT_RST, ON);
5494 +       REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_JPEG_SOFT_RST, OFF);
5495 +
5496 +       /* set configuration for the Jpeg capturing */
5497 +       ci_isp_jpe_set_config(hsize, vsize, jpe_scale);
5498 +
5499 +       /*
5500 +        * Sleep a while before setting up tables because of the 400
5501 +        * clock cycles required to initialize the table RAM after a
5502 +        * reset was issued. On FPGA we are running with only 30MHz,
5503 +        * so at least 13us are required.
5504 +        */
5505 +
5506 +
5507 +       /*
5508 +        * Note: this func is called when holding spin lock,
5509 +        * so can not change to msleep.
5510 +        */
5511 +       mdelay(15);
5512 +
5513 +       /* program tables */
5514 +       ci_isp_jpe_set_tables(compression_ratio);
5515 +
5516 +       /* choose tables */
5517 +       ci_isp_jpe_select_tables();
5518 +
5519 +       return CI_STATUS_SUCCESS;
5520 +}
5521 +
5522 +/*
5523 + * initialization of JPEG encoder
5524 + */
5525 +int ci_isp_jpe_init(u32 resolution, u8 compression_ratio, int jpe_scale)
5526 +{
5527 +       u16 hsize = 0;
5528 +       u16 vsize = 0;
5529 +
5530 +       switch (resolution) {
5531 +       case SENSOR_RES_BP1:
5532 +               /* 352; */
5533 +               hsize = BP1_SIZE_H;
5534 +               /* 240; */
5535 +               vsize = BP1_SIZE_V;
5536 +               break;
5537 +       case SENSOR_RES_S_AFM:
5538 +               /* 64; */
5539 +               hsize = S_AFM_SIZE_H;
5540 +               /* 32; */
5541 +               vsize = S_AFM_SIZE_V;
5542 +               break;
5543 +       case SENSOR_RES_M_AFM:
5544 +               /* 128; */
5545 +               hsize = M_AFM_SIZE_H;
5546 +               /* 96; */
5547 +               vsize = M_AFM_SIZE_V;
5548 +               break;
5549 +       case SENSOR_RES_L_AFM:
5550 +               /* 720; */
5551 +               hsize = L_AFM_SIZE_H;
5552 +               /* 480; */
5553 +               vsize = L_AFM_SIZE_V;
5554 +               break;
5555 +       case SENSOR_RES_QQCIF:
5556 +               /* 88; */
5557 +               hsize = QQCIF_SIZE_H;
5558 +               /* 72; */
5559 +               vsize = QQCIF_SIZE_V;
5560 +               break;
5561 +       case SENSOR_RES_QQVGA:
5562 +               /* 160; */
5563 +               hsize = QQVGA_SIZE_H;
5564 +               /* 120; */
5565 +               vsize = QQVGA_SIZE_V;
5566 +               break;
5567 +       case SENSOR_RES_QCIF:
5568 +               /* 176; */
5569 +               hsize = QCIF_SIZE_H;
5570 +               /* 144; */
5571 +               vsize = QCIF_SIZE_V;
5572 +               break;
5573 +       case SENSOR_RES_QVGA:
5574 +               /* 320; */
5575 +               hsize = QVGA_SIZE_H;
5576 +               /* 240; */
5577 +               vsize = QVGA_SIZE_V;
5578 +               break;
5579 +       case SENSOR_RES_CIF:
5580 +               /* 352; */
5581 +               hsize = CIF_SIZE_H;
5582 +               /* 288; */
5583 +               vsize = CIF_SIZE_V;
5584 +               break;
5585 +       case SENSOR_RES_VGA:
5586 +               /* 640; */
5587 +               hsize = VGA_SIZE_H;
5588 +               /* 480; */
5589 +               vsize = VGA_SIZE_V;
5590 +               break;
5591 +       case SENSOR_RES_SVGA:
5592 +               /* 800; */
5593 +               hsize = SVGA_SIZE_H;
5594 +               /* 600; */
5595 +               vsize = SVGA_SIZE_V;
5596 +               break;
5597 +       case SENSOR_RES_XGA:
5598 +               /* 1024; */
5599 +               hsize = XGA_SIZE_H;
5600 +               /* 768; */
5601 +               vsize = XGA_SIZE_V;
5602 +               break;
5603 +       case SENSOR_RES_XGA_PLUS:
5604 +               /* 1280; */
5605 +               hsize = XGA_PLUS_SIZE_H;
5606 +               /* 960; */
5607 +               vsize = XGA_PLUS_SIZE_V;
5608 +               break;
5609 +       case SENSOR_RES_SXGA:
5610 +               /* 1280; */
5611 +               hsize = SXGA_SIZE_H;
5612 +               /* 1024; */
5613 +               vsize = SXGA_SIZE_V;
5614 +               break;
5615 +       case SENSOR_RES_UXGA:
5616 +               /* 1600; */
5617 +               hsize = UXGA_SIZE_H;
5618 +               /* 1200; */
5619 +               vsize = UXGA_SIZE_V;
5620 +               break;
5621 +       case SENSOR_RES_QXGA:
5622 +               /* 2048; */
5623 +               hsize = QXGA_SIZE_H;
5624 +               /* 1536; */
5625 +               vsize = QXGA_SIZE_V;
5626 +               break;
5627 +       case SENSOR_RES_QSXGA:
5628 +               /* 2586; */
5629 +               hsize = QSXGA_SIZE_H;
5630 +               /* 2048; */
5631 +               vsize = QSXGA_SIZE_V;
5632 +               break;
5633 +       case SENSOR_RES_QSXGA_PLUS:
5634 +               /* 2600; */
5635 +               hsize = QSXGA_PLUS_SIZE_H;
5636 +               /* 2048; */
5637 +               vsize = QSXGA_PLUS_SIZE_V;
5638 +               break;
5639 +       case SENSOR_RES_QSXGA_PLUS2:
5640 +               /* 2600; */
5641 +               hsize = QSXGA_PLUS2_SIZE_H;
5642 +               /* 1950; */
5643 +               vsize = QSXGA_PLUS2_SIZE_V;
5644 +               break;
5645 +       case SENSOR_RES_QSXGA_PLUS3:
5646 +               /* 2686; */
5647 +               hsize = QSXGA_PLUS3_SIZE_H;
5648 +               /* 2048; */
5649 +               vsize = QSXGA_PLUS3_SIZE_V;
5650 +               break;
5651 +       case SENSOR_RES_WQSXGA:
5652 +               /* 3200 */
5653 +               hsize = WQSXGA_SIZE_H;
5654 +               /* 2048 */
5655 +               vsize = WQSXGA_SIZE_V;
5656 +               break;
5657 +       case SENSOR_RES_QUXGA:
5658 +               /* 3200 */
5659 +               hsize = QUXGA_SIZE_H;
5660 +               /* 2400 */
5661 +               vsize = QUXGA_SIZE_V;
5662 +               break;
5663 +       case SENSOR_RES_WQUXGA:
5664 +               /* 3840 */
5665 +               hsize = WQUXGA_SIZE_H;
5666 +               /* 2400 */
5667 +               vsize = WQUXGA_SIZE_V;
5668 +               break;
5669 +       case SENSOR_RES_HXGA:
5670 +               /* 4096 */
5671 +               hsize = HXGA_SIZE_H;
5672 +               /* 3072 */
5673 +               vsize = HXGA_SIZE_V;
5674 +               break;
5675 +       default:
5676 +               eprintk("resolution not supported");
5677 +               return CI_STATUS_NOTSUPP;
5678 +       }
5679 +
5680 +       return ci_isp_jpe_init_ex(hsize, vsize, compression_ratio, jpe_scale);
5681 +}
5682 +
5683 +void ci_isp_jpe_set_tables(u8 compression_ratio)
5684 +{
5685 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5686 +       /* required because auto-increment register */
5687 +       u32 jpe_table_data = 0;
5688 +
5689 +       u8 idx, size;
5690 +       const u8 *yqtable = NULL;
5691 +       const u8 *uvqtable = NULL;
5692 +
5693 +       switch (compression_ratio) {
5694 +       case CI_ISP_JPEG_LOW_COMPRESSION:
5695 +               yqtable = ci_isp_yq_table_low_comp1;
5696 +               uvqtable = ci_isp_uv_qtable_low_comp1;
5697 +               break;
5698 +       case CI_ISP_JPEG_01_PERCENT:
5699 +               yqtable = ci_isp_yq_table01_per_cent;
5700 +               uvqtable = ci_isp_uv_qtable01_per_cent;
5701 +               break;
5702 +       case CI_ISP_JPEG_20_PERCENT:
5703 +               yqtable = ci_isp_yq_table20_per_cent;
5704 +               uvqtable = ci_isp_uv_qtable20_per_cent;
5705 +               break;
5706 +       case CI_ISP_JPEG_30_PERCENT:
5707 +               yqtable = ci_isp_yq_table30_per_cent;
5708 +               uvqtable = ci_isp_uv_qtable30_per_cent;
5709 +               break;
5710 +       case CI_ISP_JPEG_40_PERCENT:
5711 +               yqtable = ci_isp_yq_table40_per_cent;
5712 +               uvqtable = ci_isp_uv_qtable40_per_cent;
5713 +               break;
5714 +       case CI_ISP_JPEG_50_PERCENT:
5715 +               yqtable = ci_isp_yq_table50_per_cent;
5716 +               uvqtable = ci_isp_uv_qtable50_per_cent;
5717 +               break;
5718 +       case CI_ISP_JPEG_60_PERCENT:
5719 +               yqtable = ci_isp_yq_table60_per_cent;
5720 +               uvqtable = ci_isp_uv_qtable60_per_cent;
5721 +               break;
5722 +       case CI_ISP_JPEG_70_PERCENT:
5723 +               yqtable = ci_isp_yq_table70_per_cent;
5724 +               uvqtable = ci_isp_uv_qtable70_per_cent;
5725 +               break;
5726 +       case CI_ISP_JPEG_80_PERCENT:
5727 +               yqtable = ci_isp_yq_table80_per_cent;
5728 +               uvqtable = ci_isp_uv_qtable80_per_cent;
5729 +               break;
5730 +       case CI_ISP_JPEG_90_PERCENT:
5731 +               yqtable = ci_isp_yq_table90_per_cent;
5732 +               uvqtable = ci_isp_uv_qtable90_per_cent;
5733 +               break;
5734 +       case CI_ISP_JPEG_99_PERCENT:
5735 +               yqtable = ci_isp_yq_table99_per_cent;
5736 +               uvqtable = ci_isp_uv_qtable99_per_cent;
5737 +               break;
5738 +       case CI_ISP_JPEG_HIGH_COMPRESSION:
5739 +       default:
5740 +               /*
5741 +                * in the case an unknown value is set,
5742 +                * use CI_JPEG_HIGH_COMPRESSION
5743 +                */
5744 +               yqtable = ci_isp_yq_table75_per_cent;
5745 +               uvqtable = ci_isp_uv_qtable75_per_cent;
5746 +               break;
5747 +       }
5748 +
5749 +       /* Y q-table 0 programming */
5750 +
5751 +       /* all possible assigned tables have same size */
5752 +       size = sizeof(ci_isp_yq_table75_per_cent)/
5753 +               sizeof(ci_isp_yq_table75_per_cent[0]);
5754 +       REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID,
5755 +                     MRV_JPE_TABLE_ID_QUANT0);
5756 +       for (idx = 0; idx < (size - 1); idx += 2) {
5757 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H,
5758 +                             yqtable[idx]);
5759 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L,
5760 +                             yqtable[idx + 1]);
5761 +               /* auto-increment register! */
5762 +               REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data);
5763 +       }
5764 +
5765 +       /* U/V q-table 0 programming */
5766 +
5767 +       /* all possible assigned tables have same size */
5768 +       size = sizeof(ci_isp_uv_qtable75_per_cent) /
5769 +               sizeof(ci_isp_uv_qtable75_per_cent[0]);
5770 +       REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID,
5771 +                     MRV_JPE_TABLE_ID_QUANT1);
5772 +       for (idx = 0; idx < (size - 1); idx += 2) {
5773 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H,
5774 +                             uvqtable[idx]);
5775 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L,
5776 +                             uvqtable[idx + 1]);
5777 +               /* auto-increment register! */
5778 +               REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data);
5779 +       }
5780 +
5781 +       /* Y AC-table 0 programming */
5782 +
5783 +       size = sizeof(ci_isp_ac_luma_table_annex_k) /
5784 +               sizeof(ci_isp_ac_luma_table_annex_k[0]);
5785 +       REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID,
5786 +                     MRV_JPE_TABLE_ID_VLC_AC0);
5787 +       REG_SET_SLICE(mrv_reg->jpe_tac0_len, MRV_JPE_TAC0_LEN, size);
5788 +       for (idx = 0; idx < (size - 1); idx += 2) {
5789 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H,
5790 +                             ci_isp_ac_luma_table_annex_k[idx]);
5791 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L,
5792 +                             ci_isp_ac_luma_table_annex_k[idx + 1]);
5793 +               /* auto-increment register! */
5794 +               REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data);
5795 +       }
5796 +
5797 +       /* U/V AC-table 1 programming */
5798 +
5799 +       size = sizeof(ci_isp_ac_chroma_table_annex_k) /
5800 +               sizeof(ci_isp_ac_chroma_table_annex_k[0]);
5801 +       REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID,
5802 +                     MRV_JPE_TABLE_ID_VLC_AC1);
5803 +       REG_SET_SLICE(mrv_reg->jpe_tac1_len, MRV_JPE_TAC1_LEN, size);
5804 +       for (idx = 0; idx < (size - 1); idx += 2) {
5805 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H,
5806 +                             ci_isp_ac_chroma_table_annex_k[idx]);
5807 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L,
5808 +                             ci_isp_ac_chroma_table_annex_k[idx + 1]);
5809 +               /* auto-increment register! */
5810 +               REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data);
5811 +       }
5812 +
5813 +       /* Y DC-table 0 programming */
5814 +
5815 +       size = sizeof(ci_isp_dc_luma_table_annex_k) /
5816 +               sizeof(ci_isp_dc_luma_table_annex_k[0]);
5817 +       REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID,
5818 +                     MRV_JPE_TABLE_ID_VLC_DC0);
5819 +       REG_SET_SLICE(mrv_reg->jpe_tdc0_len, MRV_JPE_TDC0_LEN, size);
5820 +       for (idx = 0; idx < (size - 1); idx += 2) {
5821 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H,
5822 +                             ci_isp_dc_luma_table_annex_k[idx]);
5823 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L,
5824 +                             ci_isp_dc_luma_table_annex_k[idx + 1]);
5825 +               /* auto-increment register! */
5826 +               REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data);
5827 +       }
5828 +
5829 +       /* U/V DC-table 1 programming */
5830 +
5831 +       size = sizeof(ci_isp_dc_chroma_table_annex_k) /
5832 +               sizeof(ci_isp_dc_chroma_table_annex_k[0]);
5833 +       REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID,
5834 +                     MRV_JPE_TABLE_ID_VLC_DC1);
5835 +       REG_SET_SLICE(mrv_reg->jpe_tdc1_len, MRV_JPE_TDC1_LEN, size);
5836 +       for (idx = 0; idx < (size - 1); idx += 2) {
5837 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H,
5838 +                             ci_isp_dc_chroma_table_annex_k[idx]);
5839 +               REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L,
5840 +                             ci_isp_dc_chroma_table_annex_k[idx + 1]);
5841 +               /* auto-increment register! */
5842 +               REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data);
5843 +       }
5844 +}
5845 +
5846 +/*
5847 + * selects tables to be used by encoder
5848 + */
5849 +void ci_isp_jpe_select_tables(void)
5850 +{
5851 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5852 +
5853 +       /* selects quantization table for Y */
5854 +       REG_SET_SLICE(mrv_reg->jpe_tq_y_select, MRV_JPE_TQ0_SELECT,
5855 +                     MRV_JPE_TQ_SELECT_TAB0);
5856 +       /* selects quantization table for U */
5857 +       REG_SET_SLICE(mrv_reg->jpe_tq_u_select, MRV_JPE_TQ1_SELECT,
5858 +                     MRV_JPE_TQ_SELECT_TAB1);
5859 +       /* selects quantization table for V */
5860 +       REG_SET_SLICE(mrv_reg->jpe_tq_v_select, MRV_JPE_TQ2_SELECT,
5861 +                     MRV_JPE_TQ_SELECT_TAB1);
5862 +       /* selects Huffman DC table */
5863 +       REG_SET_SLICE(mrv_reg->jpe_dc_table_select,
5864 +                     MRV_JPE_DC_TABLE_SELECT_Y, 0);
5865 +       REG_SET_SLICE(mrv_reg->jpe_dc_table_select,
5866 +                     MRV_JPE_DC_TABLE_SELECT_U, 1);
5867 +       REG_SET_SLICE(mrv_reg->jpe_dc_table_select,
5868 +                     MRV_JPE_DC_TABLE_SELECT_V, 1);
5869 +       /* selects Huffman AC table */
5870 +       REG_SET_SLICE(mrv_reg->jpe_ac_table_select,
5871 +                     MRV_JPE_AC_TABLE_SELECT_Y, 0);
5872 +       REG_SET_SLICE(mrv_reg->jpe_ac_table_select,
5873 +                     MRV_JPE_AC_TABLE_SELECT_U, 1);
5874 +       REG_SET_SLICE(mrv_reg->jpe_ac_table_select,
5875 +                     MRV_JPE_AC_TABLE_SELECT_V, 1);
5876 +}
5877 +
5878 +/*
5879 + * configure JPEG encoder
5880 + */
5881 +void ci_isp_jpe_set_config(u16 hsize, u16 vsize, int jpe_scale)
5882 +{
5883 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5884 +
5885 +       /* JPEG image size */
5886 +
5887 +       REG_SET_SLICE(mrv_reg->jpe_enc_hsize, MRV_JPE_ENC_HSIZE, hsize);
5888 +       REG_SET_SLICE(mrv_reg->jpe_enc_vsize, MRV_JPE_ENC_VSIZE, vsize);
5889 +
5890 +       if (jpe_scale) {
5891 +               /* upscaling of BT601 color space to full range 0..255 */
5892 +               REG_SET_SLICE(mrv_reg->jpe_y_scale_en, MRV_JPE_Y_SCALE_EN,
5893 +                             ENABLE);
5894 +               REG_SET_SLICE(mrv_reg->jpe_cbcr_scale_en,
5895 +                             MRV_JPE_CBCR_SCALE_EN, ENABLE);
5896 +       } else {
5897 +               /* bypass scaler */
5898 +               REG_SET_SLICE(mrv_reg->jpe_y_scale_en,
5899 +                             MRV_JPE_Y_SCALE_EN, DISABLE);
5900 +               REG_SET_SLICE(mrv_reg->jpe_cbcr_scale_en,
5901 +                             MRV_JPE_CBCR_SCALE_EN, DISABLE);
5902 +       }
5903 +
5904 +       /* picture format YUV 422 */
5905 +       REG_SET_SLICE(mrv_reg->jpe_pic_format, MRV_JPE_ENC_PIC_FORMAT,
5906 +                     MRV_JPE_ENC_PIC_FORMAT_422);
5907 +       REG_SET_SLICE(mrv_reg->jpe_table_flush, MRV_JPE_TABLE_FLUSH, 0);
5908 +}
5909 +
5910 +int ci_isp_jpe_generate_header(struct mrst_isp_device *intel, u8 header_mode)
5911 +{
5912 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5913 +
5914 +       WARN_ON(!((header_mode == MRV_JPE_HEADER_MODE_JFIF)
5915 +           || (header_mode == MRV_JPE_HEADER_MODE_NO)));
5916 +
5917 +       /* clear jpeg gen_header_done interrupt */
5918 +       /* since we poll them later to detect command completion */
5919 +
5920 +       REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_GEN_HEADER_DONE, 1);
5921 +       REG_SET_SLICE(mrv_reg->jpe_header_mode, MRV_JPE_HEADER_MODE,
5922 +                     header_mode);
5923 +
5924 +       /* start header generation */
5925 +       REG_SET_SLICE(mrv_reg->jpe_gen_header, MRV_JPE_GEN_HEADER, ON);
5926 +
5927 +       return ci_isp_jpe_wait_for_header_gen_done(intel);
5928 +}
5929 +
5930 +void ci_isp_jpe_prep_enc(enum ci_isp_jpe_enc_mode jpe_enc_mode)
5931 +{
5932 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5933 +       u32 jpe_encode = REG_READ(mrv_reg->jpe_encode);
5934 +
5935 +       /* clear jpeg encode_done interrupt */
5936 +       /* since we poll them later to detect command completion */
5937 +
5938 +       REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ENCODE_DONE, 1);
5939 +       REG_SET_SLICE(jpe_encode, MRV_JPE_ENCODE, ON);
5940 +
5941 +       switch (jpe_enc_mode) {
5942 +       case CI_ISP_JPE_LARGE_CONT_MODE:
5943 +               /* motion JPEG with header generation */
5944 +               REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE,
5945 +                   MRV_JPE_CONT_MODE_HEADER);
5946 +               break;
5947 +       case CI_ISP_JPE_SHORT_CONT_MODE:
5948 +               /* motion JPEG only first frame with header */
5949 +               REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE,
5950 +                   MRV_JPE_CONT_MODE_NEXT);
5951 +               break;
5952 +       default:
5953 +               /* single shot JPEG */
5954 +               REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE,
5955 +                   MRV_JPE_CONT_MODE_STOP);
5956 +               break;
5957 +       }
5958 +
5959 +       REG_WRITE(mrv_reg->jpe_encode, jpe_encode);
5960 +       REG_SET_SLICE(mrv_reg->jpe_init, MRV_JPE_JP_INIT, 1);
5961 +}
5962 +
5963 +/*
5964 + * wait until JPG Header is generated (MRV_JPGINT_GEN_HEADER_DONE
5965 + *              interrupt occurs)
5966 + *              waiting for JPG Header to be generated
5967 + */
5968 +int ci_isp_jpe_wait_for_header_gen_done(struct mrst_isp_device *intel)
5969 +{
5970 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5971 +
5972 +       mrst_timer_start();
5973 +
5974 +       while (!REG_GET_SLICE(mrv_reg->jpe_status_ris,
5975 +                              MRV_JPE_GEN_HEADER_DONE)) {
5976 +               if (mrst_get_micro_sec() > 2000000) {
5977 +                       mrst_timer_stop();
5978 +                       eprintk("timeout");
5979 +                       return CI_STATUS_FAILURE;
5980 +               }
5981 +       }
5982 +
5983 +       mrst_timer_stop();
5984 +
5985 +       return CI_STATUS_SUCCESS;
5986 +}
5987 +
5988 +/*
5989 + * wait until JPG Encoder is done  (MRV_JPGINT_ENCODE_DONE
5990 + * interrupt occurs) waiting for the JPG Encoder to be done
5991 + */
5992 +int ci_isp_jpe_wait_for_encode_done(struct mrst_isp_device *intel)
5993 +{
5994 +#if 0
5995 +       int ret = 0;
5996 +       INIT_COMPLETION(intel->jpe_complete);
5997 +       ret = wait_for_completion_interruptible_timeout(&intel->jpe_complete,
5998 +                                                       100 * HZ);
5999 +       if ((ret == 0) | (intel->irq_stat == IRQ_JPE_ERROR)) {
6000 +               eprintk("timeout");
6001 +               return CI_STATUS_FAILURE;
6002 +       }
6003 +
6004 +       return CI_STATUS_SUCCESS;
6005 +#endif
6006 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
6007 +       mrst_timer_start();
6008 +
6009 +       while (!REG_GET_SLICE(mrv_reg->jpe_status_ris,
6010 +                             MRV_JPE_ENCODE_DONE)) {
6011 +               if (mrst_get_micro_sec() > 200000) {
6012 +                       mrst_timer_stop();
6013 +                       eprintk("timeout");
6014 +                       return CI_STATUS_FAILURE;
6015 +               }
6016 +       }
6017 +
6018 +       mrst_timer_stop();
6019 +
6020 +       /* clear jpeg encode_done interrupt */
6021 +       REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ENCODE_DONE, 1);
6022 +
6023 +       return CI_STATUS_SUCCESS;
6024 +}
6025 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_main.c b/drivers/media/video/mrstci/mrstisp/mrstisp_main.c
6026 new file mode 100644
6027 index 0000000..e37b3d1
6028 --- /dev/null
6029 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_main.c
6030 @@ -0,0 +1,2977 @@
6031 +/*
6032 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
6033 + *
6034 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
6035 + *
6036 + * This program is free software; you can redistribute it and/or
6037 + * modify it under the terms of the GNU General Public License version
6038 + * 2 as published by the Free Software Foundation.
6039 + *
6040 + * This program is distributed in the hope that it will be useful,
6041 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6042 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6043 + * GNU General Public License for more details.
6044 + *
6045 + * You should have received a copy of the GNU General Public License
6046 + * along with this program; if not, write to the Free Software
6047 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
6048 + * 02110-1301, USA.
6049 + *
6050 + *
6051 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
6052 + */
6053 +
6054 +#include "mrstisp_stdinc.h"
6055 +#include "ci_isp_fmts_common.h"
6056 +
6057 +#define GPIO_SCLK_25   44
6058 +#define GPIO_STDBY1_PIN        48
6059 +#define GPIO_STDBY2_PIN        49
6060 +#define GPIO_RESET_PIN 50
6061 +
6062 +int mrstisp_debug;
6063 +module_param(mrstisp_debug, int, 0644);
6064 +
6065 +/*XXX*/
6066 +static int frame_cnt;
6067 +static long mipi_error_num;
6068 +static u32 mipi_error_flag;
6069 +static long isp_error_num;
6070 +static u32 isp_error_flag;
6071 +static unsigned long jiffies_start;
6072 +static int mipi_flag;
6073 +
6074 +void intel_timer_start(void)
6075 +{
6076 +       jiffies_start = jiffies;
6077 +}
6078 +void intel_timer_stop(void)
6079 +{
6080 +       jiffies_start = 0;
6081 +}
6082 +unsigned long intel_get_micro_sec(void)
6083 +{
6084 +       unsigned long time_diff = 0;
6085 +
6086 +       time_diff = jiffies - jiffies_start;
6087 +
6088 +       return jiffies_to_msecs(time_diff);
6089 +}
6090 +
6091 +
6092 +static inline struct mrst_isp_device *to_isp(struct v4l2_device *dev)
6093 +{
6094 +       return container_of(dev, struct mrst_isp_device, v4l2_dev);
6095 +}
6096 +
6097 +static struct mrst_camera mrst_camera_table[] = {
6098 +       {
6099 +               .type = MRST_CAMERA_SOC,
6100 +               .name = "ov2650",
6101 +               .sensor_addr = 0x30,
6102 +       },
6103 +       {
6104 +               .type = MRST_CAMERA_SOC,
6105 +               .name = "ov9665",
6106 +               .sensor_addr = 0x30,
6107 +       },
6108 +       {
6109 +               .type = MRST_CAMERA_RAW,
6110 +               .name = "ov5630",
6111 +               .sensor_addr = 0x36,
6112 +               .motor_name = "ov5630_motor",
6113 +               .motor_addr = (0x18 >> 1),
6114 +       },
6115 +       {
6116 +               .type = MRST_CAMERA_RAW,
6117 +               .name = "s5k4e1",
6118 +               .sensor_addr = 0x36,
6119 +               .motor_name = "s5k4e1_motor",
6120 +               .motor_addr = (0x18 >> 1),
6121 +       },
6122 +};
6123 +
6124 +#define N_CAMERA (ARRAY_SIZE(mrst_camera_table))
6125 +
6126 +struct videobuf_dma_contig_memory {
6127 +       u32 magic;
6128 +       void *vaddr;
6129 +       dma_addr_t dma_handle;
6130 +       unsigned long size;
6131 +       int is_userptr;
6132 +};
6133 +#define MAGIC_DC_MEM 0x0733ac61
6134 +#define MAGIC_CHECK(is, should)                                                    \
6135 +       if (unlikely((is) != (should))) {                                   \
6136 +               pr_err("magic mismatch: %x expected %x\n", (is), (should)); \
6137 +               BUG();                                                      \
6138 +       }
6139 +/* flag to determine whether to do the handler of mblk_line irq */
6140 +int mrst_isp_to_do_mblk_line;
6141 +unsigned char *mrst_isp_regs;
6142 +
6143 +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd)
6144 +{
6145 +       return container_of(sd, struct ci_sensor_config, sd);
6146 +}
6147 +
6148 +/* g45-th20-b5 gamma out curve with enhanced black level */
6149 +static struct ci_isp_gamma_out_curve g45_th20_b5 = {
6150 +       {
6151 +        0x0000, 0x0014, 0x003C, 0x0064,
6152 +        0x00A0, 0x0118, 0x0171, 0x01A7,
6153 +        0x01D8, 0x0230, 0x027A, 0x02BB,
6154 +        0x0323, 0x0371, 0x03AD, 0x03DB,
6155 +        0x03FF}
6156 +       ,
6157 +       0
6158 +};
6159 +
6160 +static void print_snr_cfg(struct ci_sensor_config *cfg)
6161 +{
6162 +       dprintk(2, "bus width = %x", cfg->bus_width);
6163 +       dprintk(2, "mode = %x", cfg->mode);
6164 +       dprintk(2, "field_inv = %x", cfg->field_inv);
6165 +       dprintk(2, "field_sel = %x", cfg->field_sel);
6166 +       dprintk(2, "ycseq = %x", cfg->ycseq);
6167 +       dprintk(2, "conv422 = %x", cfg->conv422);
6168 +       dprintk(2, "bpat = %x", cfg->bpat);
6169 +       dprintk(2, "hpol = %x", cfg->hpol);
6170 +       dprintk(2, "vpol = %x", cfg->vpol);
6171 +       dprintk(2, "edge = %x", cfg->edge);
6172 +       dprintk(2, "bls = %x", cfg->bls);
6173 +       dprintk(2, "gamma = %x", cfg->gamma);
6174 +       dprintk(2, "cconv = %x", cfg->cconv);
6175 +       dprintk(2, "res = %x", cfg->res);
6176 +       dprintk(2, "blc = %x", cfg->blc);
6177 +       dprintk(2, "agc = %x", cfg->agc);
6178 +       dprintk(2, "awb = %x", cfg->awb);
6179 +       dprintk(2, "aec = %x", cfg->aec);
6180 +       dprintk(2, "cie_profile = %x", cfg->cie_profile);
6181 +       dprintk(2, "flicker_freq = %x", cfg->flicker_freq);
6182 +       dprintk(2, "smia_mode = %x", cfg->smia_mode);
6183 +       dprintk(2, "mipi_mode = %x", cfg->mipi_mode);
6184 +       dprintk(2, "type = %x", cfg->type);
6185 +       dprintk(2, "name = %s", cfg->name);
6186 +}
6187 +
6188 +static int mrst_isp_defcfg_all_load(struct ci_isp_config *isp_config)
6189 +{
6190 +
6191 +       DBG_entering;
6192 +
6193 +       /* demosaic mode */
6194 +       isp_config->demosaic_mode = CI_ISP_DEMOSAIC_ENHANCED;
6195 +
6196 +       /* bpc */
6197 +       isp_config->bpc_cfg.bp_corr_type = CI_ISP_BP_CORR_DIRECT;
6198 +       isp_config->bpc_cfg.bp_corr_rep = CI_ISP_BP_CORR_REP_NB;
6199 +       isp_config->bpc_cfg.bp_corr_mode = CI_ISP_BP_CORR_HOT_DEAD_EN;
6200 +       isp_config->bpc_cfg.bp_abs_hot_thres = 496;
6201 +       isp_config->bpc_cfg.bp_abs_dead_thres = 20;
6202 +       isp_config->bpc_cfg.bp_dev_hot_thres = 328;
6203 +       isp_config->bpc_cfg.bp_dev_dead_thres = 328;
6204 +       isp_config->bpd_cfg.bp_dead_thres = 1;
6205 +
6206 +       /* WB */
6207 +       isp_config->wb_config.mrv_wb_mode = CI_ISP_AWB_AUTO;
6208 +       isp_config->wb_config.mrv_wb_sub_mode = CI_ISP_AWB_AUTO_ON;
6209 +       isp_config->wb_config.awb_pca_damping = 16;
6210 +       isp_config->wb_config.awb_prior_exp_damping = 12;
6211 +       isp_config->wb_config.awb_pca_push_damping = 16;
6212 +       isp_config->wb_config.awb_prior_exp_push_damping = 12;
6213 +       isp_config->wb_config.awb_auto_max_y = 254;
6214 +       isp_config->wb_config.awb_push_max_y = 250;
6215 +       isp_config->wb_config.awb_measure_max_y = 200;
6216 +       isp_config->wb_config.awb_underexp_det = 10;
6217 +       isp_config->wb_config.awb_push_underexp_det = 170;
6218 +
6219 +       /* CAC */
6220 +       isp_config->cac_config.hsize = 2048;
6221 +       isp_config->cac_config.vsize = 1536;
6222 +       isp_config->cac_config.hcenter_offset = 0;
6223 +       isp_config->cac_config.vcenter_offset = 0;
6224 +       isp_config->cac_config.hclip_mode = 1;
6225 +       isp_config->cac_config.vclip_mode = 2;
6226 +       isp_config->cac_config.ablue = 24;
6227 +       isp_config->cac_config.ared = 489;
6228 +       isp_config->cac_config.bblue = 450;
6229 +       isp_config->cac_config.bred = 53;
6230 +       isp_config->cac_config.cblue = 40;
6231 +       isp_config->cac_config.cred = 479;
6232 +       isp_config->cac_config.aspect_ratio = 0.000000;
6233 +
6234 +       /* BLS */
6235 +       isp_config->bls_cfg.enable_automatic = 0;
6236 +       isp_config->bls_cfg.disable_h = 0;
6237 +       isp_config->bls_cfg.disable_v = 0;
6238 +       isp_config->bls_cfg.isp_bls_window1.enable_window = 0;
6239 +       isp_config->bls_cfg.isp_bls_window1.start_h = 0;
6240 +       isp_config->bls_cfg.isp_bls_window1.stop_h = 0;
6241 +       isp_config->bls_cfg.isp_bls_window1.start_v = 0;
6242 +       isp_config->bls_cfg.isp_bls_window1.stop_v = 0;
6243 +       isp_config->bls_cfg.isp_bls_window2.enable_window = 0;
6244 +       isp_config->bls_cfg.isp_bls_window2.start_h = 0;
6245 +       isp_config->bls_cfg.isp_bls_window2.stop_h = 0;
6246 +       isp_config->bls_cfg.isp_bls_window2.start_v = 0;
6247 +       isp_config->bls_cfg.isp_bls_window2.stop_v = 0;
6248 +       isp_config->bls_cfg.bls_samples = 5;
6249 +       isp_config->bls_cfg.bls_subtraction.fixed_a = 0x100;
6250 +       isp_config->bls_cfg.bls_subtraction.fixed_b = 0x100;
6251 +       isp_config->bls_cfg.bls_subtraction.fixed_c = 0x100;
6252 +       isp_config->bls_cfg.bls_subtraction.fixed_d = 0x100;
6253 +
6254 +       /* AF */
6255 +       isp_config->af_cfg.wnd_pos_a.hoffs = 874;
6256 +       isp_config->af_cfg.wnd_pos_a.voffs = 618;
6257 +       isp_config->af_cfg.wnd_pos_a.hsize = 300;
6258 +       isp_config->af_cfg.wnd_pos_a.vsize = 300;
6259 +       isp_config->af_cfg.wnd_pos_b.hoffs = 0;
6260 +       isp_config->af_cfg.wnd_pos_b.voffs = 0;
6261 +       isp_config->af_cfg.wnd_pos_b.hsize = 0;
6262 +       isp_config->af_cfg.wnd_pos_b.vsize = 0;
6263 +       isp_config->af_cfg.wnd_pos_c.hoffs = 0;
6264 +       isp_config->af_cfg.wnd_pos_c.voffs = 0;
6265 +       isp_config->af_cfg.wnd_pos_c.hsize = 0;
6266 +       isp_config->af_cfg.wnd_pos_c.vsize = 0;
6267 +       isp_config->af_cfg.threshold = 0x00000000;
6268 +
6269 +       /* color */
6270 +       isp_config->color.contrast = 128;
6271 +       isp_config->color.brightness = 0;
6272 +       isp_config->color.saturation = 128;
6273 +       isp_config->color.hue = 0;
6274 +
6275 +       /* Img Effect */
6276 +       isp_config->img_eff_cfg.mode = CI_ISP_IE_MODE_OFF;
6277 +       isp_config->img_eff_cfg.color_sel = 4;
6278 +       isp_config->img_eff_cfg.color_thres = 128;
6279 +       isp_config->img_eff_cfg.tint_cb = 108;
6280 +       isp_config->img_eff_cfg.tint_cr = 141;
6281 +       isp_config->img_eff_cfg.mat_emboss.coeff_11 = 2;
6282 +       isp_config->img_eff_cfg.mat_emboss.coeff_12 = 1;
6283 +       isp_config->img_eff_cfg.mat_emboss.coeff_13 = 0;
6284 +       isp_config->img_eff_cfg.mat_emboss.coeff_21 = 1;
6285 +       isp_config->img_eff_cfg.mat_emboss.coeff_22 = 0;
6286 +       isp_config->img_eff_cfg.mat_emboss.coeff_23 = -1;
6287 +       isp_config->img_eff_cfg.mat_emboss.coeff_31 = 0;
6288 +       isp_config->img_eff_cfg.mat_emboss.coeff_32 = -1;
6289 +       isp_config->img_eff_cfg.mat_emboss.coeff_33 = -2;
6290 +       isp_config->img_eff_cfg.mat_sketch.coeff_11 = -1;
6291 +       isp_config->img_eff_cfg.mat_sketch.coeff_12 = -1;
6292 +       isp_config->img_eff_cfg.mat_sketch.coeff_13 = -1;
6293 +       isp_config->img_eff_cfg.mat_sketch.coeff_21 = -1;
6294 +       isp_config->img_eff_cfg.mat_sketch.coeff_22 = 8;
6295 +       isp_config->img_eff_cfg.mat_sketch.coeff_23 = -1;
6296 +       isp_config->img_eff_cfg.mat_sketch.coeff_31 = -1;
6297 +       isp_config->img_eff_cfg.mat_sketch.coeff_32 = -1;
6298 +       isp_config->img_eff_cfg.mat_sketch.coeff_33 = -1;
6299 +
6300 +       /* Framefun */
6301 +       isp_config->flags.bls = 0;
6302 +       isp_config->flags.lsc = 0;
6303 +       isp_config->flags.bpc = 0;
6304 +       isp_config->flags.awb = 0;
6305 +       isp_config->flags.aec = 0;
6306 +       isp_config->flags.af = 0;
6307 +       isp_config->flags.cp = 0;
6308 +       isp_config->flags.gamma = 0;
6309 +       isp_config->flags.cconv = 0;
6310 +       isp_config->flags.demosaic = 0;
6311 +       isp_config->flags.gamma2 = 0;
6312 +       isp_config->flags.isp_filters = 0;
6313 +       isp_config->flags.cac = 0;
6314 +       isp_config->flags.cconv_basic = 0;
6315 +       isp_config->demosaic_th = 4;
6316 +
6317 +       isp_config->view_finder.flags = VFFLAG_HWRGB;
6318 +
6319 +       isp_config->afm_mode = 1;
6320 +       isp_config->filter_level_noise_reduc = 4;
6321 +       isp_config->filter_level_sharp = 4;
6322 +
6323 +       isp_config->jpeg_enc_ratio = 1;
6324 +
6325 +       DBG_leaving;
6326 +       return 0;
6327 +}
6328 +
6329 +static void mrst_isp_update_marvinvfaddr(struct mrst_isp_device *isp,
6330 +                                     u32 buffer_base,
6331 +                                     enum ci_isp_conf_update_time update_time)
6332 +{
6333 +       struct ci_isp_mi_path_conf isp_mi_path_conf;
6334 +       struct ci_isp_mi_path_conf isp_sf_mi_path_conf;
6335 +       static struct v4l2_jpg_review_buffer *jpg_review;
6336 +       u32 bufsize = 0;
6337 +       u32 w;
6338 +       u32 h;
6339 +
6340 +       jpg_review = &isp->sys_conf.jpg_review;
6341 +       memset(&isp_mi_path_conf, 0, sizeof(struct ci_isp_mi_path_conf));
6342 +       memset(&isp_sf_mi_path_conf, 0, sizeof(struct ci_isp_mi_path_conf));
6343 +
6344 +       w = isp_mi_path_conf.llength = isp->bufwidth;
6345 +       h = isp_mi_path_conf.ypic_height = isp->bufheight;
6346 +       isp_mi_path_conf.ypic_width = isp->bufwidth;
6347 +
6348 +       /*XXX Zheng: disable jpg review for MIPI sensor */
6349 +       /*if ((isp->sys_conf.isi_config)->mipi_mode == SENSOR_MIPI_MODE_RAW_10)
6350 +               isp->sys_conf.jpg_review_enable = 0;
6351 +               */
6352 +
6353 +       if (isp->sys_conf.jpg_review_enable) {
6354 +
6355 +               /* for self path, JPEG review */
6356 +               isp_sf_mi_path_conf.ypic_width = jpg_review->width;
6357 +               isp_sf_mi_path_conf.llength = jpg_review->width;
6358 +               isp_sf_mi_path_conf.ypic_height = jpg_review->height;
6359 +
6360 +               bufsize = jpg_review->width * jpg_review->height;
6361 +
6362 +               /* buffer size in bytes */
6363 +               if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV420
6364 +                   || jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420) {
6365 +
6366 +                       dprintk(3, "VF yuv420 fmt");
6367 +                       isp_sf_mi_path_conf.ybuffer.size = bufsize;
6368 +                       isp_sf_mi_path_conf.cb_buffer.size = bufsize/4;
6369 +                       isp_sf_mi_path_conf.cr_buffer.size = bufsize/4;
6370 +
6371 +               } else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV422P) {
6372 +
6373 +                       dprintk(3, "VF yuv422 fmt");
6374 +                       isp_sf_mi_path_conf.ybuffer.size = bufsize;
6375 +                       isp_sf_mi_path_conf.cb_buffer.size = bufsize/2;
6376 +                       isp_sf_mi_path_conf.cr_buffer.size = bufsize/2;
6377 +
6378 +               } else if (jpg_review->pix_fmt == V4L2_PIX_FMT_NV12) {
6379 +
6380 +                       dprintk(3, "VF nv12 fmt");
6381 +                       isp_sf_mi_path_conf.ybuffer.size = bufsize;
6382 +                       isp_sf_mi_path_conf.cb_buffer.size = bufsize/2;
6383 +                       isp_sf_mi_path_conf.cr_buffer.size = 0;
6384 +
6385 +               } else {
6386 +                       printk(KERN_ERR "mrstisp: no support jpg review fmt\n");
6387 +               }
6388 +
6389 +               /* buffer address */
6390 +               if (isp_sf_mi_path_conf.ybuffer.size != 0) {
6391 +                       isp_sf_mi_path_conf.ybuffer.pucbuffer =
6392 +                           (u8 *)(unsigned long)
6393 +                           isp->mb1 + isp->mb1_size - 640*480*2;
6394 +               }
6395 +
6396 +               if (isp_sf_mi_path_conf.cb_buffer.size != 0) {
6397 +                       isp_sf_mi_path_conf.cb_buffer.pucbuffer =
6398 +                               isp_sf_mi_path_conf.ybuffer.pucbuffer +
6399 +                               isp_sf_mi_path_conf.ybuffer.size;
6400 +               }
6401 +
6402 +               if (isp_sf_mi_path_conf.cr_buffer.size != 0) {
6403 +                       isp_sf_mi_path_conf.cr_buffer.pucbuffer =
6404 +                               isp_sf_mi_path_conf.cb_buffer.pucbuffer +
6405 +                               isp_sf_mi_path_conf.cb_buffer.size;
6406 +               }
6407 +
6408 +               if (jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420) {
6409 +                       isp_sf_mi_path_conf.cr_buffer.pucbuffer =
6410 +                               isp_sf_mi_path_conf.ybuffer.pucbuffer +
6411 +                               isp_sf_mi_path_conf.ybuffer.size;
6412 +                       isp_sf_mi_path_conf.cb_buffer.pucbuffer =
6413 +                               isp_sf_mi_path_conf.cr_buffer.pucbuffer +
6414 +                               isp_sf_mi_path_conf.cr_buffer.size;
6415 +               }
6416 +
6417 +       }
6418 +
6419 +       if (isp->pixelformat == V4L2_PIX_FMT_YUV420 ||
6420 +               isp->pixelformat == V4L2_PIX_FMT_YVU420 ||
6421 +               isp->pixelformat == V4L2_PIX_FMT_YUV422P ||
6422 +               isp->pixelformat == V4L2_PIX_FMT_NV12) {
6423 +               bufsize = w*h;
6424 +       } else
6425 +               bufsize = isp->frame_size;
6426 +
6427 +       /* buffer size in bytes */
6428 +       if (isp->pixelformat == V4L2_PIX_FMT_YUV420
6429 +           || isp->pixelformat == V4L2_PIX_FMT_YVU420) {
6430 +
6431 +               dprintk(3, "yuv420 fmt");
6432 +               isp_mi_path_conf.ybuffer.size = bufsize;
6433 +               isp_mi_path_conf.cb_buffer.size = bufsize/4;
6434 +               isp_mi_path_conf.cr_buffer.size = bufsize/4;
6435 +       } else if (isp->pixelformat == V4L2_PIX_FMT_YUV422P) {
6436 +
6437 +               dprintk(3, "yuv422 fmt");
6438 +               isp_mi_path_conf.ybuffer.size = bufsize;
6439 +               isp_mi_path_conf.cb_buffer.size = bufsize/2;
6440 +               isp_mi_path_conf.cr_buffer.size = bufsize/2;
6441 +       } else if (isp->pixelformat == V4L2_PIX_FMT_NV12) {
6442 +
6443 +               dprintk(3, "nv12 fmt");
6444 +               isp_mi_path_conf.ybuffer.size = bufsize;
6445 +               isp_mi_path_conf.cb_buffer.size = bufsize/2;
6446 +               isp_mi_path_conf.cr_buffer.size = 0;
6447 +       } else {
6448 +
6449 +               dprintk(3, "jpeg and rgb fmt");
6450 +               isp_mi_path_conf.ybuffer.size = bufsize;
6451 +               isp_mi_path_conf.cb_buffer.size = 0;
6452 +               isp_mi_path_conf.cr_buffer.size = 0;
6453 +       }
6454 +
6455 +       /* buffer address */
6456 +       if (isp_mi_path_conf.ybuffer.size != 0) {
6457 +               isp_mi_path_conf.ybuffer.pucbuffer =
6458 +                   (u8 *)(unsigned long) buffer_base;
6459 +       }
6460 +
6461 +       if (isp_mi_path_conf.cb_buffer.size != 0) {
6462 +               isp_mi_path_conf.cb_buffer.pucbuffer =
6463 +                       isp_mi_path_conf.ybuffer.pucbuffer +
6464 +                       isp_mi_path_conf.ybuffer.size;
6465 +       }
6466 +
6467 +       if (isp_mi_path_conf.cr_buffer.size != 0) {
6468 +               isp_mi_path_conf.cr_buffer.pucbuffer =
6469 +                       isp_mi_path_conf.cb_buffer.pucbuffer +
6470 +                       isp_mi_path_conf.cb_buffer.size;
6471 +       }
6472 +
6473 +       if (isp->pixelformat == V4L2_PIX_FMT_YVU420) {
6474 +               isp_mi_path_conf.cr_buffer.pucbuffer =
6475 +                       isp_mi_path_conf.ybuffer.pucbuffer +
6476 +                       isp_mi_path_conf.ybuffer.size;
6477 +               isp_mi_path_conf.cb_buffer.pucbuffer =
6478 +                       isp_mi_path_conf.cr_buffer.pucbuffer +
6479 +                       isp_mi_path_conf.cr_buffer.size;
6480 +       }
6481 +
6482 +       if (isp->sys_conf.isp_cfg.view_finder.flags & VFFLAG_USE_MAINPATH) {
6483 +               ci_isp_mif_set_main_buffer(&isp_mi_path_conf, update_time);
6484 +               if (isp->pixelformat == V4L2_PIX_FMT_JPEG)
6485 +                       if (isp->sys_conf.jpg_review_enable)
6486 +                               ci_isp_mif_set_self_buffer(
6487 +                                   &isp_sf_mi_path_conf, update_time);
6488 +       } else {
6489 +               ci_isp_mif_set_self_buffer(&isp_mi_path_conf, update_time);
6490 +       }
6491 +}
6492 +
6493 +static int mrst_isp_setup_viewfinder_path(struct mrst_isp_device *isp,
6494 +                                         struct ci_sensor_config *isi_config,
6495 +                                         int zoom)
6496 +{
6497 +       int error = CI_STATUS_SUCCESS;
6498 +       struct ci_isp_datapath_desc dp_main;
6499 +       struct ci_isp_datapath_desc dp_self;
6500 +       struct ci_isp_rect self_rect;
6501 +       u16 isi_hsize;
6502 +       u16 isi_vsize;
6503 +       int jpe_scale;
6504 +       struct ci_pl_system_config *sys_conf = &isp->sys_conf;
6505 +       struct ci_isp_config *config = &sys_conf->isp_cfg;
6506 +       struct v4l2_jpg_review_buffer *jpg_review = &sys_conf->jpg_review;
6507 +       u32 dp_mode;
6508 +
6509 +       DBG_entering;
6510 +
6511 +       if (sys_conf->isp_cfg.flags.ycbcr_full_range)
6512 +               jpe_scale = false;
6513 +       else
6514 +               jpe_scale = true;
6515 +
6516 +       memset(&dp_main, 0, sizeof(struct ci_isp_datapath_desc));
6517 +       memset(&dp_self, 0, sizeof(struct ci_isp_datapath_desc));
6518 +
6519 +       self_rect.x = 0;
6520 +       self_rect.y = 0;
6521 +       self_rect.w = isp->bufwidth; /* 640 */
6522 +       self_rect.h = isp->bufheight; /* 480 */
6523 +
6524 +       if (isp->pixelformat == V4L2_PIX_FMT_JPEG) {
6525 +
6526 +               dprintk(1, "jpeg fmt");
6527 +
6528 +               dp_main.flags = CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPJPEG;
6529 +               config->view_finder.flags |= VFFLAG_USE_MAINPATH;
6530 +
6531 +               dp_main.out_w = (u16) isp->bufwidth;
6532 +               dp_main.out_h = (u16) isp->bufheight;
6533 +
6534 +               if (isp->sys_conf.jpg_review_enable) {
6535 +
6536 +                       dprintk(1, "jpg_review enabled in VF");
6537 +
6538 +                       self_rect.w = jpg_review->width;
6539 +                       self_rect.h = jpg_review->height;
6540 +
6541 +                       dp_self.flags = (CI_ISP_DPD_ENABLE
6542 +                                        | CI_ISP_DPD_MODE_ISPYC);
6543 +                       if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV420 ||
6544 +                               jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420)
6545 +                               dp_self.flags |= CI_ISP_DPD_YUV_420
6546 +                                   | CI_ISP_DPD_CSS_V2;
6547 +                       else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV422P)
6548 +                               dp_self.flags |= CI_ISP_DPD_YUV_422;
6549 +                       else if (jpg_review->pix_fmt == V4L2_PIX_FMT_NV12)
6550 +                               dp_self.flags |= CI_ISP_DPD_YUV_NV12
6551 +                                   | CI_ISP_DPD_CSS_V2;
6552 +                       else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUYV)
6553 +                               dp_self.flags |= CI_ISP_DPD_YUV_YUYV;
6554 +
6555 +                       dprintk(1, "dp_self.flags is 0x%x", dp_self.flags);
6556 +               }
6557 +
6558 +       } else if (isp->pixelformat == INTEL_PIX_FMT_RAW08) {
6559 +
6560 +               dp_main.flags = CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPRAW;
6561 +               config->view_finder.flags |= VFFLAG_USE_MAINPATH;
6562 +
6563 +               /*just take the output of the sensor without any resizing*/
6564 +               dp_main.flags |= CI_ISP_DPD_NORESIZE;
6565 +               (void)ci_sensor_res2size(isi_config->res,
6566 +                                        &(dp_main.out_w), &(dp_main.out_h));
6567 +
6568 +               dprintk(1, "RAW08 dp_main.flags is 0x%x", dp_main.flags);
6569 +
6570 +       } else if (isp->pixelformat == INTEL_PIX_FMT_RAW10
6571 +                  || isp->pixelformat == INTEL_PIX_FMT_RAW12) {
6572 +
6573 +               dp_main.flags = (CI_ISP_DPD_ENABLE
6574 +                                | CI_ISP_DPD_MODE_ISPRAW_16B);
6575 +               config->view_finder.flags |= VFFLAG_USE_MAINPATH;
6576 +
6577 +               /*just take the output of the sensor without any resizing*/
6578 +               dp_main.flags |= CI_ISP_DPD_NORESIZE;
6579 +               (void)ci_sensor_res2size(isi_config->res,
6580 +                                        &(dp_main.out_w), &(dp_main.out_h));
6581 +
6582 +               dprintk(1, "RAW10 dp_main.flags is 0x%x", dp_main.flags);
6583 +
6584 +       } /*else if (isp->bufwidth >= 640 && isp->bufheight >= 480) {*/
6585 +       else if (isp->bufwidth >= 32 && isp->bufheight >= 16) {
6586 +
6587 +               dp_main.flags = (CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPYC);
6588 +               dp_main.out_w = (u16) isp->bufwidth;
6589 +               dp_main.out_h = (u16) isp->bufheight;
6590 +               config->view_finder.flags |= VFFLAG_USE_MAINPATH;
6591 +
6592 +               if (isp->pixelformat == V4L2_PIX_FMT_YUV420 ||
6593 +                       isp->pixelformat == V4L2_PIX_FMT_YVU420)
6594 +                       dp_main.flags |= CI_ISP_DPD_YUV_420 | CI_ISP_DPD_CSS_V2;
6595 +               else if (isp->pixelformat == V4L2_PIX_FMT_YUV422P)
6596 +                       dp_main.flags |= CI_ISP_DPD_YUV_422;
6597 +               else if (isp->pixelformat == V4L2_PIX_FMT_NV12) {
6598 +                       /* to use crop set crop_flag first */
6599 +                       dp_main.flags |= CI_ISP_DPD_YUV_NV12;
6600 +                       if (!crop_flag)
6601 +                               dp_main.flags |= CI_ISP_DPD_CSS_V2;
6602 +               } else if (isp->pixelformat == V4L2_PIX_FMT_YUYV)
6603 +                       dp_main.flags |= CI_ISP_DPD_YUV_YUYV;
6604 +
6605 +               dprintk(1, "YUV dp_main.flags is 0x%x", dp_main.flags);
6606 +
6607 +       } /* else if (isp->bufwidth <= 640 && isp->bufheight <= 480) {
6608 +
6609 +               dp_self.flags = (CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPYC);
6610 +
6611 +               if (isp->pixelformat == V4L2_PIX_FMT_YUV420 ||
6612 +                       isp->pixelformat == V4L2_PIX_FMT_YVU420)
6613 +                       dp_self.flags |= CI_ISP_DPD_YUV_420 | CI_ISP_DPD_CSS_V2;
6614 +               else if (isp->pixelformat == V4L2_PIX_FMT_YUV422P)
6615 +                       dp_self.flags |= CI_ISP_DPD_YUV_422;
6616 +               else if (isp->pixelformat == V4L2_PIX_FMT_NV12)
6617 +                       dp_self.flags |= CI_ISP_DPD_YUV_NV12
6618 +                           | CI_ISP_DPD_CSS_V2;
6619 +               else if (isp->pixelformat == V4L2_PIX_FMT_YUYV)
6620 +                       dp_self.flags |= CI_ISP_DPD_YUV_YUYV;
6621 +               else if (isp->pixelformat == V4L2_PIX_FMT_RGB565)
6622 +                       dp_self.flags |= CI_ISP_DPD_HWRGB_565;
6623 +               else if (isp->pixelformat == V4L2_PIX_FMT_BGR32)
6624 +                       dp_self.flags |= CI_ISP_DPD_HWRGB_888;
6625 +
6626 +               dprintk(1, "YUV dp_self.flags is 0x%x", dp_self.flags);
6627 +       }
6628 +       */
6629 +
6630 +       dprintk(1, "sensor_res = %x", isi_config->res);
6631 +
6632 +       (void)ci_sensor_res2size(isi_config->res, &isi_hsize, &isi_vsize);
6633 +       dprintk(1, "self path: w:%d, h:%d; sensor: w:%d, h:%d",
6634 +               self_rect.w, self_rect.h, isi_hsize, isi_vsize);
6635 +       dprintk(1, "main path: out_w:%d, out_h:%d ",
6636 +               dp_main.out_w, dp_main.out_h);
6637 +
6638 +       /* no stretching/squeezing */
6639 +       if (dp_self.flags && CI_ISP_DPD_ENABLE)
6640 +               dp_self.flags |= CI_ISP_DPD_KEEPRATIO;
6641 +       else
6642 +               dp_main.flags |= CI_ISP_DPD_KEEPRATIO;
6643 +
6644 +       /* prepare datapath, 640x480, can changed to the bufsize */
6645 +       dp_self.out_w = (u16) self_rect.w;
6646 +       dp_self.out_h = (u16) self_rect.h;
6647 +
6648 +       if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_HWRGB) {
6649 +               /* YCbCr to RGB conversion in hardware */
6650 +               if (isp->pixelformat == V4L2_PIX_FMT_RGB565)
6651 +                       dp_self.flags |= CI_ISP_DPD_HWRGB_565;
6652 +               if (isp->pixelformat == V4L2_PIX_FMT_BGR32)
6653 +                       dp_self.flags |= CI_ISP_DPD_HWRGB_888;
6654 +       }
6655 +
6656 +       if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_MIRROR)
6657 +               dp_self.flags |= CI_ISP_DPD_H_FLIP;
6658 +
6659 +
6660 +       if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_V_FLIP)
6661 +               dp_self.flags |= CI_ISP_DPD_V_FLIP;
6662 +
6663 +
6664 +       if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_ROT90_CCW)
6665 +               dp_self.flags |= CI_ISP_DPD_90DEG_CCW;
6666 +
6667 +       /* setup self & main path with zoom */
6668 +       if (zoom < 0)
6669 +               zoom = sys_conf->isp_cfg.view_finder.zoom;
6670 +
6671 +       if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_USE_MAINPATH) {
6672 +               /* For RAW snapshots, we have to bypass the ISP too */
6673 +               dp_mode = dp_main.flags & CI_ISP_DPD_MODE_MASK;
6674 +               if ((dp_mode == CI_ISP_DPD_MODE_ISPRAW) ||
6675 +                       (dp_mode == CI_ISP_DPD_MODE_ISPRAW_16B)) {
6676 +                       struct ci_sensor_config isi_conf;
6677 +                       /* isi_conf = *sys_conf->isi_config; */
6678 +                       isi_conf = *isi_config;
6679 +                       isi_conf.mode = SENSOR_MODE_PICT;
6680 +                       error = ci_isp_set_input_aquisition(&isi_conf);
6681 +                       if (error != CI_STATUS_SUCCESS)
6682 +                               eprintk("33");
6683 +               }
6684 +       }
6685 +       /* to use crop mode, set crop_flag */
6686 +       if (crop_flag)
6687 +               dp_main.flags |= CI_ISP_DPD_NORESIZE;
6688 +
6689 +       error = ci_datapath_isp(sys_conf, isi_config, &dp_main, &dp_self, zoom);
6690 +       if (error != CI_STATUS_SUCCESS) {
6691 +               printk(KERN_ERR "mrstisp: failed to setup marvins datapath\n");
6692 +               return error;
6693 +       }
6694 +
6695 +       DBG_leaving;
6696 +       return error;
6697 +}
6698 +
6699 +static int mrst_isp_init_mrv_image_effects(struct ci_pl_system_config *sys_conf,
6700 +                                          int enable)
6701 +{
6702 +       int res;
6703 +
6704 +       DBG_entering;
6705 +
6706 +       if (enable && sys_conf->isp_cfg.img_eff_cfg.mode
6707 +           != CI_ISP_IE_MODE_OFF) {
6708 +               res = ci_isp_ie_set_config(&(sys_conf->isp_cfg.img_eff_cfg));
6709 +               if (res != CI_STATUS_SUCCESS)
6710 +                       printk(KERN_ERR "mrstisp: error setting ie config\n");
6711 +       } else {
6712 +               (void)ci_isp_ie_set_config(NULL);
6713 +               res = CI_STATUS_SUCCESS;
6714 +       }
6715 +
6716 +       DBG_leaving;
6717 +       return res;
6718 +}
6719 +
6720 +static int mrst_isp_init_mrvisp_lensshade(struct ci_pl_system_config *sys_conf,
6721 +                                         int enable)
6722 +{
6723 +       if (enable) {
6724 +               ci_isp_set_ls_correction(&sys_conf->isp_cfg.lsc_cfg);
6725 +               ci_isp_ls_correction_on_off(1);
6726 +       } else {
6727 +               ci_isp_ls_correction_on_off(0);
6728 +       }
6729 +       return CI_STATUS_SUCCESS;
6730 +}
6731 +
6732 +static int mrst_isp_init_mrvisp_badpixel(const struct ci_pl_system_config
6733 +                                        *sys_conf, int enable)
6734 +{
6735 +       if ((enable) && (sys_conf->isp_cfg.flags.bpc)) {
6736 +               (void)ci_bp_init(&sys_conf->isp_cfg.bpc_cfg,
6737 +                                &sys_conf->isp_cfg.bpd_cfg);
6738 +       } else {
6739 +               (void)ci_bp_end(&sys_conf->isp_cfg.bpc_cfg);
6740 +               (void)ci_isp_set_bp_correction(NULL);
6741 +               (void)ci_isp_set_bp_detection(NULL);
6742 +       }
6743 +       return CI_STATUS_SUCCESS;
6744 +}
6745 +
6746 +static int mrst_isp_init_mrv_ispfilter(const struct ci_pl_system_config
6747 +                                      *sys_conf, int enable)
6748 +{
6749 +       int res;
6750 +
6751 +       DBG_entering;
6752 +
6753 +       if ((enable) && (sys_conf->isp_cfg.flags.isp_filters)) {
6754 +               ci_isp_activate_filter(true);
6755 +               res = ci_isp_set_filter_params(sys_conf->isp_cfg.
6756 +                                              filter_level_noise_reduc,
6757 +                                              sys_conf->isp_cfg.
6758 +                                              filter_level_sharp);
6759 +               if (res != CI_STATUS_SUCCESS)
6760 +                       printk(KERN_ERR "mrstisp: error set filter param\n");
6761 +       } else {
6762 +               ci_isp_activate_filter(false);
6763 +               res = CI_STATUS_SUCCESS;
6764 +       }
6765 +
6766 +       DBG_leaving;
6767 +       return res;
6768 +}
6769 +
6770 +static int mrst_isp_init_mrvisp_cac(const struct ci_pl_system_config *sys_conf,
6771 +                                   int enable)
6772 +{
6773 +       return 0;
6774 +}
6775 +
6776 +static int mrst_isp_initbls(const struct ci_pl_system_config *sys_conf)
6777 +{
6778 +       struct ci_isp_bls_config *bls_config =
6779 +           (struct ci_isp_bls_config *)&sys_conf->isp_cfg.bls_cfg;
6780 +       return ci_isp_bls_set_config(bls_config);
6781 +}
6782 +
6783 +static int mrst_isp_dp_init(struct ci_pl_system_config *sys_conf,
6784 +                           struct ci_sensor_config *isi_config)
6785 +{
6786 +       int error;
6787 +       u8 words_per_pixel;
6788 +
6789 +       DBG_entering;
6790 +
6791 +       /* base initialisation of Marvin */
6792 +       ci_isp_init();
6793 +
6794 +       /* setup input acquisition according to image sensor settings */
6795 +       print_snr_cfg(isi_config);
6796 +       error = ci_isp_set_input_aquisition(isi_config);
6797 +       if (error) {
6798 +               printk(KERN_ERR "mrstisp: error setting input acquisition\n");
6799 +               return error;
6800 +       }
6801 +
6802 +       /* setup functional blocks for Bayer pattern processing */
6803 +       if (ci_isp_select_path(isi_config, &words_per_pixel)
6804 +           == CI_ISP_PATH_BAYER) {
6805 +
6806 +               /* black level */
6807 +               if (sys_conf->isp_cfg.flags.bls) {
6808 +                       error = mrst_isp_initbls(sys_conf);
6809 +                       if (error != CI_STATUS_SUCCESS) {
6810 +                               printk(KERN_ERR "mrstisp: error set bls\n");
6811 +                               return error;
6812 +                       }
6813 +               } else {
6814 +                       ci_isp_bls_set_config(NULL);
6815 +               }
6816 +
6817 +               /* gamma */
6818 +               if (sys_conf->isp_cfg.flags.gamma2) {
6819 +                       dprintk(1, "setting gamma 2 ");
6820 +                       ci_isp_set_gamma2(&g45_th20_b5);
6821 +               } else {
6822 +                       dprintk(1, "no setting gamma 2 ");
6823 +                       ci_isp_set_gamma2(NULL);
6824 +               }
6825 +
6826 +               /* demosaic */
6827 +               ci_isp_set_demosaic(sys_conf->isp_cfg.demosaic_mode,
6828 +                                   sys_conf->isp_cfg.demosaic_th);
6829 +
6830 +               /* color convertion */
6831 +               if (sys_conf->isp_cfg.flags.cconv) {
6832 +                       if (!sys_conf->isp_cfg.flags.cconv_basic) {
6833 +                               mrst_isp_set_color_conversion_ex();
6834 +                               /* set color converstion skipped by xiaolin,
6835 +                                * to be done in libci */
6836 +                               if (error != CI_STATUS_SUCCESS) {
6837 +                                       printk(KERN_ERR "mrstisp: error set"
6838 +                                              " color conversion\n");
6839 +                                       return error;
6840 +                               }
6841 +                       }
6842 +               }
6843 +
6844 +               /* af setting */
6845 +               if (sys_conf->isp_cfg.flags.af)
6846 +                       ci_isp_set_auto_focus(&sys_conf->isp_cfg.af_cfg);
6847 +               else
6848 +                       ci_isp_set_auto_focus(NULL);
6849 +
6850 +               /* filter */
6851 +               mrst_isp_init_mrv_ispfilter(sys_conf, true);
6852 +
6853 +               /* cac */
6854 +               mrst_isp_init_mrvisp_cac(sys_conf, true);
6855 +       }
6856 +
6857 +       /*
6858 +        * disable color processing for now (will be set under user control
6859 +        * in the main loop)
6860 +        */
6861 +       ci_isp_col_set_color_processing(NULL);
6862 +
6863 +       /* configure image effects */
6864 +       mrst_isp_init_mrv_image_effects(sys_conf, true);
6865 +
6866 +       /* configure lens shading correction */
6867 +       if (strcmp(isi_config->name, "s5k4e1") == 0
6868 +           && (isi_config->res == SENSOR_RES_720P
6869 +               || isi_config->res == SENSOR_RES_QXGA_PLUS)) {
6870 +               dprintk(1, "enabling lsc for kmot 720p and qsxga\n");
6871 +               mrst_isp_init_mrvisp_lensshade(sys_conf, true);
6872 +       } else
6873 +               mrst_isp_init_mrvisp_lensshade(sys_conf,
6874 +                                              sys_conf->isp_cfg.flags.lsc);
6875 +
6876 +       /* configure bad pixel detection/correction */
6877 +       mrst_isp_init_mrvisp_badpixel(sys_conf, true);
6878 +
6879 +       DBG_leaving;
6880 +       return CI_STATUS_SUCCESS;
6881 +}
6882 +
6883 +int ci_jpe_encode(struct mrst_isp_device *intel,
6884 +                 enum ci_isp_conf_update_time update_time,
6885 +                 enum ci_isp_jpe_enc_mode mrv_jpe_encMode)
6886 +{
6887 +       u32 mipi_data_id = 1;
6888 +       struct isp_register *mrv_reg =
6889 +           (struct isp_register *) MEM_MRV_REG_BASE;
6890 +
6891 +       ci_isp_jpe_prep_enc(mrv_jpe_encMode);
6892 +
6893 +       if (to_sensor_config(intel->sensor_curr)->mipi_mode) {
6894 +               ci_isp_start(1, update_time);
6895 +               v4l2_subdev_call(intel->sensor_curr, video, s_stream, 1);
6896 +               if (mipi_flag)
6897 +                       while (mipi_data_id)
6898 +                               mipi_data_id =
6899 +                                   REG_READ_EX(mrv_reg->mipi_cur_data_id);
6900 +               mipi_flag = 0;
6901 +
6902 +       } else
6903 +               ci_isp_start(1, update_time);
6904 +
6905 +       return ci_isp_jpe_wait_for_encode_done(intel);
6906 +}
6907 +
6908 +/* capture one frame */
6909 +u32 ci_jpe_capture(struct mrst_isp_device *isp,
6910 +                  enum ci_isp_conf_update_time update_time)
6911 +{
6912 +       int retval = CI_STATUS_SUCCESS;
6913 +
6914 +       /* generate header */
6915 +       retval = ci_isp_jpe_generate_header(isp, MRV_JPE_HEADER_MODE_JFIF);
6916 +       if (retval != CI_STATUS_SUCCESS)
6917 +               return 0;
6918 +
6919 +       /* now encode JPEG */
6920 +       retval = ci_jpe_encode(isp, update_time, CI_ISP_JPE_SINGLE_SHOT);
6921 +       if (retval != CI_STATUS_SUCCESS)
6922 +               return 0;
6923 +
6924 +       /* return ci_isp_mif_get_byte_cnt(); */
6925 +       return 0;
6926 +}
6927 +
6928 +static int mrst_ci_capture(struct mrst_isp_device *isp)
6929 +{
6930 +       u32 bufbase;
6931 +       u32 mipi_data_id = 1;
6932 +       struct videobuf_buffer *vb;
6933 +       struct isp_register *mrv_reg =
6934 +           (struct isp_register *) MEM_MRV_REG_BASE;
6935 +
6936 +       bufbase = videobuf_to_dma_contig(isp->active);
6937 +       mrst_isp_update_marvinvfaddr(isp, bufbase, CI_ISP_CFG_UPDATE_IMMEDIATE);
6938 +       ci_isp_mif_reset_offsets(CI_ISP_CFG_UPDATE_IMMEDIATE);
6939 +
6940 +       ci_isp_reset_interrupt_status();
6941 +       mrst_isp_enable_interrupt(isp);
6942 +
6943 +       if (isp->pixelformat == V4L2_PIX_FMT_JPEG) {
6944 +               mrst_isp_disable_interrupt(isp);
6945 +               ci_isp_jpe_init_ex(isp->bufwidth, isp->bufheight,
6946 +                                  isp->sys_conf.isp_cfg.jpeg_enc_ratio,
6947 +                                  true);
6948 +               ci_jpe_capture(isp, CI_ISP_CFG_UPDATE_FRAME_SYNC);
6949 +
6950 +               vb = isp->active;
6951 +               vb->size = ci_isp_mif_get_byte_cnt();
6952 +               vb->state = VIDEOBUF_DONE;
6953 +               do_gettimeofday(&vb->ts);
6954 +               vb->field_count++;
6955 +               wake_up(&vb->done);
6956 +               isp->active = NULL;
6957 +
6958 +               dprintk(2, "countcount = %lx", vb->size);
6959 +       } else if (isp->pixelformat == INTEL_PIX_FMT_RAW08
6960 +                  || isp->pixelformat == INTEL_PIX_FMT_RAW10
6961 +                  || isp->pixelformat == INTEL_PIX_FMT_RAW12) {
6962 +                       mrst_isp_disable_interrupt(isp);
6963 +                       ci_isp_start(1, CI_ISP_CFG_UPDATE_FRAME_SYNC);
6964 +                       ci_isp_wait_for_frame_end(isp);
6965 +
6966 +                       /* update captured frame status */
6967 +                       vb = isp->active;
6968 +                       /* vb->size = ci_isp_mif_get_byte_cnt(); */
6969 +                       vb->state = VIDEOBUF_DONE;
6970 +                       do_gettimeofday(&vb->ts);
6971 +                       vb->field_count++;
6972 +                       wake_up(&vb->done);
6973 +                       isp->active = NULL;
6974 +                       /* ci_isp_reg_dump_all(); */
6975 +                       dprintk(3, "captured  index = %d", vb->i);
6976 +       } else if (to_sensor_config(isp->sensor_curr)->mipi_mode) {
6977 +               ci_isp_start(0, CI_ISP_CFG_UPDATE_IMMEDIATE);
6978 +
6979 +               if (mipi_flag) {
6980 +                       v4l2_subdev_call(isp->sensor_curr, video, s_stream, 1);
6981 +
6982 +                       while (mipi_data_id) {
6983 +                               mipi_data_id =
6984 +                                   REG_READ_EX(mrv_reg->mipi_cur_data_id);
6985 +                               dprintk(5, "mipi_cur_data_id = %x",
6986 +                                       mipi_data_id);
6987 +                       }
6988 +                       mipi_flag = 0;
6989 +               }
6990 +       } else
6991 +               ci_isp_start(0, CI_ISP_CFG_UPDATE_FRAME_SYNC);
6992 +
6993 +       return 0;
6994 +}
6995 +
6996 +static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
6997 +                       unsigned int *size)
6998 +{
6999 +       struct mrst_isp_fh  *fh = vq->priv_data;
7000 +       struct mrst_isp_device *isp  = fh->dev;
7001 +
7002 +       u32 w = isp->bufwidth;
7003 +       u32 h = isp->bufheight;
7004 +       u32 depth = isp->depth;
7005 +       u32 fourcc = isp->pixelformat;
7006 +
7007 +       if (fourcc == V4L2_PIX_FMT_JPEG) {
7008 +               *size = PAGE_ALIGN((isp->mb1_size
7009 +                                   - 640*480*2)/(*count)) - PAGE_SIZE;
7010 +               /* *size = PAGE_ALIGN(2 * 1024 * 1024); */
7011 +       } else if (fourcc == INTEL_PIX_FMT_RAW08
7012 +                  || fourcc == INTEL_PIX_FMT_RAW10
7013 +                  || fourcc == INTEL_PIX_FMT_RAW12) {
7014 +               *size = (w * h * depth)/8;
7015 +       } else {
7016 +               *size = (w * h * depth)/8;
7017 +       }
7018 +
7019 +       isp->frame_size = *size;
7020 +       isp->num_frames = *count;
7021 +
7022 +       if (0 == *count)
7023 +               *count = 3;
7024 +
7025 +       while (*size * *count > isp->mb1_size)
7026 +               (*count)--;
7027 +
7028 +       dprintk(1, "count=%d, size=%d", *count, *size);
7029 +       return 0;
7030 +}
7031 +
7032 +static void free_buffer(struct videobuf_queue *vq, struct mrst_isp_buffer *buf)
7033 +{
7034 +       struct videobuf_buffer *vb = &buf->vb;
7035 +
7036 +       dprintk(1, "(vb=0x%p) baddr = 0x%08lx bsize = %d", vb,
7037 +               vb->baddr, vb->bsize);
7038 +
7039 +       videobuf_dma_contig_free(vq, vb);
7040 +
7041 +       buf->vb.state = VIDEOBUF_NEEDS_INIT;
7042 +       dprintk(1, "free_buffer: freed");
7043 +}
7044 +
7045 +static int buffer_prepare(struct videobuf_queue *vq,
7046 +                         struct videobuf_buffer *vb, enum v4l2_field field)
7047 +{
7048 +       struct mrst_isp_fh     *fh  = vq->priv_data;
7049 +       struct mrst_isp_device *isp = fh->dev;
7050 +       struct mrst_isp_buffer *buf = container_of(vb, struct mrst_isp_buffer,
7051 +                                                  vb);
7052 +       int ret;
7053 +
7054 +       if (vb->width != isp->bufwidth || vb->height != isp->bufheight
7055 +          || vb->field != field) {
7056 +               /* buf->fmt       = isp->pixelformat; */
7057 +               vb->width  = isp->bufwidth;
7058 +               vb->height = isp->bufheight;
7059 +               vb->field  = field;
7060 +               vb->state = VIDEOBUF_NEEDS_INIT;
7061 +       }
7062 +
7063 +       vb->size = isp->frame_size;
7064 +
7065 +       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
7066 +               ret = videobuf_iolock(vq, vb, NULL);
7067 +               if (ret)
7068 +                       goto fail;
7069 +               vb->state = VIDEOBUF_PREPARED;
7070 +       }
7071 +
7072 +       return 0;
7073 +
7074 +fail:
7075 +       printk(KERN_ERR "mrstisp: error calling videobuf_iolock");
7076 +       free_buffer(vq, buf);
7077 +       return ret;
7078 +}
7079 +
7080 +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
7081 +{
7082 +       struct mrst_isp_fh        *fh   = vq->priv_data;
7083 +       struct mrst_isp_device       *isp  = fh->dev;
7084 +       u32 bufbase;
7085 +
7086 +       vb->state = VIDEOBUF_QUEUED;
7087 +       dprintk(1, "buffer %d in buffer querue", vb->i);
7088 +       if (isp->stopflag) {
7089 +               list_add_tail(&vb->queue, &isp->capture);
7090 +               if (isp->active) {
7091 +                       /* dprintk(1, "AAAAAAAAAA in flag condition"); */
7092 +                       /* isp->active->state = VIDEOBUF_ACTIVE; */
7093 +                       /* mrst_isp_to_do_mblk_line = 1; */
7094 +                       bufbase = videobuf_to_dma_contig(vb);
7095 +                       mrst_isp_update_marvinvfaddr(isp, bufbase, 0);
7096 +                       /* mrst_isp_enable_interrupt(isp); */
7097 +               } else {
7098 +                       isp->active = vb;
7099 +                       mrst_isp_enable_interrupt(isp);
7100 +                       /*
7101 +                       dprintk(1, "xxxxxxxxx in flag condition");
7102 +                       isp->active->state = VIDEOBUF_ACTIVE;
7103 +                       mrst_isp_to_do_mblk_line = 1;
7104 +                       bufbase = videobuf_to_dma_contig(isp->active);
7105 +                       mrst_isp_update_marvinvfaddr(isp, bufbase,
7106 +                       CI_ISP_CFG_UPDATE_FRAME_SYNC);
7107 +                       */
7108 +               }
7109 +               isp->stopflag = 0;
7110 +       } else if (!isp->active) {
7111 +               dprintk(1, "no active queue");
7112 +               isp->active = vb;
7113 +               isp->active->state = VIDEOBUF_ACTIVE;
7114 +               mrst_isp_to_do_mblk_line = 1;
7115 +               mrst_ci_capture(isp);
7116 +       } else {
7117 +               dprintk(1, "capture to active queue");
7118 +               list_add_tail(&vb->queue, &isp->capture);
7119 +       }
7120 +
7121 +       return;
7122 +}
7123 +
7124 +static void buffer_release(struct videobuf_queue *vq,
7125 +                          struct videobuf_buffer *vb)
7126 +{
7127 +       struct mrst_isp_buffer *buf = container_of(vb,
7128 +                                                  struct mrst_isp_buffer, vb);
7129 +       DBG_entering;
7130 +       free_buffer(vq, buf);
7131 +       DBG_leaving;
7132 +}
7133 +
7134 +static struct videobuf_queue_ops mrst_isp_videobuf_qops = {
7135 +       .buf_setup      = buffer_setup,
7136 +       .buf_prepare    = buffer_prepare,
7137 +       .buf_queue      = buffer_queue,
7138 +       .buf_release    = buffer_release,
7139 +};
7140 +
7141 +static int mrst_isp_open(struct file *file)
7142 +{
7143 +       struct video_device *vdev = video_devdata(file);
7144 +       struct mrst_isp_device *isp = video_get_drvdata(vdev);
7145 +       struct mrst_isp_fh *fh = NULL;
7146 +       struct v4l2_format sensor_format;
7147 +       int ret;
7148 +
7149 +       DBG_entering;
7150 +
7151 +       if (!isp) {
7152 +               printk(KERN_ERR "null in mrst_isp_open\n");
7153 +               return -ENODEV;
7154 +       }
7155 +
7156 +       dprintk(2, "open = %d", isp->open);
7157 +       mutex_lock(&isp->mutex);
7158 +    if (isp->open == 0) {
7159 +               if (isp->sensor_soc) {
7160 +                       dprintk(0, "cur senfor soc");
7161 +                       isp->sensor_curr = isp->sensor_soc;
7162 +               } else {
7163 +                       dprintk(0, "cur sensor raw");
7164 +                       isp->sensor_curr = isp->sensor_raw;
7165 +               }
7166 +       }
7167 +       ++isp->open;
7168 +
7169 +       ret = v4l2_subdev_call(isp->sensor_curr, video, g_fmt,
7170 +                              &sensor_format);
7171 +       if (ret) {
7172 +               printk(KERN_ERR "can't get current pix from sensor!\n");
7173 +               ret = -EINVAL;
7174 +               goto exit_unlock;
7175 +       }
7176 +
7177 +       dprintk(1, "current sensor format: %d x %d",
7178 +               sensor_format.fmt.pix.width,
7179 +               sensor_format.fmt.pix.height);
7180 +
7181 +       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
7182 +       if (NULL == fh) {
7183 +               printk(KERN_ERR "no mem for fh \n");
7184 +               ret = -ENOMEM;
7185 +               goto exit_unlock;
7186 +       }
7187 +
7188 +       file->private_data = fh;
7189 +       fh->dev = isp;
7190 +
7191 +       videobuf_queue_dma_contig_init(&fh->vb_q, &mrst_isp_videobuf_qops,
7192 +                                      vdev->parent, &isp->lock,
7193 +                                      V4L2_BUF_TYPE_VIDEO_CAPTURE,
7194 +                                      V4L2_FIELD_NONE,
7195 +                                      sizeof(struct mrst_isp_buffer), fh);
7196 +
7197 +exit_unlock:
7198 +       mutex_unlock(&isp->mutex);
7199 +       DBG_leaving;
7200 +       return 0;
7201 +}
7202 +
7203 +static int mrst_isp_close(struct file *file)
7204 +{
7205 +       struct video_device *dev = video_devdata(file);
7206 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7207 +       struct mrst_isp_fh  *fh = file->private_data;
7208 +       unsigned long flags;
7209 +
7210 +       DBG_entering;
7211 +       mutex_lock(&isp->mutex);
7212 +       --isp->open;
7213 +       dprintk(2, "close = %d", isp->open);
7214 +       if (isp->open == 0) {
7215 +               if (isp->streaming == 1) {
7216 +                       videobuf_streamoff(&fh->vb_q);
7217 +                       isp->streaming = 0;
7218 +                       isp->buffer_required = 0;
7219 +                       isp->stopflag = 0;
7220 +
7221 +                       spin_lock_irqsave(&isp->lock, flags);
7222 +                       INIT_LIST_HEAD(&isp->capture);
7223 +                       isp->active = NULL;
7224 +                       isp->next = NULL;
7225 +                       isp->sys_conf.isp_hal_enable = 0;
7226 +                       isp->sys_conf.jpg_review_enable = 0;
7227 +                       spin_unlock_irqrestore(&isp->lock, flags);
7228 +
7229 +                       ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC);
7230 +                       v4l2_subdev_call(isp->sensor_curr, video, s_stream, 0);
7231 +                       isp->sensor_curr = NULL;
7232 +               }
7233 +               if (isp->sensor_soc)
7234 +                       v4l2_subdev_call(isp->sensor_soc, core, s_gpio, 1);
7235 +               if (isp->sensor_raw)
7236 +                       v4l2_subdev_call(isp->sensor_raw, core, s_gpio, 1);
7237 +       }
7238 +
7239 +       kfree(file->private_data);
7240 +
7241 +       mutex_unlock(&isp->mutex);
7242 +
7243 +       /*XXX zheng*/
7244 +       if (isp->open == 0)
7245 +               frame_cnt = 0;
7246 +
7247 +       DBG_leaving;
7248 +       return 0;
7249 +}
7250 +
7251 +static ssize_t mrst_isp_read(struct file *file, char __user *buf,
7252 +                            size_t count, loff_t *ppos)
7253 +{
7254 +       return 0;
7255 +}
7256 +
7257 +static void mrst_isp_videobuf_vm_open(struct vm_area_struct *vma)
7258 +{
7259 +       struct videobuf_mapping *map = vma->vm_private_data;
7260 +
7261 +       dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
7262 +               map, map->count, vma->vm_start, vma->vm_end);
7263 +
7264 +       map->count++;
7265 +}
7266 +
7267 +static void mrst_isp_videobuf_vm_close(struct vm_area_struct *vma)
7268 +{
7269 +       struct videobuf_mapping *map = vma->vm_private_data;
7270 +       struct videobuf_queue *q = map->q;
7271 +       int i;
7272 +
7273 +       dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
7274 +               map, map->count, vma->vm_start, vma->vm_end);
7275 +
7276 +       map->count--;
7277 +       if (0 == map->count) {
7278 +               struct videobuf_dma_contig_memory *mem;
7279 +
7280 +               dprintk(2, "munmap %p q=%p\n", map, q);
7281 +               mutex_lock(&q->vb_lock);
7282 +
7283 +               /* We need first to cancel streams, before unmapping */
7284 +               if (q->streaming)
7285 +                       videobuf_queue_cancel(q);
7286 +
7287 +               for (i = 0; i < VIDEO_MAX_FRAME; i++) {
7288 +                       if (NULL == q->bufs[i])
7289 +                               continue;
7290 +
7291 +                       if (q->bufs[i]->map != map)
7292 +                               continue;
7293 +
7294 +                       mem = q->bufs[i]->priv;
7295 +                       if (mem) {
7296 +                               /* This callback is called only if kernel has
7297 +                                  allocated memory and this memory is mmapped.
7298 +                                  In this case, memory should be freed,
7299 +                                  in order to do memory unmap.
7300 +                                */
7301 +
7302 +                               MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
7303 +
7304 +                               /* vfree is not atomic - can't be
7305 +                                  called with IRQ's disabled
7306 +                                */
7307 +                               dprintk(2, "buf[%d] freeing %p\n",
7308 +                                       i, mem->vaddr);
7309 +
7310 +                               /*
7311 +                               dma_free_coherent(q->dev, mem->size,
7312 +                                                 mem->vaddr, mem->dma_handle);
7313 +                                                 */
7314 +                               mem->vaddr = NULL;
7315 +                       }
7316 +
7317 +                       q->bufs[i]->map   = NULL;
7318 +                       q->bufs[i]->baddr = 0;
7319 +               }
7320 +
7321 +               kfree(map);
7322 +
7323 +               mutex_unlock(&q->vb_lock);
7324 +       }
7325 +}
7326 +
7327 +static struct vm_operations_struct mrst_isp_videobuf_vm_ops = {
7328 +       .open     = mrst_isp_videobuf_vm_open,
7329 +       .close    = mrst_isp_videobuf_vm_close,
7330 +};
7331 +
7332 +static int mrst_isp_mmap_mapper(struct videobuf_queue *q,
7333 +                                 struct vm_area_struct *vma)
7334 +{
7335 +       struct videobuf_dma_contig_memory *mem;
7336 +       struct videobuf_mapping *map;
7337 +       unsigned int first;
7338 +       int retval;
7339 +       unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT;
7340 +
7341 +       struct mrst_isp_fh  *fh = q->priv_data;
7342 +       struct mrst_isp_device *isp  = fh->dev;
7343 +
7344 +       DBG_entering;
7345 +
7346 +       if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
7347 +               return -EINVAL;
7348 +
7349 +       /* look for first buffer to map */
7350 +       for (first = 0; first < VIDEO_MAX_FRAME; first++) {
7351 +               if (!q->bufs[first])
7352 +                       continue;
7353 +
7354 +               if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
7355 +                       continue;
7356 +               if (q->bufs[first]->boff == offset) {
7357 +                       dprintk(1, "buff id %d is mapped", first);
7358 +                       break;
7359 +               }
7360 +       }
7361 +       if (VIDEO_MAX_FRAME == first) {
7362 +               eprintk("invalid user space offset [offset=0x%lx]", offset);
7363 +               return -EINVAL;
7364 +       }
7365 +
7366 +       /* create mapping + update buffer list */
7367 +       map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
7368 +       if (!map)
7369 +               return -ENOMEM;
7370 +
7371 +       q->bufs[first]->map = map;
7372 +       map->start = vma->vm_start;
7373 +       map->end = vma->vm_end;
7374 +       map->q = q;
7375 +
7376 +       q->bufs[first]->baddr = vma->vm_start;
7377 +
7378 +       mem = q->bufs[first]->priv;
7379 +       BUG_ON(!mem);
7380 +       MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
7381 +
7382 +       mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
7383 +       mem->dma_handle = isp->mb1 + (mem->size * first);
7384 +       mem->vaddr = (void *)0x1;
7385 +       /*
7386 +       mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
7387 +                                       &mem->dma_handle, GFP_KERNEL);
7388 +                                       */
7389 +       if (mem->size > isp->mb1_size) {
7390 +               eprintk("to big size, can not be mmapped");
7391 +               return -EINVAL;
7392 +       }
7393 +
7394 +       /* Try to remap memory */
7395 +
7396 +       size = vma->vm_end - vma->vm_start;
7397 +       size = (size < mem->size) ? size : mem->size;
7398 +
7399 +       dprintk(1, "vm_end - vm_start = %ld, mem-size = %ld", size, mem->size);
7400 +
7401 +       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
7402 +       retval = remap_pfn_range(vma, vma->vm_start,
7403 +                                mem->dma_handle >> PAGE_SHIFT,
7404 +                                size, vma->vm_page_prot);
7405 +       if (retval) {
7406 +               eprintk("mmap: remap failed with error %d. ", retval);
7407 +               goto error;
7408 +       }
7409 +
7410 +       vma->vm_ops          = &mrst_isp_videobuf_vm_ops;
7411 +       vma->vm_flags       |= VM_DONTEXPAND;
7412 +       vma->vm_private_data = map;
7413 +
7414 +       dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
7415 +               map, q, vma->vm_start, vma->vm_end,
7416 +               (long int) q->bufs[first]->bsize,
7417 +               vma->vm_pgoff, first);
7418 +
7419 +       mrst_isp_videobuf_vm_open(vma);
7420 +
7421 +       return 0;
7422 +
7423 +error:
7424 +       kfree(map);
7425 +       return -ENOMEM;
7426 +}
7427 +int mrst_isp_videobuf_mmap_mapper(struct videobuf_queue *q,
7428 +                        struct vm_area_struct *vma)
7429 +{
7430 +       MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
7431 +
7432 +       mutex_lock(&q->vb_lock);
7433 +       mrst_isp_mmap_mapper(q, vma);
7434 +       /* retval = CALL(q, mmap_mapper, q, vma); */
7435 +       q->is_mmapped = 1;
7436 +       mutex_unlock(&q->vb_lock);
7437 +
7438 +       return 0;
7439 +}
7440 +static int mrst_isp_mmap(struct file *file, struct vm_area_struct *vma)
7441 +{
7442 +       int ret;
7443 +       int map_by_myself;
7444 +       struct mrst_isp_fh  *fh;
7445 +       struct video_device *dev = video_devdata(file);
7446 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7447 +       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
7448 +       unsigned long size = vma->vm_end-vma->vm_start;
7449 +       unsigned long page;
7450 +
7451 +       DBG_entering;
7452 +
7453 +       /* temporarily put here */
7454 +       if (isp->open > 1) {
7455 +               printk(KERN_ERR "ISP already opened...");
7456 +               return -EINVAL;
7457 +       }
7458 +
7459 +       fh = file->private_data;
7460 +
7461 +       if (!(vma->vm_flags & (VM_WRITE | VM_READ))
7462 +           || !(vma->vm_flags & VM_SHARED)) {
7463 +               printk(KERN_ERR "mrstisp: wrong vma flag");
7464 +               return -EINVAL;
7465 +       }
7466 +
7467 +       /* to check whether if it is ISP bar 0 map */
7468 +       if (offset == isp->mb0_size + isp->mb1_size) {
7469 +               dprintk(1, "---- map bar0 ----");
7470 +               page = isp->mb0;
7471 +               map_by_myself = 1;
7472 +       } else if (offset == 0 && size == isp->mb1_size) {
7473 +               dprintk(1, "---- map bar1 ----");
7474 +               page = isp->mb1;
7475 +               map_by_myself = 1;
7476 +       } else if (isp->pixelformat == V4L2_PIX_FMT_JPEG
7477 +                  && isp->sys_conf.jpg_review_enable == 1
7478 +                  && offset == isp->sys_conf.jpg_review.offset) {
7479 +               dprintk(1, "---- map jpeg review buffer----");
7480 +               page = isp->mb1 + isp->sys_conf.jpg_review.offset;
7481 +               map_by_myself = 1;
7482 +       } else {
7483 +               dprintk(1, "----map one certain buffer----");
7484 +               map_by_myself = 0;
7485 +       }
7486 +
7487 +       if (map_by_myself) {
7488 +               vma->vm_flags |= VM_IO;
7489 +               vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
7490 +
7491 +               page = page >> PAGE_SHIFT;
7492 +
7493 +               if (remap_pfn_range(vma, vma->vm_start, page, size,
7494 +                                   PAGE_SHARED)) {
7495 +                       printk(KERN_ERR "fail to put MMAP buffer to user space\n");
7496 +                       return -EAGAIN;
7497 +               }
7498 +
7499 +               return 0;
7500 +       }
7501 +
7502 +       if (size > isp->num_frames * PAGE_ALIGN(isp->frame_size)) {
7503 +               eprintk("length is larger than num * size");
7504 +               return -EINVAL;
7505 +       }
7506 +
7507 +       ret = mrst_isp_videobuf_mmap_mapper(&fh->vb_q, vma);
7508 +
7509 +       dprintk(1, "vma start=0x%08lx, size=%ld, offset=%ld ret=%d",
7510 +               (unsigned long)vma->vm_start,
7511 +               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
7512 +               (unsigned long)offset, ret);
7513 +
7514 +       return ret;
7515 +}
7516 +
7517 +static int mrst_isp_g_fmt_cap(struct file *file, void *priv,
7518 +                               struct v4l2_format *f)
7519 +{
7520 +       struct video_device *dev = video_devdata(file);
7521 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7522 +       int ret;
7523 +
7524 +       WARN_ON(priv != file->private_data);
7525 +
7526 +       DBG_entering;
7527 +
7528 +       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
7529 +               f->fmt.pix.width = isp->bufwidth;
7530 +               f->fmt.pix.height = isp->bufheight;
7531 +               f->fmt.pix.pixelformat = isp->pixelformat;
7532 +               f->fmt.pix.bytesperline = (f->fmt.pix.width * isp->depth) >> 3;
7533 +               f->fmt.pix.sizeimage = f->fmt.pix.height
7534 +                   * f->fmt.pix.bytesperline;
7535 +               ret = 0;
7536 +       } else {
7537 +               ret = -EINVAL;
7538 +       }
7539 +
7540 +       dprintk(1, "get fmt %d x %d ", f->fmt.pix.width, f->fmt.pix.height);
7541 +       DBG_leaving;
7542 +       return ret;
7543 +}
7544 +
7545 +static struct intel_fmt *fmt_by_fourcc(unsigned int fourcc)
7546 +{
7547 +       unsigned int i;
7548 +
7549 +       for (i = 0; i < NUM_FORMATS; i++)
7550 +               if (fmts[i].fourcc == fourcc)
7551 +                       return fmts+i;
7552 +       return NULL;
7553 +}
7554 +
7555 +static int mrst_isp_try_fmt_cap(struct file *file, void *priv,
7556 +                               struct v4l2_format *f)
7557 +{
7558 +       struct video_device *dev = video_devdata(file);
7559 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7560 +
7561 +       struct intel_fmt *fmt;
7562 +       int w, h;
7563 +       int ret;
7564 +
7565 +       WARN_ON(priv != file->private_data);
7566 +
7567 +       DBG_entering;
7568 +
7569 +       mutex_lock(&isp->mutex);
7570 +
7571 +       fmt = fmt_by_fourcc(f->fmt.pix.pixelformat);
7572 +       if (NULL == fmt && f->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) {
7573 +               printk(KERN_ERR "mrstisp: fmt not found\n");
7574 +               ret = -EINVAL;
7575 +               goto exit_unlock;
7576 +       }
7577 +
7578 +       w = f->fmt.pix.width;
7579 +       h = f->fmt.pix.height;
7580 +
7581 +       dprintk(1, "sensor name %s: before w = %d, h = %d",
7582 +               isp->sensor_curr->name, w, h);
7583 +
7584 +       ret = v4l2_subdev_call(isp->sensor_curr, video, try_fmt, f);
7585 +       if (ret)
7586 +               goto exit_unlock;
7587 +
7588 +
7589 +       w = f->fmt.pix.width;
7590 +       h = f->fmt.pix.height;
7591 +
7592 +       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 ||
7593 +           f->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
7594 +               if (w < INTEL_MIN_WIDTH)
7595 +                       w = INTEL_MIN_WIDTH;
7596 +               if (w > INTEL_MAX_WIDTH)
7597 +                       w = INTEL_MAX_WIDTH;
7598 +               if (h < INTEL_MIN_HEIGHT)
7599 +                       h = INTEL_MIN_HEIGHT;
7600 +               if (h > INTEL_MAX_HEIGHT)
7601 +                       h = INTEL_MAX_HEIGHT;
7602 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
7603 +       } else {
7604 +               if (w < INTEL_MIN_WIDTH)
7605 +                       w = INTEL_MIN_WIDTH;
7606 +               if (w > INTEL_MAX_WIDTH_MP)
7607 +                       w = INTEL_MAX_WIDTH_MP;
7608 +               if (h < INTEL_MIN_HEIGHT)
7609 +                       h = INTEL_MIN_HEIGHT;
7610 +               if (h > INTEL_MAX_HEIGHT_MP)
7611 +                       h = INTEL_MAX_HEIGHT_MP;
7612 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
7613 +       }
7614 +
7615 +       f->fmt.pix.width = w;
7616 +       f->fmt.pix.height = h;
7617 +
7618 +       f->fmt.pix.field = V4L2_FIELD_NONE;
7619 +       f->fmt.pix.bytesperline = (w * h)/8;
7620 +       if (fmt)
7621 +               f->fmt.pix.sizeimage = (w * h * fmt->depth)/8;
7622 +       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
7623 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
7624 +       f->fmt.pix.priv = 0;
7625 +
7626 +       dprintk(3, "after w = %d, h = %d", w, h);
7627 +       ret = 0;
7628 +
7629 +exit_unlock:
7630 +       mutex_unlock(&isp->mutex);
7631 +
7632 +       DBG_leaving;
7633 +       return ret;
7634 +}
7635 +
7636 +static int mrst_isp_s_fmt_cap(struct file *file, void *priv,
7637 +                                       struct v4l2_format *f)
7638 +{
7639 +       struct video_device *dev = video_devdata(file);
7640 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7641 +       struct intel_fmt *fmt;
7642 +       int ret;
7643 +       unsigned int width_o, height_o;
7644 +       unsigned short width_sensor, height_sensor;
7645 +       unsigned int w, h;
7646 +
7647 +       WARN_ON(priv != file->private_data);
7648 +
7649 +       DBG_entering;
7650 +
7651 +       mipi_flag = 1;
7652 +
7653 +       w = f->fmt.pix.width;
7654 +       h = f->fmt.pix.height;
7655 +
7656 +       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 ||
7657 +           f->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) {
7658 +               if (w < INTEL_MIN_WIDTH)
7659 +                       w = INTEL_MIN_WIDTH;
7660 +               if (w > INTEL_MAX_WIDTH)
7661 +                       w = INTEL_MAX_WIDTH;
7662 +               if (h < INTEL_MIN_HEIGHT)
7663 +                       h = INTEL_MIN_HEIGHT;
7664 +               if (h > INTEL_MAX_HEIGHT)
7665 +                       h = INTEL_MAX_HEIGHT;
7666 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
7667 +       } else {
7668 +               if (w < INTEL_MIN_WIDTH)
7669 +                       w = INTEL_MIN_WIDTH;
7670 +               if (w > INTEL_MAX_WIDTH_MP)
7671 +                       w = INTEL_MAX_WIDTH_MP;
7672 +               if (h < INTEL_MIN_HEIGHT)
7673 +                       h = INTEL_MIN_HEIGHT;
7674 +               if (h > INTEL_MAX_HEIGHT_MP)
7675 +                       h = INTEL_MAX_HEIGHT_MP;
7676 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
7677 +       }
7678 +
7679 +       f->fmt.pix.width = w;
7680 +       f->fmt.pix.height = h;
7681 +
7682 +       width_o = f->fmt.pix.width;
7683 +       height_o = f->fmt.pix.height;
7684 +
7685 +       (void)ci_sensor_res2size(to_sensor_config(isp->sensor_curr)->res,
7686 +                                &width_sensor, &height_sensor);
7687 +
7688 +       ret = mrst_isp_try_fmt_cap(file, priv, f);
7689 +       if (0 != ret) {
7690 +               printk(KERN_ERR "mrstisp: set format failed\n");
7691 +               return ret;
7692 +       }
7693 +
7694 +       /* set fmt for only sensor */
7695 +       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_MPEG) {
7696 +               ret = v4l2_subdev_call(isp->sensor_curr, video, s_fmt, f);
7697 +               dprintk(1, "------------set fmt only for sensor (%d x %d)",
7698 +                       f->fmt.pix.width, f->fmt.pix.height);
7699 +               return ret;
7700 +       }
7701 +
7702 +       if (isp->sys_conf.isp_hal_enable) {
7703 +               /* set fmt for isp */
7704 +               mutex_lock(&isp->mutex);
7705 +               fmt = fmt_by_fourcc(f->fmt.pix.pixelformat);
7706 +
7707 +               isp->pixelformat = fmt->fourcc;
7708 +               isp->depth = fmt->depth;
7709 +
7710 +               dprintk(1, "sensor (%d x %d)", width_sensor, height_sensor);
7711 +               if (width_o < f->fmt.pix.width &&
7712 +                   height_o < f->fmt.pix.height) {
7713 +                       isp->bufwidth = width_o;
7714 +                       isp->bufheight = height_o;
7715 +               } else if (width_sensor < f->fmt.pix.width &&
7716 +                          height_sensor < f->fmt.pix.height) {
7717 +                       isp->bufwidth = width_sensor;
7718 +                       isp->bufheight = height_sensor;
7719 +                       f->fmt.pix.width = width_sensor;
7720 +                       f->fmt.pix.height = height_sensor;
7721 +               } else {
7722 +                       isp->bufwidth = f->fmt.pix.width;
7723 +                       isp->bufheight = f->fmt.pix.height;
7724 +               }
7725 +
7726 +               /* FIXME
7727 +                * check if buf res is larger than
7728 +                * sensor real res(1304x980)
7729 +                * if yes, down buf res to VGA
7730 +                */
7731 +               if (to_sensor_config(isp->sensor_curr)->res ==
7732 +                               SENSOR_RES_VGA_PLUS)
7733 +                       if (isp->bufwidth >= VGA_SIZE_H &&
7734 +                                       isp->bufheight >= VGA_SIZE_V) {
7735 +                               isp->bufwidth = VGA_SIZE_H;
7736 +                               isp->bufheight = VGA_SIZE_V;
7737 +                       }
7738 +
7739 +               mutex_unlock(&isp->mutex);
7740 +
7741 +               dprintk(1, "----------set fmt only to isp: w %d, h%d, "
7742 +                       "fourcc: %lx", isp->bufwidth,
7743 +                       isp->bufheight, fmt->fourcc);
7744 +       } else {
7745 +
7746 +               /* set fmt for both isp and sensor */
7747 +               mutex_lock(&isp->mutex);
7748 +               fmt = fmt_by_fourcc(f->fmt.pix.pixelformat);
7749 +
7750 +               isp->pixelformat = fmt->fourcc;
7751 +               isp->depth = fmt->depth;
7752 +               isp->bufwidth = width_o;
7753 +               isp->bufheight = height_o;
7754 +
7755 +               mutex_unlock(&isp->mutex);
7756 +
7757 +               dprintk(1, "--------set fmt for isp : w%d, h%d, fourcc: %lx",
7758 +                       isp->bufwidth, isp->bufheight, fmt->fourcc);
7759 +               dprintk(1, "--------set fmt for sesnro : w%d, h%d, fourcc: %lx",
7760 +                       f->fmt.pix.width, f->fmt.pix.height, fmt->fourcc);
7761 +
7762 +               ret = v4l2_subdev_call(isp->sensor_curr, video, s_fmt, f);
7763 +       }
7764 +
7765 +       DBG_leaving;
7766 +       return ret;
7767 +}
7768 +
7769 +static int mrst_isp_enum_framesizes(struct file *file, void *priv,
7770 +                                   struct v4l2_frmsizeenum *arg)
7771 +{
7772 +       struct video_device *dev = video_devdata(file);
7773 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7774 +       int ret;
7775 +
7776 +       DBG_entering;
7777 +
7778 +       WARN_ON(priv != file->private_data);
7779 +
7780 +       ret = v4l2_subdev_call(isp->sensor_curr, video, enum_framesizes, arg);
7781 +
7782 +       DBG_leaving;
7783 +       return ret;
7784 +}
7785 +
7786 +static int mrst_isp_enum_frameintervals(struct file *file, void *priv,
7787 +                                       struct v4l2_frmivalenum *arg)
7788 +{
7789 +       struct video_device *dev = video_devdata(file);
7790 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7791 +       int ret;
7792 +
7793 +       DBG_entering;
7794 +
7795 +       WARN_ON(priv != file->private_data);
7796 +
7797 +       ret = v4l2_subdev_call(isp->sensor_curr, video, enum_frameintervals,
7798 +                              arg);
7799 +       DBG_leaving;
7800 +       return ret;
7801 +}
7802 +
7803 +static int mrst_isp_queryctrl(struct file *file, void *priv,
7804 +       struct v4l2_queryctrl *c)
7805 +{
7806 +       struct video_device *vdev = video_devdata(file);
7807 +       struct mrst_isp_device *isp = video_get_drvdata(vdev);
7808 +
7809 +       WARN_ON(priv != file->private_data);
7810 +
7811 +       DBG_entering;
7812 +
7813 +       if (!v4l2_subdev_call(isp->sensor_curr, core, queryctrl, c))
7814 +               return 0;
7815 +       else if (!v4l2_subdev_call(isp->motor, core, queryctrl, c))
7816 +               return 0;
7817 +
7818 +       /* No controls supported */
7819 +       return -EINVAL;
7820 +}
7821 +
7822 +static int mrst_isp_g_ctrl(struct file *file, void *priv,
7823 +                          struct v4l2_control *c)
7824 +{
7825 +       struct video_device *dev = video_devdata(file);
7826 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7827 +       int ret;
7828 +
7829 +       WARN_ON(priv != file->private_data);
7830 +
7831 +       DBG_entering;
7832 +       if (c->id == V4L2_CID_FOCUS_ABSOLUTE) {
7833 +               ret = v4l2_subdev_call(isp->motor, core, g_ctrl, c);
7834 +               dprintk(2, "get focus from motor : %d", c->value);
7835 +               return ret;
7836 +       } else {
7837 +               ret = v4l2_subdev_call(isp->sensor_curr, core, g_ctrl, c);
7838 +               dprintk(2, "get other cotrol from senrsor : %d", c->value);
7839 +               return ret;
7840 +       }
7841 +}
7842 +
7843 +static int mrst_isp_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
7844 +{
7845 +       struct video_device *dev = video_devdata(file);
7846 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7847 +
7848 +       DBG_entering;
7849 +
7850 +       if (c->id == V4L2_CID_FOCUS_ABSOLUTE) {
7851 +               dprintk(2, "setting focus %d to motor", c->value);
7852 +               return v4l2_subdev_call(isp->motor, core, s_ctrl, c);
7853 +       } else {
7854 +               dprintk(2, "setting other ctrls, value = %d", c->value);
7855 +               return v4l2_subdev_call(isp->sensor_curr, core, s_ctrl, c);
7856 +       }
7857 +}
7858 +
7859 +static int mrst_isp_index_to_camera(struct mrst_isp_device *isp, u32 index)
7860 +{
7861 +       int camera = MRST_CAMERA_NONE;
7862 +
7863 +       if (isp->sensor_soc && isp->sensor_raw) {
7864 +               switch (index) {
7865 +               case 0:
7866 +                       camera = isp->sensor_soc_index;
7867 +                       break;
7868 +               case 1:
7869 +                       camera = isp->sensor_raw_index;
7870 +                       break;
7871 +               }
7872 +       } else if (isp->sensor_soc) {
7873 +               switch (index) {
7874 +               case 0:
7875 +                       camera = isp->sensor_soc_index;
7876 +                       break;
7877 +               }
7878 +       } else if (isp->sensor_raw) {
7879 +               switch (index) {
7880 +               case 0:
7881 +                       camera = isp->sensor_raw_index;
7882 +                       break;
7883 +               }
7884 +       }
7885 +
7886 +       return camera;
7887 +}
7888 +
7889 +static int mrst_isp_enum_input(struct file *file, void *priv,
7890 +                           struct v4l2_input *i)
7891 +{
7892 +       struct video_device *vdev = video_devdata(file);
7893 +       struct mrst_isp_device *isp = video_get_drvdata(vdev);
7894 +       int camera;
7895 +
7896 +       DBG_entering;
7897 +
7898 +       WARN_ON(priv != file->private_data);
7899 +
7900 +       camera = mrst_isp_index_to_camera(isp, i->index);
7901 +       if (MRST_CAMERA_NONE == camera)
7902 +               return -EINVAL;
7903 +
7904 +       i->type = V4L2_INPUT_TYPE_CAMERA;
7905 +       i->std = V4L2_STD_UNKNOWN;
7906 +       strcpy(i->name, mrst_camera_table[camera].name);
7907 +
7908 +       DBG_leaving;
7909 +       return 0;
7910 +}
7911 +static int mrst_isp_g_input(struct file *file, void *priv, unsigned int *i)
7912 +{
7913 +       struct video_device *vdev = video_devdata(file);
7914 +       struct mrst_isp_device *isp = video_get_drvdata(vdev);
7915 +
7916 +       DBG_entering;
7917 +
7918 +       WARN_ON(priv != file->private_data);
7919 +
7920 +       if (isp->sensor_soc && isp->sensor_raw)
7921 +               if (isp->sensor_curr == isp->sensor_soc)
7922 +                       *i = 0;
7923 +               else
7924 +                       *i = 1;
7925 +       else
7926 +               *i = 0;
7927 +
7928 +       DBG_leaving;
7929 +       return 0;
7930 +}
7931 +
7932 +static int mrst_isp_s_input(struct file *file, void *priv, unsigned int i)
7933 +{
7934 +       struct video_device *vdev = video_devdata(file);
7935 +       struct mrst_isp_device *isp = video_get_drvdata(vdev);
7936 +
7937 +       int camera;
7938 +
7939 +       DBG_entering;
7940 +
7941 +       if (isp->streaming) {
7942 +               printk(KERN_WARNING "VIDIOC_S_INPUT error: ISP is streaming\n");
7943 +               return -EBUSY;
7944 +       }
7945 +
7946 +       camera = mrst_isp_index_to_camera(isp, i);
7947 +       if (MRST_CAMERA_NONE == camera)
7948 +               return -EINVAL;
7949 +
7950 +       if (mrst_camera_table[camera].type == MRST_CAMERA_SOC)
7951 +               isp->sensor_curr = isp->sensor_soc;
7952 +       else
7953 +               isp->sensor_curr = isp->sensor_raw;
7954 +
7955 +       dprintk(1, "set sensor %s as input", isp->sensor_curr->name);
7956 +
7957 +       DBG_leaving;
7958 +       return 0;
7959 +}
7960 +
7961 +static int mrst_isp_g_ext_ctrls(struct file *file,
7962 +                            void *fh,
7963 +                            struct v4l2_ext_controls *c)
7964 +{
7965 +       struct video_device *dev = video_devdata(file);
7966 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7967 +
7968 +       int ret = -EINVAL;
7969 +
7970 +       DBG_entering;
7971 +
7972 +       if (c->ctrl_class != V4L2_CTRL_CLASS_CAMERA) {
7973 +               printk(KERN_ERR "Invalid control class\n");
7974 +               return ret;
7975 +       }
7976 +
7977 +       c->error_idx = 0;
7978 +       if (isp->motor) {
7979 +               ret = v4l2_subdev_call(isp->motor, core, g_ext_ctrls, c);
7980 +               if (c->error_idx) {
7981 +                       printk(KERN_ERR "mrst: error call g_ext_ctrls\n");
7982 +                       return ret;
7983 +               }
7984 +       }
7985 +
7986 +       DBG_leaving;
7987 +       return 0;
7988 +}
7989 +
7990 +static int mrst_isp_s_ext_ctrls(struct file *file, void *fh,
7991 +                            struct v4l2_ext_controls *c)
7992 +{
7993 +       struct video_device *dev = video_devdata(file);
7994 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
7995 +
7996 +       int ret = -EINVAL;
7997 +
7998 +       DBG_entering;
7999 +
8000 +       if (c->ctrl_class != V4L2_CTRL_CLASS_CAMERA) {
8001 +               printk(KERN_INFO "Invalid control class\n");
8002 +               return ret;
8003 +       }
8004 +
8005 +       c->error_idx = 0;
8006 +       if (isp->motor) {
8007 +               ret = v4l2_subdev_call(isp->motor, core, s_ext_ctrls, c);
8008 +               if (c->error_idx) {
8009 +                       printk(KERN_ERR "mrst: error call s_ext_ctrls\n");
8010 +                       return ret;
8011 +               }
8012 +       }
8013 +
8014 +       DBG_leaving;
8015 +       return 0;
8016 +}
8017 +
8018 +static int mrst_isp_s_std(struct file *filp, void *priv, v4l2_std_id *a)
8019 +{
8020 +       DBG_entering;
8021 +       DBG_leaving;
8022 +       return 0;
8023 +}
8024 +
8025 +static int mrst_isp_querycap(struct file *file, void  *priv,
8026 +       struct v4l2_capability *cap)
8027 +{
8028 +       struct video_device *dev = video_devdata(file);
8029 +
8030 +       DBG_entering;
8031 +
8032 +       strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
8033 +       strlcpy(cap->card, dev->name, sizeof(cap->card));
8034 +
8035 +       cap->version = INTEL_VERSION(0, 5, 0);
8036 +       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
8037 +
8038 +       DBG_leaving;
8039 +
8040 +       return 0;
8041 +}
8042 +
8043 +static int mrst_isp_cropcap(struct file *file, void *priv,
8044 +                                       struct v4l2_cropcap *cap)
8045 +{
8046 +       struct video_device *dev = video_devdata(file);
8047 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
8048 +
8049 +       WARN_ON(priv != file->private_data);
8050 +
8051 +       DBG_entering;
8052 +
8053 +       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8054 +               return -EINVAL;
8055 +
8056 +       cap->bounds.left = 0;
8057 +       cap->bounds.top = 0;
8058 +       cap->bounds.width = isp->bufwidth;
8059 +       cap->bounds.height = isp->bufheight;
8060 +       cap->defrect = cap->bounds;
8061 +       cap->pixelaspect.numerator   = 1;
8062 +       cap->pixelaspect.denominator = 1;
8063 +
8064 +       DBG_leaving;
8065 +
8066 +       return 0;
8067 +}
8068 +
8069 +static int mrst_isp_enum_fmt_cap(struct file *file, void  *priv,
8070 +                                       struct v4l2_fmtdesc *f)
8071 +{
8072 +       struct video_device *dev = video_devdata(file);
8073 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
8074 +
8075 +       unsigned int index;
8076 +
8077 +       DBG_entering;
8078 +
8079 +       index = f->index;
8080 +
8081 +       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8082 +               return -EINVAL;
8083 +       else {
8084 +               if (isp->sensor_curr == isp->sensor_soc)
8085 +                       if (index >= 8)
8086 +                               return -EINVAL;
8087 +               if (index >= sizeof(fmts) / sizeof(*fmts))
8088 +                       return -EINVAL;
8089 +
8090 +               f->index = index;
8091 +               f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
8092 +               strlcpy(f->description, fmts[index].name,
8093 +                       sizeof(f->description));
8094 +               f->pixelformat = fmts[index].fourcc;
8095 +               if (fmts[index].fourcc == V4L2_PIX_FMT_JPEG)
8096 +                       f->flags = V4L2_FMT_FLAG_COMPRESSED;
8097 +       }
8098 +
8099 +       DBG_leaving;
8100 +
8101 +       return 0;
8102 +
8103 +}
8104 +
8105 +#define ALIGN4(x)       ((((long)(x)) & 0x3) == 0)
8106 +
8107 +static int mrst_isp_reqbufs(struct file *file, void *priv,
8108 +               struct v4l2_requestbuffers *req)
8109 +{
8110 +       int ret;
8111 +       struct mrst_isp_fh  *fh = file->private_data;
8112 +       struct video_device *dev = video_devdata(file);
8113 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
8114 +
8115 +       WARN_ON(priv != file->private_data);
8116 +
8117 +       DBG_entering;
8118 +       if (req->count == 0)
8119 +               return 0;
8120 +
8121 +       /*
8122 +        * if (req->count > 3)
8123 +               req->count = 3;
8124 +       */
8125 +
8126 +       if (req->memory != V4L2_MEMORY_MMAP) {
8127 +               eprintk("wrong memory type");
8128 +               return -EINVAL;
8129 +       }
8130 +       ret = videobuf_reqbufs(&fh->vb_q, req);
8131 +       if (ret)
8132 +               eprintk("err calling videobuf_reqbufs ret = %d", ret);
8133 +
8134 +       if (!ret)
8135 +               isp->buffer_required = 1;
8136 +
8137 +       DBG_leaving;
8138 +       return ret;
8139 +}
8140 +
8141 +static int mrst_isp_querybuf(struct file *file, void *priv,
8142 +                                       struct v4l2_buffer *buf)
8143 +{
8144 +       int ret;
8145 +       struct mrst_isp_fh  *fh = file->private_data;
8146 +
8147 +       WARN_ON(priv != file->private_data);
8148 +
8149 +       DBG_entering;
8150 +       ret = videobuf_querybuf(&fh->vb_q, buf);
8151 +
8152 +       DBG_leaving;
8153 +       return ret;
8154 +}
8155 +
8156 +static int mrst_isp_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
8157 +{
8158 +       int ret;
8159 +       struct mrst_isp_fh  *fh = file->private_data;
8160 +
8161 +       WARN_ON(priv != file->private_data);
8162 +
8163 +       DBG_entering;
8164 +       ret = videobuf_qbuf(&fh->vb_q, buf);
8165 +       /* identify which video buffer was q-ed */
8166 +       if (ret == 0)
8167 +               fh->qbuf_flag |= (1<<buf->index);
8168 +       dprintk(1, "q-ed index = %d", buf->index);
8169 +
8170 +       DBG_leaving;
8171 +
8172 +       return ret;
8173 +}
8174 +
8175 +static int mrst_isp_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
8176 +{
8177 +       int ret;
8178 +       struct mrst_isp_fh  *fh = file->private_data;
8179 +
8180 +       WARN_ON(priv != file->private_data);
8181 +
8182 +       /*XXX zheng*/
8183 +       /*
8184 +       if (frame_cnt == 0) {
8185 +               printk(KERN_WARNING "timer start\n");
8186 +               intel_timer_start();
8187 +       }
8188 +       */
8189 +
8190 +       DBG_entering;
8191 +
8192 +       if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8193 +               return -EINVAL;
8194 +       if (b->memory != V4L2_MEMORY_MMAP)
8195 +               return -EINVAL;
8196 +       if (fh->qbuf_flag == 0) {
8197 +               dprintk(1, "no buffer can be dq-ed\n");
8198 +               return -EINVAL;
8199 +       }
8200 +
8201 +       /*dprintk(3, "entering");*/
8202 +       /* ret = videobuf_dqbuf(&fh->vb_q, b, file->f_flags & O_NONBLOCK); */
8203 +       ret = videobuf_dqbuf(&fh->vb_q, b, 0);
8204 +       /* identify which video buffer was dq-ed */
8205 +       if (ret == 0)
8206 +               fh->qbuf_flag &= ~(1<<b->index);
8207 +
8208 +       /*XXX zheng*/
8209 +       ++frame_cnt;
8210 +       /*
8211 +       if (frame_cnt % 10 == 0)
8212 +               printk(KERN_WARNING "%d frames takes %dms to go, fps = %d\n",
8213 +                      frame_cnt, intel_get_micro_sec(),
8214 +                      frame_cnt * 1000 / intel_get_micro_sec());
8215 +                      */
8216 +
8217 +       dprintk(1, "dq-ed index = %d", b->index);
8218 +       DBG_leaving;
8219 +       return ret;
8220 +}
8221 +
8222 +static int mrst_isp_streamon(struct file *file, void *priv,
8223 +                            enum v4l2_buf_type type)
8224 +{
8225 +       struct mrst_isp_fh  *fh = file->private_data;
8226 +       struct video_device *dev = video_devdata(file);
8227 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
8228 +       int ret;
8229 +
8230 +       DBG_entering;
8231 +
8232 +       if (!isp->buffer_required) {
8233 +               eprintk("buffer is not required, can not stream on ");
8234 +               return -EINVAL;
8235 +       }
8236 +
8237 +       dprintk(2, "gamma2 = %d", isp->sys_conf.isp_cfg.flags.gamma2);
8238 +       WARN_ON(priv != file->private_data);
8239 +
8240 +       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8241 +               return -EINVAL;
8242 +
8243 +       mutex_lock(&isp->mutex);
8244 +
8245 +       if (!to_sensor_config(isp->sensor_curr)->mipi_mode)
8246 +               v4l2_subdev_call(isp->sensor_curr, video, s_stream, 1);
8247 +
8248 +       mrst_isp_dp_init(&isp->sys_conf, to_sensor_config(isp->sensor_curr));
8249 +       mrst_isp_setup_viewfinder_path(isp,
8250 +                                      to_sensor_config(isp->sensor_curr), -1);
8251 +
8252 +       ret = videobuf_streamon(&fh->vb_q);
8253 +       isp->streaming = 1;
8254 +
8255 +       mutex_unlock(&isp->mutex);
8256 +
8257 +       dprintk(1, "isp->active = %p", isp->active);
8258 +       DBG_leaving;
8259 +       return ret;
8260 +}
8261 +
8262 +static int mrst_isp_streamoff(struct file *file, void *priv,
8263 +                             enum v4l2_buf_type type)
8264 +{
8265 +       struct mrst_isp_fh  *fh = file->private_data;
8266 +       struct video_device *dev = video_devdata(file);
8267 +       struct mrst_isp_device *isp = video_get_drvdata(dev);
8268 +
8269 +       unsigned long flags;
8270 +       int ret;
8271 +
8272 +       DBG_entering;
8273 +
8274 +       WARN_ON(priv != file->private_data);
8275 +
8276 +       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8277 +               return -EINVAL;
8278 +
8279 +       mutex_lock(&isp->mutex);
8280 +
8281 +       ret = videobuf_streamoff(&fh->vb_q);
8282 +       dprintk(1, "ret of videobuf_streamoff = %d", ret);
8283 +       isp->streaming = 0;
8284 +
8285 +       spin_lock_irqsave(&isp->lock, flags);
8286 +       INIT_LIST_HEAD(&isp->capture);
8287 +       isp->active = NULL;
8288 +       isp->next = NULL;
8289 +       isp->stopflag = 0;
8290 +       isp->sys_conf.isp_hal_enable = 0;
8291 +       isp->sys_conf.jpg_review_enable = 0;
8292 +       isp->sys_conf.isp_cfg.img_eff_cfg.mode = CI_ISP_IE_MODE_OFF;
8293 +       isp->sys_conf.isp_cfg.jpeg_enc_ratio = 1;
8294 +
8295 +       spin_unlock_irqrestore(&isp->lock, flags);
8296 +
8297 +       v4l2_subdev_call(isp->sensor_curr, video, s_stream, 0);
8298 +       ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC);
8299 +
8300 +       mutex_unlock(&isp->mutex);
8301 +
8302 +       DBG_leaving;
8303 +       return ret;
8304 +}
8305 +
8306 +static const struct v4l2_file_operations mrst_isp_fops = {
8307 +       .owner = THIS_MODULE,
8308 +       .open = mrst_isp_open,
8309 +       .release = mrst_isp_close,
8310 +       .read = mrst_isp_read,
8311 +       .mmap = mrst_isp_mmap,
8312 +       .ioctl = video_ioctl2,
8313 +};
8314 +
8315 +static const struct v4l2_ioctl_ops mrst_isp_ioctl_ops = {
8316 +       .vidioc_querycap                = mrst_isp_querycap,
8317 +       .vidioc_enum_fmt_vid_cap        = mrst_isp_enum_fmt_cap,
8318 +       .vidioc_g_fmt_vid_cap           = mrst_isp_g_fmt_cap,
8319 +       /* .vidioc_g_fmt_vid_out                =
8320 +        * mrst_isp_g_fmt_cap_for_sensor_hal, */
8321 +       .vidioc_try_fmt_vid_cap         = mrst_isp_try_fmt_cap,
8322 +       .vidioc_s_fmt_vid_cap           = mrst_isp_s_fmt_cap,
8323 +       .vidioc_cropcap                 = mrst_isp_cropcap,
8324 +       .vidioc_reqbufs                 = mrst_isp_reqbufs,
8325 +       .vidioc_querybuf                = mrst_isp_querybuf,
8326 +       .vidioc_qbuf                    = mrst_isp_qbuf,
8327 +       .vidioc_dqbuf                   = mrst_isp_dqbuf,
8328 +       .vidioc_enum_input              = mrst_isp_enum_input,
8329 +       .vidioc_g_input                 = mrst_isp_g_input,
8330 +       .vidioc_s_input                 = mrst_isp_s_input,
8331 +       .vidioc_s_std                   = mrst_isp_s_std,
8332 +       .vidioc_queryctrl               = mrst_isp_queryctrl,
8333 +       .vidioc_streamon                = mrst_isp_streamon,
8334 +       .vidioc_streamoff               = mrst_isp_streamoff,
8335 +       .vidioc_g_ctrl                  = mrst_isp_g_ctrl,
8336 +       .vidioc_s_ctrl                  = mrst_isp_s_ctrl,
8337 +       .vidioc_enum_framesizes         = mrst_isp_enum_framesizes,
8338 +       .vidioc_enum_frameintervals     = mrst_isp_enum_frameintervals,
8339 +       .vidioc_g_ext_ctrls             = mrst_isp_g_ext_ctrls,
8340 +       .vidioc_s_ext_ctrls             = mrst_isp_s_ext_ctrls,
8341 +       /* FIXME private ioctls */
8342 +       .vidioc_default                 = mrst_isp_vidioc_default,
8343 +};
8344 +
8345 +static struct video_device mrst_isp_vdev = {
8346 +       .name                           = "mrst_isp",
8347 +       .minor                          = -1,
8348 +       .fops                           = &mrst_isp_fops,
8349 +       .ioctl_ops                      = &mrst_isp_ioctl_ops,
8350 +       .release                        = video_device_release_empty,
8351 +};
8352 +
8353 +static int mrst_ci_sensor_probe(struct mrst_isp_device *isp)
8354 +{
8355 +       struct v4l2_subdev *sensor = NULL, *motor = NULL;
8356 +       int i;
8357 +       char *name;
8358 +       u8 addr;
8359 +
8360 +       isp->adapter_sensor = i2c_get_adapter(MRST_I2C_BUS_SENSOR);
8361 +       if (NULL == isp->adapter_sensor) {
8362 +               printk(KERN_ERR "mrstisp: no sensor i2c adapter\n");
8363 +               return -ENODEV;
8364 +       }
8365 +
8366 +       dprintk(1, "got sensor i2c adapter: %s", isp->adapter_sensor->name);
8367 +
8368 +       gpio_request(GPIO_STDBY1_PIN, "Sensor Standby1");
8369 +       gpio_request(GPIO_STDBY2_PIN, "Sensor Standby2");
8370 +       gpio_request(GPIO_RESET_PIN, "Sensor Reset");
8371 +       gpio_request(GPIO_SCLK_25, "Sensor clock");
8372 +       gpio_request(95, "Camera Motor");
8373 +
8374 +       /* Enable sensor related GPIO in system */
8375 +       gpio_direction_output(GPIO_STDBY1_PIN, 0);
8376 +       gpio_direction_output(GPIO_STDBY2_PIN, 0);
8377 +       gpio_direction_output(GPIO_RESET_PIN, 1);
8378 +       gpio_direction_output(GPIO_SCLK_25, 0);
8379 +       /* gpio_direction_output(GPIO_AF_PD, 1); */
8380 +
8381 +       /*
8382 +       gpio_alt_func(GPIO_STDBY1_PIN, 0);
8383 +       gpio_alt_func(GPIO_STDBY2_PIN, 0);
8384 +       gpio_alt_func(GPIO_RESET_PIN, 0);
8385 +       gpio_alt_func(GPIO_SCLK_25, 1);
8386 +       */
8387 +
8388 +       for (i = 0; i < N_CAMERA; i++) {
8389 +               name = mrst_camera_table[i].name;
8390 +               addr = mrst_camera_table[i].sensor_addr;
8391 +               if (mrst_camera_table[i].type == MRST_CAMERA_SOC) {
8392 +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
8393 +                       sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8394 +                                                    isp->adapter_sensor,
8395 +                                                    name, name, addr);
8396 +#else
8397 +                       sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8398 +                                                    isp->adapter_sensor,
8399 +                                                    name, name, addr, NULL);
8400 +#endif
8401 +
8402 +                       if (sensor == NULL) {
8403 +                               dprintk(2, "sensor %s not found", name);
8404 +                               continue;
8405 +                       }
8406 +                       isp->sensor_soc = sensor;
8407 +                       isp->sensor_soc_index = i;
8408 +                       dprintk(0, "soc camera sensor %s-%s successfully found",
8409 +                               name, sensor->name);
8410 +               }
8411 +
8412 +               if (mrst_camera_table[i].type == MRST_CAMERA_RAW) {
8413 +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
8414 +                       sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8415 +                                                    isp->adapter_sensor,
8416 +                                                    name, name, addr);
8417 +#else
8418 +                       sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8419 +                                                    isp->adapter_sensor,
8420 +                                                    name, name, addr, NULL);
8421 +#endif
8422 +
8423 +                       if (sensor == NULL) {
8424 +                               dprintk(2, "sensor %s not found", name);
8425 +                               continue;
8426 +                       }
8427 +                       isp->sensor_raw = sensor;
8428 +                       isp->sensor_raw_index = i;
8429 +                       dprintk(0, "raw camera sensor %s successfully found",
8430 +                               name);
8431 +                       name = mrst_camera_table[i].motor_name;
8432 +                       addr = mrst_camera_table[i].motor_addr;
8433 +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
8434 +                       motor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8435 +                                                   isp->adapter_sensor,
8436 +                                                   name, name, addr);
8437 +#else
8438 +                       motor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8439 +                                                   isp->adapter_sensor,
8440 +                                                   name, name, addr, NULL);
8441 +#endif
8442 +
8443 +                       if (motor == NULL)
8444 +                               dprintk(2, "motor %s not found", name);
8445 +                       else {
8446 +                               isp->motor = motor;
8447 +                               dprintk(0, "motor %s successfully found", name);
8448 +                       }
8449 +               }
8450 +       }
8451 +
8452 +       if (!isp->sensor_soc && !isp->sensor_raw) {
8453 +               dprintk(0, "no camera sensor device attached");
8454 +               return -ENODEV;
8455 +       } else {
8456 +               if (isp->sensor_soc)
8457 +                       isp->sensor_curr = isp->sensor_soc;
8458 +               else
8459 +                       isp->sensor_curr = isp->sensor_raw;
8460 +               return 0;
8461 +       }
8462 +}
8463 +
8464 +static int mrst_ci_flash_probe(struct mrst_isp_device *isp)
8465 +{
8466 +       struct v4l2_subdev *flash = NULL;
8467 +       char *name = "mrst_camera_flash";
8468 +
8469 +       gpio_request(45, "Camera Flash");
8470 +       gpio_direction_output(45, 0);
8471 +
8472 +       isp->adapter_flash = i2c_get_adapter(MRST_I2C_BUS_FLASH);
8473 +       if (NULL == isp->adapter_flash) {
8474 +               dprintk(0, "no flash i2c adapter\n");
8475 +               return -ENODEV;
8476 +       }
8477 +
8478 +       dprintk(1, "got flash i2c adapter: %s", isp->adapter_flash->name);
8479 +
8480 +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
8481 +       flash = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8482 +                                   isp->adapter_flash,
8483 +                                   name, name, 0x53);
8484 +#else
8485 +       flash = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8486 +                                   isp->adapter_flash,
8487 +                                   name, name, 0x53, NULL);
8488 +#endif
8489 +
8490 +       if (flash == NULL) {
8491 +               dprintk(0, "no flash IC found\n");
8492 +               return -ENODEV;
8493 +       }
8494 +
8495 +       dprintk(0, "flash IC found");
8496 +       return 0;
8497 +}
8498 +
8499 +#if IRQ
8500 +static irqreturn_t mrst_isp_irq_handler(int this_irq, void *dev_id)
8501 +{
8502 +       struct isp_register *mrv_reg =
8503 +           (struct isp_register *) MEM_MRV_REG_BASE;
8504 +       struct mrst_isp_device *isp = dev_id;
8505 +       struct videobuf_buffer *vb;
8506 +       unsigned long flags;
8507 +
8508 +       u32     mi_mask = ci_isp_get_frame_end_irq_mask_isp();
8509 +       u32     isp_mask = MRV_ISP_RIS_DATA_LOSS_MASK
8510 +           | MRV_ISP_RIS_PIC_SIZE_ERR_MASK;
8511 +       u32     jpe_status_mask = MRV_JPE_ALL_STAT_MASK;
8512 +       u32     jpe_error_mask = MRV_JPE_ALL_ERR_MASK;
8513 +       u32     mblk_line_mask = MRV_MI_MBLK_LINE_MASK;
8514 +
8515 +       u32     isp_irq;
8516 +       u32     mi_irq;
8517 +       u32     jpe_status_irq;
8518 +       u32     jpe_error_irq;
8519 +       u32     mipi_irq;
8520 +       u32     mblk_line;
8521 +       u32     bufbase;
8522 +
8523 +       isp_irq = REG_READ_EX(mrv_reg->isp_ris) & isp_mask;
8524 +       mi_irq = REG_READ_EX(mrv_reg->mi_ris) & mi_mask;
8525 +
8526 +       mblk_line = REG_READ_EX(mrv_reg->mi_ris) & mblk_line_mask;
8527 +
8528 +       jpe_status_irq = REG_READ_EX(mrv_reg->jpe_status_ris) & jpe_status_mask;
8529 +       jpe_error_irq = REG_READ_EX(mrv_reg->jpe_error_ris) & jpe_error_mask;
8530 +
8531 +       mipi_irq = REG_READ_EX(mrv_reg->mipi_ris) & 0x00f00000;
8532 +
8533 +       dprintk(3, "IRQ: mblk_line = %x, mi_irq = %x, jpe_status_irq = %x,"
8534 +               " jpe_error_irq = %x, isp_irq = %x", mblk_line, mi_irq,
8535 +               jpe_status_irq, jpe_error_irq, isp_irq);
8536 +
8537 +       if (!(isp_irq | mi_irq | jpe_status_irq | jpe_error_irq | mblk_line
8538 +             | mipi_irq)) {
8539 +               dprintk(2, "unknown interrupt");
8540 +               return IRQ_HANDLED;
8541 +       }
8542 +
8543 +       REG_SET_SLICE_EX(mrv_reg->isp_icr, MRV_ISP_ICR_ALL, ON);
8544 +       REG_SET_SLICE_EX(mrv_reg->mi_icr, MRV_MI_ALLIRQS, ON);
8545 +       REG_SET_SLICE_EX(mrv_reg->jpe_error_icr, MRV_JPE_ALL_ERR, ON);
8546 +       REG_SET_SLICE_EX(mrv_reg->jpe_status_icr, MRV_JPE_ALL_STAT, ON);
8547 +       REG_WRITE_EX(mrv_reg->mipi_icr, 0xffffffff);
8548 +
8549 +       if (isp_irq) {
8550 +               /* Currently we don't reset hardware even error detect */
8551 +               dprintk(3, "ISP error IRQ received %x", isp_irq);
8552 +               isp_error_num++;
8553 +               isp_error_flag |= isp_irq;
8554 +               return IRQ_HANDLED;
8555 +       }
8556 +
8557 +       if (mipi_irq) {
8558 +               dprintk(3, "error in mipi_irq %x", mipi_irq);
8559 +               mipi_error_num++;
8560 +               mipi_error_flag |= mipi_irq;
8561 +               return IRQ_HANDLED;
8562 +       }
8563 +
8564 +       if (mblk_line && mrst_isp_to_do_mblk_line) {
8565 +               REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, OFF);
8566 +               dprintk(3, "enter mblk_line irq");
8567 +
8568 +               if (!(isp->active && !isp->next)) {
8569 +                       dprintk(3, "wrong isq status");
8570 +                       if (isp->active)
8571 +                               dprintk(2, "actie->i = %d", isp->active->i);
8572 +                       else
8573 +                               dprintk(2, "actie = NULL");
8574 +                       if (isp->next)
8575 +                               dprintk(2, "next->i = %d", isp->next->i);
8576 +                       else
8577 +                               dprintk(2, "next = NULL");
8578 +                       return IRQ_HANDLED;
8579 +               }
8580 +
8581 +               spin_lock_irqsave(&isp->lock, flags);
8582 +
8583 +               if (!list_empty(&isp->capture)) {
8584 +                       isp->next = list_entry(isp->capture.next,
8585 +                                              struct videobuf_buffer, queue);
8586 +                       isp->next->state = VIDEOBUF_ACTIVE;
8587 +                       bufbase = videobuf_to_dma_contig(isp->next);
8588 +                       mrst_isp_update_marvinvfaddr(isp, bufbase,
8589 +                                            CI_ISP_CFG_UPDATE_FRAME_SYNC);
8590 +                       dprintk(1, "updating new addr, next = %d",
8591 +                               isp->next->i);
8592 +               } else {
8593 +                       isp->stopflag = 1;
8594 +                       dprintk(0, "stop isp");
8595 +               }
8596 +
8597 +               mrst_isp_to_do_mblk_line = 0;
8598 +
8599 +               spin_unlock_irqrestore(&isp->lock, flags);
8600 +
8601 +               /* return IRQ_HANDLED; */
8602 +       }
8603 +
8604 +       if (mi_irq && isp->pixelformat != V4L2_PIX_FMT_JPEG &&
8605 +           !jpe_status_irq) {
8606 +               dprintk(1, "view finding case");
8607 +
8608 +               if (!isp->active) {
8609 +                       dprintk(0, "no active queue, You should not go here");
8610 +                       mrst_isp_to_do_mblk_line = 1;
8611 +                       REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON);
8612 +                       return IRQ_HANDLED;
8613 +               }
8614 +
8615 +               spin_lock_irqsave(&isp->lock, flags);
8616 +
8617 +               /* update captured frame status */
8618 +               vb = isp->active;
8619 +               /* vb->size = ci_isp_mif_get_byte_cnt(); */
8620 +               /* if this buffer has been dq-ed, set nothing to state*/
8621 +               if (vb->state != VIDEOBUF_IDLE)
8622 +                       vb->state = VIDEOBUF_DONE;
8623 +               vb->field_count++;
8624 +
8625 +               isp->active = NULL;
8626 +               dprintk(1, "buf %d size = %lx", vb->i, vb->size);
8627 +               do_gettimeofday(&vb->ts);
8628 +               wake_up(&vb->done);
8629 +
8630 +               if (!isp->next) {
8631 +                       if (!list_empty(&isp->capture)) {
8632 +                               isp->active = list_entry(isp->capture.next,
8633 +                                                struct videobuf_buffer, queue);
8634 +                               list_del_init(&isp->active->queue);
8635 +                               isp->active->state = VIDEOBUF_ACTIVE;
8636 +                               dprintk(3, "start next frame %d",
8637 +                                       isp->active->i);
8638 +                               mrst_isp_to_do_mblk_line = 1;
8639 +                               REG_SET_SLICE(mrv_reg->mi_imsc,
8640 +                                             MRV_MI_MBLK_LINE, ON);
8641 +                       } else {
8642 +                               mrst_isp_to_do_mblk_line = 1;
8643 +                               REG_SET_SLICE(mrv_reg->mi_imsc,
8644 +                                             MRV_MI_MBLK_LINE, ON);
8645 +                               mrst_isp_disable_interrupt(isp);
8646 +                               dprintk(3, "no frame right now");
8647 +                       }
8648 +               } else {
8649 +                       isp->active = isp->next;
8650 +                       list_del_init(&isp->next->queue);
8651 +                       isp->next = NULL;
8652 +                       dprintk(1, "active = next = %d, next = NULL",
8653 +                               isp->active->i);
8654 +                       mrst_isp_to_do_mblk_line = 1;
8655 +                       REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON);
8656 +               }
8657 +
8658 +               spin_unlock_irqrestore(&isp->lock, flags);
8659 +               return IRQ_HANDLED;
8660 +       }
8661 +
8662 +       if (jpe_status_irq) {
8663 +               dprintk(2, "jpeg capture case");
8664 +
8665 +               if (!isp->active)
8666 +                       return IRQ_HANDLED;
8667 +
8668 +               spin_lock_irqsave(&isp->lock, flags);
8669 +
8670 +               vb = isp->active;
8671 +               vb->size = ci_isp_mif_get_byte_cnt();
8672 +               vb->state = VIDEOBUF_DONE;
8673 +               do_gettimeofday(&vb->ts);
8674 +               vb->field_count++;
8675 +               wake_up(&vb->done);
8676 +               isp->active = NULL;
8677 +
8678 +               dprintk(2, "index =%d, bufsize = %lx", vb->i, vb->size);
8679 +
8680 +               spin_unlock_irqrestore(&isp->lock, flags);
8681 +
8682 +               return IRQ_HANDLED;
8683 +       }
8684 +
8685 +       if (jpe_error_irq)
8686 +               dprintk(2, "entered jpe_error_irq");
8687 +
8688 +       return IRQ_HANDLED;
8689 +}
8690 +#endif
8691 +
8692 +static void __devexit mrst_isp_pci_remove(struct pci_dev *pdev)
8693 +{
8694 +       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
8695 +       struct mrst_isp_device *isp = to_isp(v4l2_dev);
8696 +
8697 +       DBG_entering;
8698 +
8699 +       ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC);
8700 +       mrst_isp_disable_interrupt(isp);
8701 +
8702 +#if IRQ
8703 +       free_irq(pdev->irq, isp);
8704 +#endif
8705 +
8706 +       if (isp->vdev) {
8707 +               dprintk(2, "isp->vdev = %p", isp->vdev);
8708 +               video_unregister_device(isp->vdev);
8709 +       }
8710 +
8711 +       dma_release_declared_memory(&pdev->dev);
8712 +
8713 +       iounmap(isp->regs);
8714 +
8715 +       pci_release_regions(pdev);
8716 +
8717 +       pci_disable_device(pdev);
8718 +
8719 +       v4l2_device_unregister(&isp->v4l2_dev);
8720 +
8721 +       kfree(isp);
8722 +
8723 +       DBG_leaving;
8724 +}
8725 +
8726 +static int __devinit mrst_isp_pci_probe(struct pci_dev *pdev,
8727 +                                       const struct pci_device_id *pci_id)
8728 +{
8729 +       struct mrst_isp_device *isp;
8730 +       unsigned int start = 0;
8731 +       unsigned int len = 0;
8732 +       int ret = 0;
8733 +
8734 +       DBG_entering;
8735 +
8736 +       /* alloc device struct */
8737 +       isp = kzalloc(sizeof(struct mrst_isp_device), GFP_KERNEL);
8738 +       if (NULL == isp) {
8739 +               printk(KERN_ERR "mrstisp: fail to kzalloc mrst_isp_device\n");
8740 +               ret = -ENOMEM;
8741 +               goto exit;
8742 +       }
8743 +
8744 +       /* register v4l2 device */
8745 +       ret = v4l2_device_register(&pdev->dev, &isp->v4l2_dev);
8746 +       if (ret) {
8747 +               printk(KERN_ERR "mrstisp: fail to register v4l2 device\n");
8748 +               goto exit_free_isp;
8749 +       }
8750 +
8751 +       /* PCI operations */
8752 +       ret = pci_enable_device(pdev);
8753 +       if (ret) {
8754 +               printk(KERN_ERR "mrstisp: can't enable isp\n");
8755 +               goto exit_unregister_v4l2;
8756 +       }
8757 +
8758 +       pci_set_master(pdev);
8759 +
8760 +       ret = pci_request_regions(pdev, "mrst isp");
8761 +       if (ret) {
8762 +               printk(KERN_ERR "mrstisp: can't request regions\n");
8763 +               goto exit_disable_isp;
8764 +       }
8765 +
8766 +       /* mem bar 0 */
8767 +       start = isp->mb0 = pci_resource_start(pdev, 0);
8768 +       len = isp->mb0_size = pci_resource_len(pdev, 0);
8769 +
8770 +       isp->regs = ioremap_nocache(start, len);
8771 +       mrst_isp_regs = isp->regs;
8772 +       if (isp->regs == NULL) {
8773 +               printk(KERN_ERR "mrstisp: fail to ioremap isp registers\n");
8774 +               goto exit_release_regions;
8775 +       }
8776 +
8777 +       dprintk(1, "isp mb0 = %lx, mb0_size = %lx, regs = %p",
8778 +               isp->mb0, isp->mb0_size, isp->regs);
8779 +
8780 +       /* mem bar 1 */
8781 +       start = isp->mb1 = pci_resource_start(pdev, 1);
8782 +       len = isp->mb1_size = pci_resource_len(pdev, 1);
8783 +
8784 +       dprintk(1, "isp mb1 = %lx, mb1_size = %lx", isp->mb1, isp->mb1_size);
8785 +
8786 +       ret = dma_declare_coherent_memory(&pdev->dev, start,
8787 +                                         /* start, len - 640 * 480 * 2, */
8788 +                                         start, len,
8789 +                                         DMA_MEMORY_MAP);
8790 +                                         /*
8791 +                                         DMA_MEMORY_MAP
8792 +                                         | DMA_MEMORY_EXCLUSIVE);
8793 +                                         */
8794 +       if (!ret) {
8795 +               dprintk(0, "failed to declare dma memory");
8796 +               ret = -ENXIO;
8797 +               goto exit_iounmap;
8798 +       }
8799 +
8800 +       /* init device struct */
8801 +       INIT_LIST_HEAD(&isp->capture);
8802 +       spin_lock_init(&isp->lock);
8803 +       mutex_init(&isp->mutex);
8804 +
8805 +       pci_read_config_word(pdev, PCI_VENDOR_ID, &isp->vendorID);
8806 +       pci_read_config_word(pdev, PCI_DEVICE_ID, &isp->deviceID);
8807 +
8808 +       mrst_isp_defcfg_all_load(&isp->sys_conf.isp_cfg);
8809 +
8810 +       isp->bufwidth = 640;
8811 +       isp->bufheight = 480;
8812 +       isp->depth = 12;
8813 +       isp->pixelformat = V4L2_PIX_FMT_YVU420;
8814 +       isp->streaming = 0;
8815 +       isp->buffer_required = 0;
8816 +
8817 +
8818 +       /* probe sensor */
8819 +       ret = mrst_ci_sensor_probe(isp);
8820 +       if (ret) {
8821 +               dprintk(0, "failed to sensor probe\n");
8822 +               goto exit_dma_release;
8823 +       }
8824 +
8825 +       /* regiter video device */
8826 +       isp->vdev = &mrst_isp_vdev;
8827 +       isp->vdev->parent = &pdev->dev;
8828 +       video_set_drvdata(isp->vdev, isp);
8829 +
8830 +       ret = video_register_device(isp->vdev, VFL_TYPE_GRABBER, -1);
8831 +       if (ret) {
8832 +               dprintk(0, "fail to register video deivice");
8833 +               goto exit_dma_release;
8834 +       }
8835 +
8836 +       dprintk(0, "registered dev/video%d", isp->vdev->num);
8837 +       dprintk(0, "isp->vdev = %p", isp->vdev);
8838 +
8839 +#if IRQ
8840 +       /* request irq */
8841 +       ret = request_irq(pdev->irq, mrst_isp_irq_handler, IRQF_SHARED,
8842 +                         /* pci_name(pdev), isp); */
8843 +                         "mrst_camera_imaging", isp);
8844 +       if (ret) {
8845 +               dprintk(0, "fail to request irq");
8846 +               goto exit_unregister_video;
8847 +       }
8848 +
8849 +       mrst_isp_disable_interrupt(isp);
8850 +#endif
8851 +
8852 +       /* probe flash */
8853 +       mrst_ci_flash_probe(isp);
8854 +
8855 +       mrst_isp_to_do_mblk_line = 0;
8856 +
8857 +       dprintk(0, "mrstisp driver module successfully loaded");
8858 +       return 0;
8859 +
8860 +exit_unregister_video:
8861 +       video_unregister_device(isp->vdev);
8862 +exit_dma_release:
8863 +       dma_release_declared_memory(&pdev->dev);
8864 +exit_iounmap:
8865 +       iounmap(isp->regs);
8866 +exit_release_regions:
8867 +       pci_release_regions(pdev);
8868 +exit_disable_isp:
8869 +       pci_disable_device(pdev);
8870 +exit_unregister_v4l2:
8871 +       v4l2_device_unregister(&isp->v4l2_dev);
8872 +exit_free_isp:
8873 +       kfree(isp);
8874 +exit:
8875 +       return ret;
8876 +}
8877 +
8878 +#ifdef CONFIG_PM
8879 +static int mrst_isp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
8880 +{
8881 +       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
8882 +       struct mrst_isp_device *isp = to_isp(v4l2_dev);
8883 +       int ret;
8884 +
8885 +       DBG_entering;
8886 +
8887 +       ci_isp_off();
8888 +
8889 +       ret = pci_save_state(pdev);
8890 +       if (ret) {
8891 +               printk(KERN_ERR "mrstisp: pci_save_state failed %d\n", ret);
8892 +               return ret;
8893 +       }
8894 +
8895 +       ret = pci_set_power_state(pdev, PCI_D3cold);
8896 +       if (ret) {
8897 +               printk(KERN_ERR "mrstisp: fail to set power state\n");
8898 +               return ret;
8899 +       }
8900 +
8901 +/*
8902 +       ret = ci_sensor_suspend();
8903 +       if (ret) {
8904 +               printk(KERN_ERR "mrstisp: Fail to suspend sensor\n");
8905 +               return ret;
8906 +       }
8907 +*/
8908 +       if (isp->sensor_soc)
8909 +               v4l2_subdev_call(isp->sensor_soc, core, s_gpio, 1);
8910 +       if (isp->sensor_raw)
8911 +               v4l2_subdev_call(isp->sensor_raw, core, s_gpio, 1);
8912 +
8913 +       DBG_leaving;
8914 +       return 0;
8915 +}
8916 +
8917 +static int mrst_isp_pci_resume(struct pci_dev *pdev)
8918 +{
8919 +       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
8920 +       struct mrst_isp_device *isp = to_isp(v4l2_dev);
8921 +       int ret;
8922 +
8923 +       DBG_entering;
8924 +
8925 +       pci_set_power_state(pdev, PCI_D0);
8926 +       pci_restore_state(pdev);
8927 +
8928 +       ret = pci_enable_device(pdev);
8929 +       if (ret) {
8930 +               printk(KERN_ERR "mrstisp: fail to enable device in resume\n");
8931 +               return ret;
8932 +       }
8933 +
8934 +/*
8935 +       ret = ci_sensor_resume();
8936 +       if (ret) {
8937 +               printk(KERN_ERR "mrstisp: Fail to resume sensor\n");
8938 +               return ret;
8939 +       }
8940 +*/
8941 +       if (isp->sensor_soc)
8942 +               v4l2_subdev_call(isp->sensor_soc, core, s_gpio, 0);
8943 +       if (isp->sensor_raw)
8944 +               v4l2_subdev_call(isp->sensor_raw, core, s_gpio, 0);
8945 +
8946 +       ci_isp_init();
8947 +
8948 +       DBG_leaving;
8949 +       return 0;
8950 +}
8951 +#endif
8952 +
8953 +static struct pci_device_id mrst_isp_pci_tbl[] __devinitdata = {
8954 +       { PCI_DEVICE(0x8086, 0x080B) },
8955 +       {0,}
8956 +};
8957 +
8958 +MODULE_DEVICE_TABLE(pci, mrst_isp_pci_tbl);
8959 +
8960 +static struct pci_driver mrst_isp_pci_driver = {
8961 +       .name = "mrstisp",
8962 +       .id_table = mrst_isp_pci_tbl,
8963 +       .probe = mrst_isp_pci_probe,
8964 +       .remove = mrst_isp_pci_remove,
8965 +       #ifdef CONFIG_PM
8966 +       .suspend = mrst_isp_pci_suspend,
8967 +       .resume = mrst_isp_pci_resume,
8968 +       #endif
8969 +};
8970 +
8971 +static int __init mrst_isp_pci_init(void)
8972 +{
8973 +       int ret;
8974 +
8975 +       DBG_entering;
8976 +
8977 +       ret = pci_register_driver(&mrst_isp_pci_driver);
8978 +       if (ret) {
8979 +               printk(KERN_ERR "mrstisp: Unable to register driver\n");
8980 +               return ret;
8981 +       }
8982 +
8983 +       if (ret)
8984 +               dprintk(1, "Unable to register flash driver");
8985 +
8986 +       DBG_leaving;
8987 +       return 0;
8988 +}
8989 +
8990 +static void __exit mrst_isp_pci_exit(void)
8991 +{
8992 +       DBG_entering;
8993 +
8994 +       pci_unregister_driver(&mrst_isp_pci_driver);
8995 +
8996 +       DBG_leaving;
8997 +}
8998 +
8999 +module_init(mrst_isp_pci_init);
9000 +/* late_initcall(mrst_isp_pci_init); */
9001 +module_exit(mrst_isp_pci_exit);
9002 +
9003 +MODULE_DESCRIPTION("Intel Moorestown ISP driver");
9004 +MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
9005 +MODULE_LICENSE("GPL");
9006 +MODULE_SUPPORTED_DEVICE("video");
9007 +
9008 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c b/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c
9009 new file mode 100644
9010 index 0000000..a05731a
9011 --- /dev/null
9012 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c
9013 @@ -0,0 +1,763 @@
9014 +/*
9015 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
9016 + *
9017 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
9018 + *
9019 + * Copyright (c) Silicon Image 2008  www.siliconimage.com
9020 + *
9021 + * This program is free software; you can redistribute it and/or
9022 + * modify it under the terms of the GNU General Public License version
9023 + * 2 as published by the Free Software Foundation.
9024 + *
9025 + * This program is distributed in the hope that it will be useful,
9026 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9027 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9028 + * GNU General Public License for more details.
9029 + *
9030 + * You should have received a copy of the GNU General Public License
9031 + * along with this program; if not, write to the Free Software
9032 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
9033 + * 02110-1301, USA.
9034 + *
9035 + *
9036 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
9037 + */
9038 +
9039 +#include "mrstisp_stdinc.h"
9040 +
9041 +/*
9042 + * sets all main picture and self picture buffer offsets back to 0
9043 + */
9044 +void ci_isp_mif_reset_offsets(enum ci_isp_conf_update_time update_time)
9045 +{
9046 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9047 +
9048 +       REG_SET_SLICE(mrv_reg->mi_mp_y_offs_cnt_init,
9049 +                     MRV_MI_MP_Y_OFFS_CNT_INIT, 0);
9050 +       REG_SET_SLICE(mrv_reg->mi_mp_cb_offs_cnt_init,
9051 +                     MRV_MI_MP_CB_OFFS_CNT_INIT, 0);
9052 +       REG_SET_SLICE(mrv_reg->mi_mp_cr_offs_cnt_init,
9053 +                     MRV_MI_MP_CR_OFFS_CNT_INIT, 0);
9054 +
9055 +       REG_SET_SLICE(mrv_reg->mi_sp_y_offs_cnt_init,
9056 +                     MRV_MI_SP_Y_OFFS_CNT_INIT, 0);
9057 +       REG_SET_SLICE(mrv_reg->mi_sp_cb_offs_cnt_init,
9058 +                     MRV_MI_SP_CB_OFFS_CNT_INIT, 0);
9059 +       REG_SET_SLICE(mrv_reg->mi_sp_cr_offs_cnt_init,
9060 +                     MRV_MI_SP_CR_OFFS_CNT_INIT, 0);
9061 +
9062 +       REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_OFFSET_EN, ON);
9063 +       REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_BASE_EN, ON);
9064 +
9065 +       switch (update_time) {
9066 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
9067 +               break;
9068 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
9069 +               REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9070 +               break;
9071 +       case CI_ISP_CFG_UPDATE_LATER:
9072 +               break;
9073 +       default:
9074 +               break;
9075 +       }
9076 +}
9077 +
9078 +/*
9079 + * This function get the byte count from the last JPEG or raw data transfer
9080 + */
9081 +u32 ci_isp_mif_get_byte_cnt(void)
9082 +{
9083 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9084 +
9085 +       return (u32) REG_GET_SLICE(mrv_reg->mi_byte_cnt, MRV_MI_BYTE_CNT);
9086 +}
9087 +
9088 +/*
9089 + * Sets the desired self picture orientation, if possible.
9090 + */
9091 +static int ci_isp_mif_set_self_pic_orientation(enum ci_isp_mif_sp_mode
9092 +                                               mrv_mif_sp_mode,
9093 +                                               int activate_self_path)
9094 +{
9095 +
9096 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9097 +       u32 mi_ctrl = REG_READ(mrv_reg->mi_ctrl);
9098 +
9099 +       u32 output_format = REG_GET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT);
9100 +
9101 +       /* apply the desired self picture orientation, if possible */
9102 +       switch (mrv_mif_sp_mode) {
9103 +       case CI_ISP_MIF_SP_ORIGINAL:
9104 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, 0);
9105 +               break;
9106 +
9107 +       case CI_ISP_MIF_SP_HORIZONTAL_FLIP:
9108 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9109 +                             MRV_MI_ROT_AND_FLIP_H_FLIP);
9110 +               break;
9111 +
9112 +       case CI_ISP_MIF_SP_VERTICAL_FLIP:
9113 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9114 +                             MRV_MI_ROT_AND_FLIP_V_FLIP);
9115 +               break;
9116 +
9117 +       case CI_ISP_MIF_SP_ROTATION_090_DEG:
9118 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9119 +                             MRV_MI_ROT_AND_FLIP_ROTATE);
9120 +               break;
9121 +
9122 +       case CI_ISP_MIF_SP_ROTATION_180_DEG:
9123 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9124 +                             MRV_MI_ROT_AND_FLIP_H_FLIP |
9125 +                             MRV_MI_ROT_AND_FLIP_V_FLIP);
9126 +               break;
9127 +
9128 +       case CI_ISP_MIF_SP_ROTATION_270_DEG:
9129 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9130 +                             MRV_MI_ROT_AND_FLIP_H_FLIP |
9131 +                             MRV_MI_ROT_AND_FLIP_V_FLIP |
9132 +                             MRV_MI_ROT_AND_FLIP_ROTATE);
9133 +               break;
9134 +
9135 +       case CI_ISP_MIF_SP_ROT_090_V_FLIP:
9136 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9137 +                             MRV_MI_ROT_AND_FLIP_V_FLIP |
9138 +                             MRV_MI_ROT_AND_FLIP_ROTATE);
9139 +               break;
9140 +
9141 +       case CI_ISP_MIF_SP_ROT_270_V_FLIP:
9142 +               REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP,
9143 +                             MRV_MI_ROT_AND_FLIP_H_FLIP |
9144 +                             MRV_MI_ROT_AND_FLIP_ROTATE);
9145 +               break;
9146 +
9147 +       default:
9148 +               eprintk("unknown value for mrv_mif_sp_mode");
9149 +               return CI_STATUS_NOTSUPP;
9150 +       }
9151 +
9152 +       if (REG_GET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP) &
9153 +           MRV_MI_ROT_AND_FLIP_ROTATE) {
9154 +               switch (output_format) {
9155 +               case MRV_MI_SP_OUTPUT_FORMAT_RGB888:
9156 +               case MRV_MI_SP_OUTPUT_FORMAT_RGB666:
9157 +               case MRV_MI_SP_OUTPUT_FORMAT_RGB565:
9158 +                       /* rotation supported on this output modes */
9159 +                       break;
9160 +               default:
9161 +                       eprintk("rotation is only allowed for RGB modes.");
9162 +                       return CI_STATUS_NOTSUPP;
9163 +               }
9164 +       }
9165 +
9166 +       REG_SET_SLICE(mi_ctrl, MRV_MI_SP_ENABLE,
9167 +                     (activate_self_path) ? ENABLE : DISABLE);
9168 +       REG_WRITE(mrv_reg->mi_ctrl, mi_ctrl);
9169 +       REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9170 +
9171 +       return CI_STATUS_SUCCESS;
9172 +}
9173 +
9174 +/*
9175 + * Checks the main or self picture path buffer structure.
9176 + */
9177 +static int ci_isp_mif_check_mi_path_conf(const struct ci_isp_mi_path_conf
9178 +                                        *isp_mi_path_conf, int main_buffer)
9179 +{
9180 +       if (!isp_mi_path_conf) {
9181 +               eprintk("isp_mi_path_conf is NULL");
9182 +               return CI_STATUS_NULL_POINTER;
9183 +       }
9184 +
9185 +       if (!isp_mi_path_conf->ybuffer.pucbuffer) {
9186 +               eprintk("isp_mi_path_conf->ybuffer.pucbuffer is NULL");
9187 +               return CI_STATUS_NULL_POINTER;
9188 +       }
9189 +
9190 +       if (main_buffer) {
9191 +               if ((((unsigned long)(isp_mi_path_conf->ybuffer.pucbuffer)
9192 +                     & ~(MRV_MI_MP_Y_BASE_AD_INIT_VALID_MASK)) != 0)
9193 +                       ||
9194 +                       ((isp_mi_path_conf->ybuffer.size
9195 +                       & ~(MRV_MI_MP_Y_SIZE_INIT_VALID_MASK)) != 0)
9196 +                       ||
9197 +                       ((isp_mi_path_conf->ybuffer.size
9198 +                       & (MRV_MI_MP_Y_SIZE_INIT_VALID_MASK)) == 0)
9199 +                       ||
9200 +                       ((isp_mi_path_conf->ybuffer.offs
9201 +                       & ~(MRV_MI_MP_Y_OFFS_CNT_INIT_VALID_MASK)) != 0)) {
9202 +                               return CI_STATUS_OUTOFRANGE;
9203 +               }
9204 +       } else {
9205 +               if ((((unsigned long) isp_mi_path_conf->ybuffer.pucbuffer
9206 +                       & ~(MRV_MI_SP_Y_BASE_AD_INIT_VALID_MASK)) != 0)
9207 +                       ||
9208 +                       ((isp_mi_path_conf->ybuffer.size &
9209 +                       ~(MRV_MI_SP_Y_SIZE_INIT_VALID_MASK)) != 0)
9210 +                       ||
9211 +                       ((isp_mi_path_conf->ybuffer.size &
9212 +                       (MRV_MI_SP_Y_SIZE_INIT_VALID_MASK)) == 0)
9213 +                       ||
9214 +                       ((isp_mi_path_conf->ybuffer.offs &
9215 +                       ~(MRV_MI_SP_Y_OFFS_CNT_INIT_VALID_MASK)) !=
9216 +                       0)
9217 +                       ||
9218 +                       ((isp_mi_path_conf->llength &
9219 +                       ~(MRV_MI_SP_Y_LLENGTH_VALID_MASK)) != 0)
9220 +                       ||
9221 +                       ((isp_mi_path_conf->
9222 +                       llength & (MRV_MI_SP_Y_LLENGTH_VALID_MASK)) == 0)) {
9223 +                       return CI_STATUS_OUTOFRANGE;
9224 +               }
9225 +       }
9226 +
9227 +       if (isp_mi_path_conf->cb_buffer.pucbuffer != 0) {
9228 +               if (main_buffer) {
9229 +                       if ((((unsigned long)
9230 +                               isp_mi_path_conf->cb_buffer.pucbuffer
9231 +                               & ~(MRV_MI_MP_CB_BASE_AD_INIT_VALID_MASK)) !=
9232 +                               0)
9233 +                               ||
9234 +                               ((isp_mi_path_conf->cb_buffer.size &
9235 +                               ~(MRV_MI_MP_CB_SIZE_INIT_VALID_MASK)) != 0)
9236 +                               ||
9237 +                               ((isp_mi_path_conf->cb_buffer.size &
9238 +                               (MRV_MI_MP_CB_SIZE_INIT_VALID_MASK)) == 0)
9239 +                               ||
9240 +                               ((isp_mi_path_conf->cb_buffer.offs &
9241 +                               ~(MRV_MI_MP_CB_OFFS_CNT_INIT_VALID_MASK)) !=
9242 +                               0)) {
9243 +                                       return CI_STATUS_OUTOFRANGE;
9244 +                       }
9245 +               } else {
9246 +                       if ((((unsigned long)
9247 +                               isp_mi_path_conf->cb_buffer.pucbuffer
9248 +                               & ~(MRV_MI_SP_CB_BASE_AD_INIT_VALID_MASK)) !=
9249 +                               0)
9250 +                               ||
9251 +                               ((isp_mi_path_conf->cb_buffer.size &
9252 +                               ~(MRV_MI_SP_CB_SIZE_INIT_VALID_MASK)) != 0)
9253 +                               ||
9254 +                               ((isp_mi_path_conf->cb_buffer.size &
9255 +                               (MRV_MI_SP_CB_SIZE_INIT_VALID_MASK)) == 0)
9256 +                               ||
9257 +                               ((isp_mi_path_conf->cb_buffer.offs &
9258 +                               ~(MRV_MI_SP_CB_OFFS_CNT_INIT_VALID_MASK)) !=
9259 +                               0)) {
9260 +                                       return CI_STATUS_OUTOFRANGE;
9261 +                       }
9262 +               }
9263 +       }
9264 +
9265 +       if (isp_mi_path_conf->cr_buffer.pucbuffer != 0) {
9266 +               if (main_buffer) {
9267 +                       if ((((unsigned long)
9268 +                               isp_mi_path_conf->cr_buffer.pucbuffer
9269 +                               & ~(MRV_MI_MP_CR_BASE_AD_INIT_VALID_MASK)) !=
9270 +                               0)
9271 +                               ||
9272 +                               ((isp_mi_path_conf->cr_buffer.size &
9273 +                               ~(MRV_MI_MP_CR_SIZE_INIT_VALID_MASK)) != 0)
9274 +                               ||
9275 +                               ((isp_mi_path_conf->cr_buffer.size &
9276 +                               (MRV_MI_MP_CR_SIZE_INIT_VALID_MASK)) == 0)
9277 +                               ||
9278 +                               ((isp_mi_path_conf->cr_buffer.offs &
9279 +                               ~(MRV_MI_MP_CR_OFFS_CNT_INIT_VALID_MASK)) !=
9280 +                               0)){
9281 +                                       return CI_STATUS_OUTOFRANGE;
9282 +                       }
9283 +               } else {
9284 +                       if ((((unsigned long)
9285 +                               isp_mi_path_conf->cr_buffer.pucbuffer
9286 +                               & ~(MRV_MI_SP_CR_BASE_AD_INIT_VALID_MASK))
9287 +                               != 0)
9288 +                           ||
9289 +                           ((isp_mi_path_conf->cr_buffer.size &
9290 +                             ~(MRV_MI_SP_CR_SIZE_INIT_VALID_MASK)) != 0)
9291 +                           ||
9292 +                           ((isp_mi_path_conf->cr_buffer.size &
9293 +                           (MRV_MI_SP_CR_SIZE_INIT_VALID_MASK)) == 0)
9294 +                           ||
9295 +                           ((isp_mi_path_conf->cr_buffer.offs &
9296 +                           ~(MRV_MI_SP_CR_OFFS_CNT_INIT_VALID_MASK)) != 0)) {
9297 +                               return CI_STATUS_OUTOFRANGE;
9298 +                       }
9299 +               }
9300 +       }
9301 +
9302 +       return CI_STATUS_SUCCESS;
9303 +}
9304 +
9305 +/*
9306 + * Configures the main picture path buffers of the MI.
9307 + */
9308 +int ci_isp_mif_set_main_buffer(const struct ci_isp_mi_path_conf
9309 +                              *isp_mi_path_conf,
9310 +                              enum ci_isp_conf_update_time update_time)
9311 +{
9312 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9313 +       int error = CI_STATUS_FAILURE;
9314 +
9315 +       error = ci_isp_mif_check_mi_path_conf(isp_mi_path_conf, true);
9316 +       if (error != CI_STATUS_SUCCESS)
9317 +               return error;
9318 +
9319 +       /* set register values */
9320 +       REG_SET_SLICE(mrv_reg->mi_mp_y_base_ad_init,
9321 +                     MRV_MI_MP_Y_BASE_AD_INIT,
9322 +                     (u32)(unsigned long)isp_mi_path_conf->ybuffer.pucbuffer);
9323 +       REG_SET_SLICE(mrv_reg->mi_mp_y_size_init, MRV_MI_MP_Y_SIZE_INIT,
9324 +                     isp_mi_path_conf->ybuffer.size);
9325 +       REG_SET_SLICE(mrv_reg->mi_mp_y_offs_cnt_init,
9326 +                     MRV_MI_MP_Y_OFFS_CNT_INIT,
9327 +                     isp_mi_path_conf->ybuffer.offs);
9328 +
9329 +       if (isp_mi_path_conf->cb_buffer.pucbuffer != 0) {
9330 +               REG_SET_SLICE(mrv_reg->mi_mp_cb_base_ad_init,
9331 +                             MRV_MI_MP_CB_BASE_AD_INIT,
9332 +                             (u32)(unsigned long) isp_mi_path_conf->cb_buffer.
9333 +                             pucbuffer);
9334 +               REG_SET_SLICE(mrv_reg->mi_mp_cb_size_init,
9335 +                             MRV_MI_MP_CB_SIZE_INIT,
9336 +                             isp_mi_path_conf->cb_buffer.size);
9337 +               REG_SET_SLICE(mrv_reg->mi_mp_cb_offs_cnt_init,
9338 +                             MRV_MI_MP_CB_OFFS_CNT_INIT,
9339 +                             isp_mi_path_conf->cb_buffer.offs);
9340 +       }
9341 +
9342 +       if (isp_mi_path_conf->cr_buffer.pucbuffer != 0) {
9343 +               REG_SET_SLICE(mrv_reg->mi_mp_cr_base_ad_init,
9344 +                             MRV_MI_MP_CR_BASE_AD_INIT,
9345 +                             (u32)(unsigned long) isp_mi_path_conf->cr_buffer.
9346 +                             pucbuffer);
9347 +               REG_SET_SLICE(mrv_reg->mi_mp_cr_size_init,
9348 +                             MRV_MI_MP_CR_SIZE_INIT,
9349 +                             isp_mi_path_conf->cr_buffer.size);
9350 +               REG_SET_SLICE(mrv_reg->mi_mp_cr_offs_cnt_init,
9351 +                             MRV_MI_MP_CR_OFFS_CNT_INIT,
9352 +                             isp_mi_path_conf->cr_buffer.offs);
9353 +       }
9354 +
9355 +       /*
9356 +        * update base and offset registers during next immediate or
9357 +        * automatic update request
9358 +        */
9359 +       REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE);
9360 +       REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE);
9361 +
9362 +       switch (update_time) {
9363 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
9364 +               /*
9365 +                * frame synchronous update of shadow registers,
9366 +                * update is done after the curr frame
9367 +                */
9368 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON);
9369 +               break;
9370 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
9371 +               /*
9372 +                * immediate update of shadow registers
9373 +                * (will disturb an ongoing frame processing)
9374 +                */
9375 +               REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9376 +               break;
9377 +       case CI_ISP_CFG_UPDATE_LATER:
9378 +               /* no update from within this function */
9379 +               break;
9380 +       default:
9381 +               break;
9382 +       }
9383 +
9384 +       return error;
9385 +}
9386 +
9387 +/*
9388 + * Configures the self picture path buffers of the MI.
9389 + *
9390 + */
9391 +int ci_isp_mif_set_self_buffer(const struct ci_isp_mi_path_conf
9392 +                               *isp_mi_path_conf,
9393 +                               enum ci_isp_conf_update_time update_time)
9394 +{
9395 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9396 +       int error = CI_STATUS_FAILURE;
9397 +
9398 +       error = ci_isp_mif_check_mi_path_conf(isp_mi_path_conf, false);
9399 +       if (error != CI_STATUS_SUCCESS)
9400 +               return error;
9401 +
9402 +       /* set register values */
9403 +       REG_SET_SLICE(mrv_reg->mi_sp_y_base_ad_init,
9404 +                     MRV_MI_SP_Y_BASE_AD_INIT,
9405 +                     (u32)(unsigned long)isp_mi_path_conf->ybuffer.pucbuffer);
9406 +       REG_SET_SLICE(mrv_reg->mi_sp_y_size_init, MRV_MI_SP_Y_SIZE_INIT,
9407 +                     isp_mi_path_conf->ybuffer.size);
9408 +       REG_SET_SLICE(mrv_reg->mi_sp_y_offs_cnt_init,
9409 +                     MRV_MI_SP_Y_OFFS_CNT_INIT,
9410 +                     isp_mi_path_conf->ybuffer.offs);
9411 +
9412 +       /*
9413 +        * llength is counted in pixels and this value could be stored
9414 +        * directly into the register
9415 +        */
9416 +       REG_SET_SLICE(mrv_reg->mi_sp_y_llength, MRV_MI_SP_Y_LLENGTH,
9417 +                     isp_mi_path_conf->llength);
9418 +
9419 +       if (isp_mi_path_conf->cb_buffer.pucbuffer) {
9420 +               REG_SET_SLICE(mrv_reg->mi_sp_cb_base_ad_init,
9421 +                             MRV_MI_SP_CB_BASE_AD_INIT,
9422 +                             (u32) (unsigned long)isp_mi_path_conf->cb_buffer.
9423 +                             pucbuffer);
9424 +               REG_SET_SLICE(mrv_reg->mi_sp_cb_size_init,
9425 +                             MRV_MI_SP_CB_SIZE_INIT,
9426 +                             isp_mi_path_conf->cb_buffer.size);
9427 +               REG_SET_SLICE(mrv_reg->mi_sp_cb_offs_cnt_init,
9428 +                             MRV_MI_SP_CB_OFFS_CNT_INIT,
9429 +                             isp_mi_path_conf->cb_buffer.offs);
9430 +       }
9431 +
9432 +       if (isp_mi_path_conf->cr_buffer.pucbuffer) {
9433 +               REG_SET_SLICE(mrv_reg->mi_sp_cr_base_ad_init,
9434 +                             MRV_MI_SP_CR_BASE_AD_INIT,
9435 +                             (u32) (unsigned long)isp_mi_path_conf->cr_buffer.
9436 +                             pucbuffer);
9437 +               REG_SET_SLICE(mrv_reg->mi_sp_cr_size_init,
9438 +                             MRV_MI_SP_CR_SIZE_INIT,
9439 +                             isp_mi_path_conf->cr_buffer.size);
9440 +               REG_SET_SLICE(mrv_reg->mi_sp_cr_offs_cnt_init,
9441 +                             MRV_MI_SP_CR_OFFS_CNT_INIT,
9442 +                             isp_mi_path_conf->cr_buffer.offs);
9443 +       }
9444 +
9445 +       if ((!isp_mi_path_conf->ypic_width)
9446 +           || (!isp_mi_path_conf->ypic_height)) {
9447 +               return CI_STATUS_FAILURE;
9448 +       }
9449 +
9450 +       REG_SET_SLICE(mrv_reg->mi_sp_y_pic_width, MRV_MI_SP_Y_PIC_WIDTH,
9451 +                     isp_mi_path_conf->ypic_width);
9452 +       REG_SET_SLICE(mrv_reg->mi_sp_y_pic_height, MRV_MI_SP_Y_PIC_HEIGHT,
9453 +                     isp_mi_path_conf->ypic_height);
9454 +       REG_SET_SLICE(mrv_reg->mi_sp_y_pic_size, MRV_MI_SP_Y_PIC_SIZE,
9455 +                     isp_mi_path_conf->ypic_height *
9456 +                     isp_mi_path_conf->llength);
9457 +
9458 +       /*
9459 +        * update base and offset registers during next immediate or
9460 +        * automatic update request
9461 +        */
9462 +       REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE);
9463 +       REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE);
9464 +
9465 +       switch (update_time) {
9466 +       case CI_ISP_CFG_UPDATE_FRAME_SYNC:
9467 +               REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD,
9468 +                             ON);
9469 +               break;
9470 +       case CI_ISP_CFG_UPDATE_IMMEDIATE:
9471 +               REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9472 +               break;
9473 +       case CI_ISP_CFG_UPDATE_LATER:
9474 +               break;
9475 +       default:
9476 +               break;
9477 +       }
9478 +
9479 +       return error;
9480 +}
9481 +
9482 +/*
9483 + * Configures the DMA path of the MI.
9484 + *
9485 + */
9486 +int ci_isp_mif_set_path_and_orientation(const struct ci_isp_mi_ctrl
9487 +                                       *mrv_mi_ctrl)
9488 +{
9489 +       struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9490 +       int error = CI_STATUS_OUTOFRANGE;
9491 +       u32 mi_ctrl = 0;
9492 +
9493 +       if (!mrv_mi_ctrl) {
9494 +               eprintk("mrv_mi_ctrl is NULL");
9495 +               return CI_STATUS_NULL_POINTER;
9496 +       }
9497 +
9498 +       if ((mrv_mi_ctrl->irq_offs_init &
9499 +            ~(MRV_MI_MP_Y_IRQ_OFFS_INIT_VALID_MASK)) != 0) {
9500 +               eprintk("bad mrv_mi_ctrl->irq_offs_init value");
9501 +               return error;
9502 +       }
9503 +
9504 +       REG_SET_SLICE(mrv_reg->mi_mp_y_irq_offs_init,
9505 +                     MRV_MI_MP_Y_IRQ_OFFS_INIT, mrv_mi_ctrl->irq_offs_init);
9506 +
9507 +       /* main picture path */
9508 +       switch (mrv_mi_ctrl->main_path) {
9509 +       case CI_ISP_PATH_OFF:
9510 +               REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, OFF);
9511 +               break;
9512 +       case CI_ISP_PATH_ON:
9513 +               REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, ON);
9514 +               break;
9515 +       case CI_ISP_PATH_JPE:
9516 +               REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, ON);
9517 +               break;
9518 +       case CI_ISP_PATH_RAW8:
9519 +               REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, ON);
9520 +               break;
9521 +       case CI_ISP_PATH_RAW816:
9522 +               REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, ON);
9523 +               REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
9524 +                             MRV_MI_MP_WRITE_FORMAT_INTERLEAVED);
9525 +               break;
9526 +       default:
9527 +               eprintk("bad mrv_mi_ctrl->main_path value");
9528 +               return error;
9529 +       }
9530 +
9531 +       /* self picture path output format */
9532 +       switch (mrv_mi_ctrl->mrv_mif_sp_out_form) {
9533 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_422:
9534 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9535 +                             MRV_MI_SP_OUTPUT_FORMAT_YUV422);
9536 +               break;
9537 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_444:
9538 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9539 +                             MRV_MI_SP_OUTPUT_FORMAT_YUV444);
9540 +               break;
9541 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_420:
9542 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9543 +                             MRV_MI_SP_OUTPUT_FORMAT_YUV420);
9544 +               break;
9545 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_400:
9546 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9547 +                             MRV_MI_SP_OUTPUT_FORMAT_YUV400);
9548 +               break;
9549 +       case CI_ISP_MIF_COL_FORMAT_RGB_565:
9550 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9551 +                             MRV_MI_SP_OUTPUT_FORMAT_RGB565);
9552 +               break;
9553 +       case CI_ISP_MIF_COL_FORMAT_RGB_888:
9554 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9555 +                             MRV_MI_SP_OUTPUT_FORMAT_RGB888);
9556 +               break;
9557 +       case CI_ISP_MIF_COL_FORMAT_RGB_666:
9558 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT,
9559 +                             MRV_MI_SP_OUTPUT_FORMAT_RGB666);
9560 +               break;
9561 +
9562 +       default:
9563 +               eprintk("bad mrv_mi_ctrl->mrv_mif_sp_out_form value");
9564 +               return error;
9565 +       }
9566 +
9567 +       /* self picture path input format */
9568 +       switch (mrv_mi_ctrl->mrv_mif_sp_in_form) {
9569 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_422:
9570 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT,
9571 +                             MRV_MI_SP_INPUT_FORMAT_YUV422);
9572 +               break;
9573 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_444:
9574 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT,
9575 +                             MRV_MI_SP_INPUT_FORMAT_YUV444);
9576 +               break;
9577 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_420:
9578 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT,
9579 +                             MRV_MI_SP_INPUT_FORMAT_YUV420);
9580 +               break;
9581 +       case CI_ISP_MIF_COL_FORMAT_YCBCR_400:
9582 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT,
9583 +                             MRV_MI_SP_INPUT_FORMAT_YUV400);
9584 +               break;
9585 +       case CI_ISP_MIF_COL_FORMAT_RGB_565:
9586 +       case CI_ISP_MIF_COL_FORMAT_RGB_666:
9587 +       case CI_ISP_MIF_COL_FORMAT_RGB_888:
9588 +       default:
9589 +               eprintk("bad mrv_mi_ctrl->mrv_mif_sp_in_form value");
9590 +               return error;
9591 +       }
9592 +
9593 +       error = CI_STATUS_SUCCESS;
9594 +
9595 +       /* self picture path write format */
9596 +       switch (mrv_mi_ctrl->mrv_mif_sp_pic_form) {
9597 +       case CI_ISP_MIF_PIC_FORM_PLANAR:
9598 +               REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
9599 +                             MRV_MI_SP_WRITE_FORMAT_PLANAR);
9600 +               break;
9601 +       case CI_ISP_MIF_PIC_FORM_SEMI_PLANAR:
9602 +               if ((mrv_mi_ctrl->mrv_mif_sp_out_form ==
9603 +                   CI_ISP_MIF_COL_FORMAT_YCBCR_422)
9604 +                   || (mrv_mi_ctrl->mrv_mif_sp_out_form ==
9605 +                   CI_ISP_MIF_COL_FORMAT_YCBCR_420)) {
9606 +                       REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
9607 +                                     MRV_MI_SP_WRITE_FORMAT_SEMIPLANAR);
9608 +               } else {
9609 +                       error = CI_STATUS_NOTSUPP;
9610 +               }
9611 +               break;
9612 +       case CI_ISP_MIF_PIC_FORM_INTERLEAVED:
9613 +               if (mrv_mi_ctrl->mrv_mif_sp_out_form ==
9614 +                   CI_ISP_MIF_COL_FORMAT_YCBCR_422) {
9615 +                       REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT,
9616 +                                     MRV_MI_SP_WRITE_FORMAT_INTERLEAVED);
9617 +               } else {
9618 +                       error = CI_STATUS_NOTSUPP;
9619 +               }
9620 +               break;
9621 +       default:
9622 +               error = CI_STATUS_OUTOFRANGE;
9623 +               break;
9624 +
9625 +       }
9626 +
9627 +       if (error != CI_STATUS_SUCCESS) {
9628 +               eprintk("bad mrv_mi_ctrl->mrv_mif_sp_pic_form value");
9629 +               return error;
9630 +       }
9631 +
9632 +       if (mrv_mi_ctrl->main_path == CI_ISP_PATH_ON) {
9633 +               /* for YCbCr mode only, permitted for raw mode */
9634 +               /* main picture path write format */
9635 +               switch (mrv_mi_ctrl->mrv_mif_mp_pic_form) {
9636 +               case CI_ISP_MIF_PIC_FORM_PLANAR:
9637 +                       REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
9638 +                                     MRV_MI_MP_WRITE_FORMAT_PLANAR);
9639 +                       break;
9640 +               case CI_ISP_MIF_PIC_FORM_SEMI_PLANAR:
9641 +                       REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
9642 +                                     MRV_MI_MP_WRITE_FORMAT_SEMIPLANAR);
9643 +                       break;
9644 +               case CI_ISP_MIF_PIC_FORM_INTERLEAVED:
9645 +                       REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT,
9646 +                                     MRV_MI_MP_WRITE_FORMAT_INTERLEAVED);
9647 +                       break;
9648 +               default:
9649 +                       error = CI_STATUS_OUTOFRANGE;
9650 +                       break;
9651 +               }
9652 +       }
9653 +
9654 +       if (error != CI_STATUS_SUCCESS) {
9655 +               eprintk("bad mrv_mi_ctrl->mrv_mif_mp_pic_form value");
9656 +               return error;
9657 +       }
9658 +
9659 +       /* burst length for chrominance for write port */
9660 +       /* setting burst mode to 16 bits
9661 +       switch (mrv_mi_ctrl->burst_length_chrom) {
9662 +       case CI_ISP_MIF_BURST_LENGTH_4:
9663 +               REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM,
9664 +                   MRV_MI_BURST_LEN_CHROM_4);
9665 +               break;
9666 +       case CI_ISP_MIF_BURST_LENGTH_8:
9667 +               REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM,
9668 +                   MRV_MI_BURST_LEN_CHROM_8);
9669 +               break;
9670 +       case CI_ISP_MIF_BURST_LENGTH_16:
9671 +               REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM,
9672 +                   MRV_MI_BURST_LEN_CHROM_16);
9673 +               break;
9674 +       default:
9675 +               error = CI_STATUS_OUTOFRANGE;
9676 +               break;
9677 +       }
9678 +       */
9679 +       REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM,
9680 +           MRV_MI_BURST_LEN_CHROM_16);
9681 +
9682 +       if (error != CI_STATUS_SUCCESS) {
9683 +               eprintk("bad mrv_mi_ctrl->burst_length_chrom value");
9684 +               return error;
9685 +       }
9686 +
9687 +       /* burst length for luminance for write port */
9688 +       /* setting burst mode to 16 bits
9689 +       switch (mrv_mi_ctrl->burst_length_lum) {
9690 +       case CI_ISP_MIF_BURST_LENGTH_4:
9691 +               REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM,
9692 +                   MRV_MI_BURST_LEN_LUM_4);
9693 +               break;
9694 +       case CI_ISP_MIF_BURST_LENGTH_8:
9695 +               REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM,
9696 +                   MRV_MI_BURST_LEN_LUM_8);
9697 +               break;
9698 +       case CI_ISP_MIF_BURST_LENGTH_16:
9699 +               REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM,
9700 +                   MRV_MI_BURST_LEN_LUM_16);
9701 +               break;
9702 +       default:
9703 +               error = CI_STATUS_OUTOFRANGE;
9704 +               break;
9705 +       }
9706 +       */
9707 +       REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM,
9708 +           MRV_MI_BURST_LEN_LUM_16);
9709 +
9710 +       if (error != CI_STATUS_SUCCESS) {
9711 +               eprintk("bad mrv_mi_ctrl->burst_length_lum value");
9712 +               return error;
9713 +       }
9714 +
9715 +       /* enable updating of the shadow registers for main and self picture
9716 +        * to their init values
9717 +        */
9718 +       switch (mrv_mi_ctrl->init_vals) {
9719 +       case CI_ISP_MIF_NO_INIT_VALS:
9720 +               break;
9721 +       case CI_ISP_MIF_INIT_OFFS:
9722 +               REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE);
9723 +               break;
9724 +       case CI_ISP_MIF_INIT_BASE:
9725 +               REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE);
9726 +               break;
9727 +       case CI_ISP_MIF_INIT_OFFSAndBase:
9728 +               REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE);
9729 +               REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE);
9730 +               break;
9731 +       default:
9732 +               error = CI_STATUS_OUTOFRANGE;
9733 +               break;
9734 +       }
9735 +
9736 +       if (error != CI_STATUS_SUCCESS) {
9737 +               eprintk("bad mrv_mi_ctrl->init_vals value");
9738 +               return error;
9739 +       }
9740 +
9741 +       /* enable change of byte order for write port */
9742 +       REG_SET_SLICE(mi_ctrl, MRV_MI_BYTE_SWAP,
9743 +           (mrv_mi_ctrl->byte_swap_enable) ? ON : OFF);
9744 +
9745 +       /* enable or disable the last pixel signalization */
9746 +       REG_SET_SLICE(mi_ctrl, MRV_MI_LAST_PIXEL_SIG_EN,
9747 +           (mrv_mi_ctrl->last_pixel_enable) ? ON : OFF);
9748 +
9749 +       /* now write settings into register */
9750 +       REG_WRITE(mrv_reg->mi_ctrl, mi_ctrl);
9751 +
9752 +       dprintk(2, "mi_ctrl = 0x%x", mi_ctrl);
9753 +
9754 +       /* self picture path operating mode */
9755 +       if ((mrv_mi_ctrl->self_path == CI_ISP_PATH_ON) ||
9756 +           (mrv_mi_ctrl->self_path == CI_ISP_PATH_OFF)) {
9757 +
9758 +               /* do not call if not supported */
9759 +
9760 +               /* support has been restricted to >= MI_V2 && <= MI_V3 in
9761 +                * ci_isp_mif_set_self_pic_orientation, so we do the same here
9762 +                */
9763 +
9764 +               error = ci_isp_mif_set_self_pic_orientation(
9765 +                                   mrv_mi_ctrl->mrv_mif_sp_mode,
9766 +                                   (int) (mrv_mi_ctrl->self_path
9767 +                                          == CI_ISP_PATH_ON));
9768 +       } else {
9769 +               eprintk("bad mrv_mi_ctrl->self_path value");
9770 +               error = CI_STATUS_OUTOFRANGE;
9771 +       }
9772 +
9773 +       REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9774 +
9775 +       return error;
9776 +}
9777 -- 
9778 1.6.0.6
9779