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
6 Patch-mainline: 2.6.35?
10 3469638 3469639 3469710 3469822 (high)
13 Changes from Beta 8.0:
15 3469056 3469058 (critical)
16 3469705 3469696 3469709 3469510 (medium)
18 Changes from Beta 7.0:
19 1. Fixed hsd sighting 3469681,3469682,3469683 (high)
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)
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
31 Changes from Beta 5.0:
32 Fixed a critical issue of camera driver not loading -- hsd 3469557
34 Main changes from Beta 4.0:
35 Fixed 4 HSD sightings: 3469392,3469099,3469470,3469500
37 Main changes from Beta 3.0:
38 Fixed 7 HSD sightings: 3469264,3469112,3469395,3469103,3469105,3469471,3469484
40 Main changes from Beta 2.0:
41 Fixed 6 HSD sightings: 3469047,3469315,3469317,3469101,3468409,3469391
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
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.
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.
60 1. camera driver depends on GPIO library and I2C driver.
64 2. camera driver depends on videobuf-core and videobuf-dma-contig.
67 3. enable multimedia support and video capture.
68 CONFIG_MEDIA_SUPPORT=y
70 CONFIG_VIDEO_V4L2_COMMON=y
73 4. camera drivers incluing ISP, 5630, 5630-motor, s5k4e1, s5k4e1-motor, 2650,
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
85 Signed-off-by: Zheng Ba <zheng.ba@intel.com>
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
111 diff --git a/drivers/media/video/mrstci/Kconfig b/drivers/media/video/mrstci/Kconfig
113 index 0000000..9ac7065
115 +++ b/drivers/media/video/mrstci/Kconfig
117 +menuconfig VIDEO_MRSTCI
118 + bool "Moorestown Langwell Camera Imaging Subsystem support"
119 + depends on VIDEO_V4L2
123 + Say Y here to enable selecting the Intel Moorestown Langwell Camera Imaging Subsystem for webcams.
125 +if VIDEO_MRSTCI && VIDEO_V4L2
127 +source "drivers/media/video/mrstci/mrstisp/Kconfig"
129 +source "drivers/media/video/mrstci/mrstov5630/Kconfig"
130 +source "drivers/media/video/mrstci/mrstov5630_motor/Kconfig"
132 +source "drivers/media/video/mrstci/mrsts5k4e1/Kconfig"
133 +source "drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig"
135 +source "drivers/media/video/mrstci/mrstflash/Kconfig"
137 +source "drivers/media/video/mrstci/mrstov2650/Kconfig"
139 +source "drivers/media/video/mrstci/mrstov9665/Kconfig"
141 +endif # VIDEO_MRSTCI
143 diff --git a/drivers/media/video/mrstci/Makefile b/drivers/media/video/mrstci/Makefile
145 index 0000000..9d3449e
147 +++ b/drivers/media/video/mrstci/Makefile
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
159 index 0000000..8e58a87
161 +++ b/drivers/media/video/mrstci/mrstisp/Kconfig
163 +config VIDEO_MRST_ISP
164 + tristate "Moorstown Marvin - ISP Driver"
165 + depends on VIDEO_V4L2
166 + select VIDEOBUF_DMA_CONTIG
169 + Say Y here if you want support for cameras based on the Intel Moorestown platform.
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
175 index 0000000..30f4e62
177 +++ b/drivers/media/video/mrstci/mrstisp/Makefile
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
183 +obj-$(CONFIG_VIDEO_MRST_ISP) += mrstisp.o
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
188 index 0000000..85cc482
190 +++ b/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c
193 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
195 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
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.
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.
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
212 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
215 +#include "mrstisp_stdinc.h"
218 +static u32 copy_sensor_config_from_user(struct ci_sensor_config *des,
219 + struct ci_sensor_config *src)
222 + ret = copy_from_user((void *)des, (const void *)src,
223 + sizeof(struct ci_sensor_config));
229 +static u32 copy_sensor_caps_from_user(struct ci_sensor_caps *des,
230 + struct ci_sensor_caps *src)
233 + ret = copy_from_user((void *)des, (const void *)src,
234 + sizeof(struct ci_sensor_caps));
240 +static u32 copy_isp_config_from_user(struct ci_isp_config *des,
241 + struct ci_isp_config *src)
244 + ret = copy_from_user((void *)des, (const void *)src,
245 + sizeof(struct ci_isp_config));
247 + eprintk("returning %d", ret);
254 +static void print_bls_cfg(struct ci_isp_config *isp_cfg)
256 + struct ci_isp_bls_config *bls_cfg = &isp_cfg->bls_cfg;
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);
282 +static int mrst_isp_set_cfg(struct file *file, void *priv,
283 + struct ci_pl_system_config *arg)
285 + struct video_device *dev = video_devdata(file);
286 + struct mrst_isp_device *isp = video_get_drvdata(dev);
288 + WARN_ON(priv != file->private_data);
293 + eprintk("NULL pointer of arg");
296 + mutex_lock(&isp->mutex);
299 + if (arg->isi_config != NULL) {
300 + dprintk(2, "sync isi cfg");
301 + copy_sensor_config_from_user(isp->sys_conf.isi_config,
304 + eprintk("NULL arg->isi_config");
305 + ret = CI_STATUS_NULL_POINTER;
309 + if (arg->isi_caps != NULL) {
310 + dprintk(2, "sync isi caps");
311 + copy_sensor_caps_from_user(isp->sys_conf.isi_caps,
314 + eprintk("NULL arg->isi_caps");
315 + ret = CI_STATUS_NULL_POINTER;
320 + memcpy(&isp->sys_conf.isp_cfg, &arg->isp_cfg,
321 + sizeof(struct ci_isp_config));
323 + print_bls_cfg(&isp->sys_conf.isp_cfg);
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);
329 + isp->sys_conf.isp_hal_enable = 1;
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)
339 + struct video_device *dev = video_devdata(file);
340 + struct mrst_isp_device *isp = video_get_drvdata(dev);
342 + WARN_ON(priv != file->private_data);
346 + mutex_lock(&isp->mutex);
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);
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;
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);
365 + mutex_unlock(&isp->mutex);
371 +static int mrst_isp_set_jpg_enc_ratio(struct file *file, void *priv, int *arg)
373 + struct video_device *dev = video_devdata(file);
374 + struct mrst_isp_device *isp = video_get_drvdata(dev);
376 + WARN_ON(priv != file->private_data);
380 + dprintk(2, "set jpg compression ratio is %d", *arg);
382 + mutex_lock(&isp->mutex);
383 + isp->sys_conf.isp_cfg.jpeg_enc_ratio = *arg;
384 + mutex_unlock(&isp->mutex);
390 +int mrst_isp_get_isp_mem_info(struct file *file, void *priv,
391 + struct ci_isp_mem_info *arg)
394 + struct video_device *dev = video_devdata(file);
395 + struct mrst_isp_device *isp = video_get_drvdata(dev);
397 + WARN_ON(priv != file->private_data);
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);
412 +int mrst_isp_create_jpg_review_frame(struct file *file, void *priv,
413 + struct v4l2_jpg_review_buffer *arg)
415 + struct video_device *dev = video_devdata(file);
416 + struct mrst_isp_device *isp = video_get_drvdata(dev);
418 + u32 width = arg->width;
419 + u32 height = arg->height;
420 + u32 pix_fmt = arg->pix_fmt;
421 + u32 jpg_frame = arg->jpg_frame;
423 + static struct v4l2_jpg_review_buffer *jpg_review;
425 + jpg_review = &isp->sys_conf.jpg_review;
427 + WARN_ON(priv != file->private_data);
431 + if (width > 640 || height > 480 || width < 32 || height < 16) {
432 + eprintk("unsupported resolution: %d * %d", width, height);
436 + if (jpg_frame >= isp->num_frames) {
437 + eprintk("error jpeg frame id");
441 + jpg_review->width = width;
442 + jpg_review->height = height;
443 + jpg_review->pix_fmt = pix_fmt;
444 + jpg_review->jpg_frame = jpg_frame;
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;
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;
458 + eprintk("unsupported pix_fmt: %d", arg->pix_fmt);
462 + jpg_review->offset = isp->mb1_size - 640*480*2;
464 + isp->sys_conf.jpg_review_enable = 1; /* enable jpg review flag */
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;
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);
480 +/* isp private ioctl for libci */
481 +long mrst_isp_vidioc_default(struct file *file, void *fh,
482 + int cmd, void *arg)
484 + void *priv = file->private_data;
489 + case VIDIOC_GET_ISP_MEM_INFO:
490 + return mrst_isp_get_isp_mem_info(file, priv,
491 + (struct ci_isp_mem_info *)arg);
493 + case VIDIOC_SET_SYS_CFG:
494 + return mrst_isp_set_cfg(file, priv,
495 + (struct ci_pl_system_config *)arg);
497 + case VIDIOC_SET_JPG_ENC_RATIO:
498 + return mrst_isp_set_jpg_enc_ratio(file, priv, (int *)arg);
500 + case ISP_IOCTL_GET_FRAME_INFO:
501 + return mrst_isp_get_frame_info(file, priv,
502 + (struct ci_frame_info *)arg);
504 + case VIDIOC_CREATE_JPG_REVIEW_BUF:
505 + return mrst_isp_create_jpg_review_frame(file, priv,
506 + (struct v4l2_jpg_review_buffer *)arg);
508 + v4l_print_ioctl("lnw_isp", cmd);
509 + dprintk(2, "VIDIOC_SET_SYS_CFG = %x", VIDIOC_SET_SYS_CFG);
516 diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c b/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c
518 index 0000000..dd892fb
520 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c
523 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
525 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
527 + * Copyright (c) Silicon Image 2008 www.siliconimage.com
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.
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.
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
544 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
547 +#include "mrstisp_stdinc.h"
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)
552 +#define SCALER_COFFS_COSITED 0x400
553 +#define FIXEDPOINT_ONE 0x1000
555 +/* limitations of main and self scaler */
556 +#define MAIN_SCALER_WIDTH_MAX 2600
558 +#define SELF_SCALER_WIDTH_MAX 640
559 +#define SCALER_MIN 16
561 +#define SELF_UPSCALE_FACTOR_MAX 5
563 +#define MAIN_UPSCALE_FACTOR_MAX 5
566 + * upscale lookup table for smooth edges
567 + * (linear interpolation between pixels)
571 +static const struct ci_isp_rsz_lut isp_rsz_lut_smooth_lin = {
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
585 + * upscale lookup table for sharp edges
586 + * (no interpolation, just duplicate pixels)
590 +static const struct ci_isp_rsz_lut isp_rsz_lut_sharp = {
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
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;
609 +/* static storage to remember last applied virtual ISP window settings */
610 +static struct ci_isp_virtual_isp_wnds last_isp_wnds;
613 + * Calculates the value to program into the struct ci_isp_scale or
614 + * tsMrvSScale structures to scale from in pixels to out pixels.
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).
620 +static u32 ci_get_scale_reg(u16 in, u16 out)
624 + return (u32) (((((u32) out - 1) * RSZ_SCALER_BYPASS) /
625 + (u32) (in - 1)) + 1);
626 + } else if (in < out) {
628 + return (u32) (((((u32) in - 1) * RSZ_SCALER_BYPASS) /
629 + (u32) (out - 1)) | (u32) RSZ_UPSCALE_ENABLE);
633 + return RSZ_SCALER_BYPASS;
637 + * Calculates the values of the ci_isp_scale structure for the
638 + * given input size and data path descriptor.
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)
644 + u32 scaler_output_format;
646 + u32 scaler_input_format;
650 + u16 chroma_out_wcr;
651 + u16 chroma_out_wcb;
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);
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);
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;
672 + /* ISP originated data */
673 + scaler_input_format = CI_ISP_DPD_DMA_IN_422;
677 + dprintk(1, "scaler_input_format is 0x%x", scaler_input_format);
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;
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;
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;
701 + case CI_ISP_DPD_DMA_IN_444:
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;
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;
716 + case CI_ISP_DPD_CSS_H4:
717 + chroma_out_wcb /= 4;
718 + chroma_out_wcr /= 4;
720 + case CI_ISP_DPD_CSS_HUP2:
721 + chroma_out_wcb *= 2;
722 + chroma_out_wcr *= 2;
724 + case CI_ISP_DPD_CSS_HUP4:
725 + chroma_out_wcb *= 4;
726 + chroma_out_wcr *= 4;
729 + /*leave chroma_out_w untouched*/
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;
737 + switch (path->flags & CI_ISP_DPD_CSS_V_MASK) {
738 + case CI_ISP_DPD_CSS_V2:
741 + case CI_ISP_DPD_CSS_V4:
744 + case CI_ISP_DPD_CSS_VUP2:
747 + case CI_ISP_DPD_CSS_VUP4:
751 + /* leave chroma_out_h untouched */
755 + scale->scale_vc = ci_get_scale_reg(chroma_in_h, chroma_out_h);
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;
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;
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;
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;
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;
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;
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;
844 + /* DMA input format not supported */
849 + return scaler_output_format;
853 + * Returns the address of up-scaling lookup table to use for
854 + * the given data path flags.
856 +static const struct ci_isp_rsz_lut *ci_get_rsz_lut(u32 flags)
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;
864 + ret_val = &isp_rsz_lut_smooth_lin;
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.
876 + * Following fields are being filled in:
877 + * scale_main: [all fields]
878 + * mrv_mi_ctrl: mrv_mif_mp_pic_form main_path
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)
887 + WARN_ON(!(source != NULL));
888 + WARN_ON(!(scale_main != NULL));
889 + WARN_ON(!(mrv_mi_ctrl != NULL));
891 + /* assume datapath deactivation if no selfpath pointer is given) */
893 + main_flag = main->flags;
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;
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;
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;
916 + case CI_ISP_DPD_MODE_ISPRAW:
917 + mrv_mi_ctrl->main_path = CI_ISP_PATH_RAW8;
919 + case CI_ISP_DPD_MODE_ISPRAW_16B:
920 + mrv_mi_ctrl->main_path = CI_ISP_PATH_RAW816;
923 + eprintk("unsupported mode for main path");
924 + return CI_STATUS_NOTSUPP;
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;
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;
937 + (CI_ISP_DPD_LUMA_HSHIFT | CI_ISP_DPD_LUMA_VSHIFT)) {
938 + eprintk("main path needs rezizer");
939 + return CI_STATUS_NOTSUPP;
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;
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)
952 + (((u32) (source->out_h) *
953 + MAIN_UPSCALE_FACTOR_MAX) <
955 + eprintk("main upscaling exceeded");
956 + return CI_STATUS_NOTSUPP;
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;
966 + WARN_ON(main == NULL);
969 + if (source->out_w & 0x01) {
970 + eprintk("input width must be even!");
971 + return CI_STATUS_NOTSUPP;
974 + /* calculate scale factors. */
975 + (void)ci_calc_scale_factors(source, main, scale_main,
976 + MARVIN_FEATURE_MSCALE_FACTORCALC);
979 + mrv_mi_ctrl->main_path = CI_ISP_PATH_OFF;
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;
991 + case CI_ISP_DPD_YUV_NV12:
992 + mrv_mi_ctrl->mrv_mif_mp_pic_form =
993 + CI_ISP_MIF_PIC_FORM_SEMI_PLANAR;
995 + case CI_ISP_DPD_YUV_YUYV:
996 + mrv_mi_ctrl->mrv_mif_mp_pic_form =
997 + CI_ISP_MIF_PIC_FORM_INTERLEAVED;
1000 + mrv_mi_ctrl->mrv_mif_mp_pic_form =
1001 + CI_ISP_MIF_PIC_FORM_PLANAR;
1005 + return CI_STATUS_SUCCESS;
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.
1014 + * Following fields are being filled in:
1018 + * mrv_mif_sp_out_form
1019 + * mrv_mif_sp_in_form
1020 + * mrv_mif_sp_pic_form
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)
1029 + u32 scaler_out_col_format;
1032 + WARN_ON(!(source != NULL));
1033 + WARN_ON(!(scale_flag != NULL));
1034 + WARN_ON(!(mrv_mi_ctrl != NULL));
1036 + /* assume datapath deactivation if no selfpath pointer is given) */
1038 + self_flag = self->flags;
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;
1050 + if (self_flag & CI_ISP_DPD_ENABLE) {
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;
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;
1064 + eprintk("unsupported mode for self path");
1065 + return CI_STATUS_NOTSUPP;
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;
1074 + (CI_ISP_DPD_LUMA_HSHIFT | CI_ISP_DPD_LUMA_VSHIFT)) {
1075 + eprintk("n self path needs rezizer");
1076 + return CI_STATUS_NOTSUPP;
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;
1086 + WARN_ON(self == NULL);
1089 + /* changed to avoid LINT warnings (Warning 613) */
1090 + if (self != NULL) {
1091 + /* upscaling only to factor
1092 + * SELF_UPSCALE_FACTOR_MAX possible
1094 + if ((((u32) (source->out_w) *
1095 + SELF_UPSCALE_FACTOR_MAX) <
1098 + (((u32) (source->out_h) *
1099 + SELF_UPSCALE_FACTOR_MAX) <
1101 + eprintk("apability exceeded");
1102 + return CI_STATUS_NOTSUPP;
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;
1112 + WARN_ON(self == NULL);
1114 + /* Remember that the input picture width should be
1115 + * even if the scaler is used */
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;
1124 + /* calculate scale factors. */
1125 + scaler_out_col_format =
1126 + ci_calc_scale_factors(source, self, scale_flag,
1127 + MARVIN_FEATURE_SSCALE_FACTORCALC);
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;
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;
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;
1145 + /* no break, does not seem to be supported by HW */
1146 + case CI_ISP_DPD_DMA_IN_411:
1148 + eprintk("input color format not supported");
1149 + return CI_STATUS_NOTSUPP;
1152 + /* figure out the output format setting */
1153 + dprintk(2, "step2, self_flag is 0x%x", self_flag);
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;
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;
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;
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;
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;
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;
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;
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;
1206 + eprintk("output color format not supported");
1207 + return CI_STATUS_NOTSUPP;
1210 + /* picture flipping / rotation */
1211 + dprintk(2, "step3");
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;
1220 + case (CI_ISP_DPD_V_FLIP):
1221 + mrv_mi_ctrl->mrv_mif_sp_mode =
1222 + CI_ISP_MIF_SP_VERTICAL_FLIP;
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;
1228 + case (CI_ISP_DPD_90DEG_CCW):
1229 + mrv_mi_ctrl->mrv_mif_sp_mode =
1230 + CI_ISP_MIF_SP_ROTATION_090_DEG;
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;
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;
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;
1246 + mrv_mi_ctrl->mrv_mif_sp_mode = CI_ISP_MIF_SP_ORIGINAL;
1251 + mrv_mi_ctrl->self_path = CI_ISP_PATH_OFF;
1254 + dprintk(2, "step4");
1255 + /*mrv_mi_ctrl->mrv_mif_sp_pic_form = CI_ISP_MIF_PIC_FORM_PLANAR;*/
1257 + return CI_STATUS_SUCCESS;
1261 + * Translates the given memory interface configuration struct
1262 + * into appropriate values to program the data path multiplexers.
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)
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;
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;
1284 + *peYcsChnMode = CI_ISP_YCS_MV;
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;
1292 + *peYcsChnMode = CI_ISP_YCS_MV;
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;
1300 + *peYcsChnMode = CI_ISP_YCS_OFF;
1304 + return CI_STATUS_NOTSUPP;
1307 + return CI_STATUS_SUCCESS;
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
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.
1325 +static u32 ci_get_isp_wnd_style(enum ci_isp_path isp_path)
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
1335 + res = ISPWND_APPLY_OUTFORM | ISPWND_APPLY_ISCONF;
1337 + res = ISPWND_COMBINE_WNDS | ISPWND_APPLY_OUTFORM;
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.
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)
1352 + struct ci_isp_window wnd_out_form;
1353 + struct ci_isp_is_config is_conf;
1354 + enum ci_isp_path isp_path;
1357 + memset(&wnd_out_form, 0, sizeof(wnd_out_form));
1358 + memset(&is_conf, 0, sizeof(is_conf));
1361 + * figure out the path through the ISP to process the data from the
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;
1371 + * get the recommended way to configure output formatter and/or
1372 + * image stabilization
1374 + wnd_style = ci_get_isp_wnd_style(isp_path);
1375 + if (wnd_style & ISPWND_NO_CROPPING) {
1377 + * cropping not possible -> make sure that it is *not*
1378 + * supposed to be used
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;
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;
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
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;
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) {
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
1424 + is_conf.mrv_is_window.hoffs = 0;
1425 + is_conf.mrv_is_window.voffs = 0;
1429 + * do not combine windows --> blacklines done with output
1430 + * formatter, zoom/cropping done with image stabilization
1432 + wnd_out_form = *wnd_blackline;
1433 + is_conf.mrv_is_window = *wnd_zoom_crop;
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);
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");
1449 + /* success - remember our virtual settings */
1450 + last_isp_wnds.wnd_blacklines = *wnd_blackline;
1451 + last_isp_wnds.wnd_zoom_crop = *wnd_zoom_crop;
1453 + return CI_STATUS_SUCCESS;
1456 +/* sets extended YCbCr mode */
1457 +static int ci_ext_ycb_cr_mode(const struct ci_isp_datapath_desc *path)
1461 + WARN_ON(!(path != NULL));
1463 + /* assume datapath deactivation if no selfpath pointer is given) */
1465 + main_flag = path->flags;
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();
1475 + return CI_STATUS_SUCCESS;
1479 + * Configures main and self data pathes and scaler for data coming from the ISP.
1481 + * Following MARVIN subsystems are programmed:
1482 + * - ISP output formatter
1483 + * - Image stabilization module
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
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
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)
1504 + * copy of flags for main and self path to simplify access (no
1505 + * pointer de-reference)
1509 + /* resolution from sensor configuration */
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;
1524 + const struct ci_isp_datapath_desc *target = NULL;
1526 + /* assume dapapath deactivation for not provided descriptors */
1530 + main_flag = main->flags; /* 0x012 */
1533 + self_flag = self->flags; /* 0x10015 */
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));
1544 + * ISP Windowing - fill in wnd_out_form, apply_out_form, is_conf and
1549 + * by default, size of both blackline and zoom/crop window
1550 + * is what the camera delivers.
1553 + /* (no cropping, no offset) */
1554 + wnd_blackline.hsize = isiX;
1555 + wnd_blackline.vsize = isiY;
1556 + wnd_zoom_crop = wnd_blackline;
1559 + * check if we have to crop because of aspect ratio
1560 + * preservement of an
1563 + /* output channel */
1564 + if ((main_flag & CI_ISP_DPD_ENABLE) &&
1565 + (main_flag & CI_ISP_DPD_KEEPRATIO)) {
1568 + if ((self_flag & CI_ISP_DPD_ENABLE) &&
1569 + (self_flag & CI_ISP_DPD_KEEPRATIO)) {
1571 + eprintk("only allowed for one path");
1572 + return CI_STATUS_NOTSUPP;
1577 + /* if so, calculate the cropping */
1579 + u32 aspect_cam = (0x1000 * ((u32) isiX)) / isiY;
1580 + u32 aspect_target = (0x1000 * ((u32) (target->out_w))) /
1582 + if (aspect_cam < aspect_target) {
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)
1590 + wnd_zoom_crop.vsize = (u16) (((u32) isiX *
1591 + (u32) (target->out_h)) / target->out_w);
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);
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.
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));
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)
1621 + wnd_zoom_crop.hsize &= ~0x01;
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)
1627 + wnd_zoom_crop.hoffs = (isiX - wnd_zoom_crop.hsize) / 2;
1628 + wnd_zoom_crop.voffs = (isiY - wnd_zoom_crop.vsize) / 2;
1630 + * If the image sensor delivers blacklines, we cut them
1631 + * away with moving wnd_blackline window by the given
1634 + switch (isi_config->bls) {
1635 + /* no black lines */
1636 + case SENSOR_BLS_OFF:
1638 + /* two black lines at frame start */
1639 + case SENSOR_BLS_TWO_LINES:
1640 + wnd_blackline.voffs += 2;
1642 + /* two black lines at frame start and two at the end */
1643 + case SENSOR_BLS_FOUR_LINES:
1644 + wnd_blackline.voffs += 2;
1647 + eprintk("config");
1648 + return CI_STATUS_NOTSUPP;
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.
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;
1669 + wnd_blackline.voffs = 0;
1670 + wnd_zoom_crop.voffs = 0;
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;
1678 + /*to use crop set crop_flag first*/
1680 + wnd_zoom_crop.hsize = main->out_w;
1681 + wnd_zoom_crop.vsize = main->out_h;
1684 + dprintk(1, "source.out_w %d, source.out_h %d",
1685 + source.out_w, source.out_h);
1687 + dprintk(1, "main.out_w %d, main.out_h %d",
1688 + main->out_w, main->out_h);
1690 + dprintk(1, "self.out_w %d, self.out_h %d",
1691 + self->out_w, self->out_h);
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.
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,
1711 + if (res != CI_STATUS_SUCCESS)
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 */
1724 + eprintk("data coming from the ISP");
1725 + return CI_STATUS_NOTSUPP;
1729 + /* SELF path - fill in self_path & scale_flag */
1730 + /* basic selfpath settings */
1731 + res = ci_calc_self_path_settings(&source, self, &scale_flag,
1733 + if (res != CI_STATUS_SUCCESS)
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;
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;
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 */
1750 + eprintk("data coming from the ISP");
1751 + return CI_STATUS_NOTSUPP;
1755 + /* Datapath multiplexers */
1756 + res = ci_calc_dp_mux_settings(&mrv_mi_ctrl, &chn_mode, &dp_switch);
1757 + if (res != CI_STATUS_SUCCESS)
1760 + /* hardcoded global settings of the memory interface */
1761 + mrv_mi_ctrl.byte_swap_enable = false;
1763 + mrv_mi_ctrl.init_vals = CI_ISP_MIF_INIT_OFFSAndBase;
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.
1771 + /*to use crop set crop_flag first*/
1773 + wnd_blackline.hsize = main->out_w;
1774 + wnd_blackline.vsize = main->out_h;
1777 + res = ci_set_isp_windows(isi_config, &wnd_blackline,
1779 + if (res != CI_STATUS_SUCCESS) {
1780 + eprintk("failed to set ISP window configuration");
1783 + res = ci_isp_set_data_path(chn_mode, dp_switch);
1784 + if (res != CI_STATUS_SUCCESS)
1787 + res = ci_isp_set_mipi_smia(isi_config->mode);
1788 + if (res != CI_STATUS_SUCCESS)
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));
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));
1801 + ci_isp_set_dma_read_mode(CI_ISP_DMA_RD_OFF,
1802 + CI_ISP_CFG_UPDATE_IMMEDIATE);
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");
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);
1814 + (void)ci_isp_set_yc_mode();
1816 + if (res != CI_STATUS_SUCCESS) {
1817 + eprintk("failed to set ISP YCbCr extended mode");
1821 + return CI_STATUS_SUCCESS;
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
1827 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c
1830 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
1832 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
1834 + * Copyright (c) Silicon Image 2008 www.siliconimage.com
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.
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.
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.
1851 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
1854 +#include "mrstisp_stdinc.h"
1856 +static unsigned long jiffies_start;
1858 +void mrst_timer_start(void)
1860 + jiffies_start = jiffies;
1863 +void mrst_timer_stop(void)
1865 + jiffies_start = 0;
1868 +unsigned long mrst_get_micro_sec(void)
1870 + unsigned long time_diff = 0;
1872 + time_diff = jiffies - jiffies_start;
1874 + return jiffies_to_msecs(time_diff);
1878 + * Returns the ISP hardware ID.
1880 +static u32 ci_isp_get_ci_isp_id(void)
1882 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1885 + result = REG_GET_SLICE(mrv_reg->vi_id, MRV_REV_ID);
1891 + * Gets the hardware ID and compares it with the expected one.
1893 +static int ci_isp_verify_chip_id(void)
1895 + u32 mrv_id = ci_isp_get_ci_isp_id();
1896 + dprintk(1, "HW-Id: 0x%08X", mrv_id);
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;
1903 + return CI_STATUS_SUCCESS;
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.
1914 +void ci_isp_init(void)
1916 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1918 + /* verify ID, but no consequences if it doesn't match */
1919 + (void)ci_isp_verify_chip_id();
1921 + /* enable main clock */
1922 + REG_SET_SLICE(mrv_reg->vi_ccl, MRV_VI_CCLFDIS, MRV_VI_CCLFDIS_ENABLE);
1925 + * enable all clocks to make sure that all submodules will be able to
1926 + * perform the reset correctly
1928 + REG_SET_SLICE(mrv_reg->vi_iccl, MRV_VI_ALL_CLK_ENABLE, ENABLE);
1931 + * Reset of the entire MARVIN triggered by software. The minimum time
1932 + * permitted by mdelay ensures enough delay.
1935 + /* The reset bit will be cleared by the reset itself. */
1938 + * The default value of the clock registers is all clocks on. So we
1939 + * don't have to enable the clocks again afterwards.
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);
1947 +void ci_isp_off(void)
1949 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1951 + /* enable main clock */
1952 + REG_SET_SLICE(mrv_reg->vi_ccl, MRV_VI_CCLFDIS,
1953 + MRV_VI_CCLFDIS_DISABLE);
1956 + * enable all clocks to make sure that all submodules will be able to
1957 + * perform the reset correctly
1959 + REG_SET_SLICE(mrv_reg->vi_iccl, MRV_VI_ALL_CLK_ENABLE, DISABLE);
1963 + * Returns the mask for the frame end interrupts, which are
1966 +u32 ci_isp_get_frame_end_irq_mask_isp(void)
1968 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
1970 + switch (REG_GET_SLICE(mrv_reg->vi_dpcl, MRV_VI_DMA_SWITCH)) {
1972 + * 2: path to image effects block (i.e. replacement for data coming
1975 + case MRV_VI_DMA_SWITCH_IE:
1976 + /* datapath is used by DMA */
1979 + * 0: direct path to self path mux
1981 + case MRV_VI_DMA_SWITCH_SELF:
1983 + * 1: path to superimpose block
1985 + case MRV_VI_DMA_SWITCH_SI:
1987 + * 3: direct path to JPEG encoder (R2B-buffer-less encodein mode)
1989 + case MRV_VI_DMA_SWITCH_JPG:
1991 + /* main and/or self path depends on the YC-splitter setting */
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;
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.
2017 +void ci_isp_start(u16 number_of_frames,
2018 + enum ci_isp_conf_update_time update_time)
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();
2024 + /* max. 10 bits allowed */
2025 + WARN_ON(!(number_of_frames <= MRV_ISP_ACQ_NR_FRAMES_MAX));
2027 + REG_SET_SLICE(mrv_reg->isp_acq_nr_frames, MRV_ISP_ACQ_NR_FRAMES,
2028 + number_of_frames);
2030 + /* clear frame end interrupt */
2031 + REG_WRITE(mrv_reg->mi_icr, eof_irq_mask);
2033 + /* Enable ISP input Acquisition and output formatter. */
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.
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
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.
2059 + /* If the output formatter does not start check the following:
2062 + * mode in register isp_ctrl
2063 + * sampling window of input acquisition <= picture size of image
2065 + * output formatter window <= sampling window of input
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.
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);
2079 + case CI_ISP_CFG_UPDATE_IMMEDIATE:
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
2086 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CFG_UPD, ENABLE);
2088 + case CI_ISP_CFG_UPDATE_LATER:
2089 + /* no update from within this function
2090 + * but enable ISP and Input */
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);
2100 + dprintk(3, "ISP_CTRL = 0x%08X", mrv_reg->isp_ctrl);
2104 + * Clear frame end interrupt to allow waiting in
2105 + * ci_isp_wait_for_frame_end(). Disable output formatter (frame
2108 +void ci_isp_stop(enum ci_isp_conf_update_time update_time)
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();
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);
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);
2123 + case CI_ISP_CFG_UPDATE_IMMEDIATE:
2124 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CFG_UPD, ENABLE);
2126 + case CI_ISP_CFG_UPDATE_LATER:
2132 + REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl);
2136 + * Changes the data path settings.
2138 +int ci_isp_set_data_path(enum ci_isp_ycs_chn_mode ycs_chn_mode,
2139 + enum ci_isp_dp_switch dp_switch)
2141 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2142 + u32 vi_dpcl = REG_READ(mrv_reg->vi_dpcl);
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;
2151 + case CI_ISP_YCS_Y:
2152 + vi_chan_mode = MRV_VI_CHAN_MODE_Y;
2154 + case CI_ISP_YCS_MVRaw:
2155 + vi_chan_mode = MRV_VI_CHAN_MODE_MP_RAW;
2157 + case CI_ISP_YCS_MV:
2158 + vi_chan_mode = MRV_VI_CHAN_MODE_MP;
2160 + case CI_ISP_YCS_SP:
2161 + vi_chan_mode = MRV_VI_CHAN_MODE_SP;
2163 + case CI_ISP_YCS_MV_SP:
2164 + vi_chan_mode = MRV_VI_CHAN_MODE_MP_SP;
2167 + eprintk("unknown value for ycs_chn_mode");
2168 + return CI_STATUS_NOTSUPP;
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;
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;
2181 + case CI_ISP_DP_JPEG:
2182 + vi_mp_mux = MRV_VI_MP_MUX_JPEG;
2184 + case CI_ISP_DP_MV:
2185 + vi_mp_mux = MRV_VI_MP_MUX_MP;
2188 + eprintk("unknown value for dp_switch");
2189 + return CI_STATUS_NOTSUPP;
2192 + if (vi_mp_mux & ~MRV_VI_MP_MUX_MASK) {
2193 + eprintk("dp_switch value not supported");
2194 + return CI_STATUS_NOTSUPP;
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);
2202 + return CI_STATUS_SUCCESS;
2206 + * Changes the data path settings to SMIA or MIPI.
2208 +int ci_isp_set_mipi_smia(u32 mode)
2210 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2213 + /* get desired setting for if_select bits */
2215 + case SENSOR_MODE_SMIA:
2216 + if_select = MRV_IF_SELECT_SMIA;
2218 + case SENSOR_MODE_MIPI:
2219 + if_select = MRV_IF_SELECT_MIPI;
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;
2231 + eprintk("unknown value for mode");
2232 + return CI_STATUS_NOTSUPP;
2235 + /* program settings into MARVIN vi_dpcl register */
2236 + REG_SET_SLICE(mrv_reg->vi_dpcl, MRV_IF_SELECT, if_select);
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? */
2243 + return CI_STATUS_SUCCESS;
2247 + * Waits until the specified bits becomes signaled in the mi_ris
2250 +static int ci_isp_wait_for_mi(struct mrst_isp_device *intel, u32 bit_mask)
2252 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2255 + INIT_COMPLETION(intel->mi_complete);
2256 + ret = wait_for_completion_interruptible_timeout(&intel->mi_complete,
2259 + eprintk("time out in wait for mi");
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.
2271 + * Note that only modules with clock enabled will be
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);
2278 + * isp config update, neccessary to update v/h_size
2279 + * into shadow registers
2281 + REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_CFG_UPD, ON);
2282 + return CI_STATUS_FAILURE;
2284 + return CI_STATUS_SUCCESS;
2287 + static int err_frame_cnt;
2288 + mrst_timer_start();
2290 + * Wait for the curr BitMask. If the BitMask is zero, then it's no
2293 + while ((mrv_reg->mi_ris & bit_mask) != bit_mask) {
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)){
2299 + dprintk(1, "irq = 0x%x, err rumber = %d", irq,
2302 + if (mrst_get_micro_sec() > 1000) {
2304 + * Note: Don't use REG_READ because content of
2305 + * registers would be already printed here.
2307 + dprintk(1, "time out");
2308 + mrst_timer_stop();
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.
2320 + * Note that only modules with clock enabled will be
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);
2330 + * isp config update, neccessary to update v/h_size
2331 + * into shadow registers
2333 + REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_CFG_UPD,
2335 + return CI_STATUS_FAILURE;
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");
2343 + return CI_STATUS_SUCCESS;
2347 + * Waits until a frame is written to memory (frame end
2348 + * interrupt occurs).
2349 + * Waits for the frame end interrupt of the memory
2352 +int ci_isp_wait_for_frame_end(struct mrst_isp_device *intel)
2354 + return ci_isp_wait_for_mi(intel, ci_isp_get_frame_end_irq_mask_isp());
2358 + * Writes '0xFFFFFFFF' into all *_icr registers to clear all
2361 +void ci_isp_reset_interrupt_status(void)
2363 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
2374 + REG_WRITE(mrv_reg->mipi_icr, 0xffffffff); /*XXX replace by a macro */
2377 +void mrst_isp_disable_interrupt(struct mrst_isp_device *isp)
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);
2387 +void mrst_isp_enable_interrupt(struct mrst_isp_device *isp)
2389 + struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE;
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);
2394 + REG_WRITE(mrv_reg->mi_imsc, MRV_MI_MP_FRAME_END_MASK);
2396 + REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON);
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);
2401 + REG_WRITE(mrv_reg->mipi_imsc, 0x00f00000);
2403 + ci_isp_reset_interrupt_status();
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
2412 +void ci_isp_set_dma_read_mode(enum ci_isp_dma_read_mode mode,
2413 + enum ci_isp_conf_update_time update_time)
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;
2425 + u32 vi_dpcl = REG_READ(mrv_reg->vi_dpcl);
2428 + * DMA-read feature connected through a dedicated DMA-read
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)));
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;
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;
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;
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;
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;
2472 + /* unknown DMA-read mode */
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);
2486 + /* direct DMA to JPEG not supported */
2487 + UNUSED_PARAM(dma_jpeg_select);
2489 + REG_WRITE(mrv_reg->vi_dpcl, vi_dpcl);
2493 + * Set extended mode with unrestricted values for YCbCr
2494 + * Y (0-255) CbCr (0-255)
2496 +void ci_isp_set_ext_ycmode(void)
2498 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2499 + u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
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);
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);
2520 +void ci_isp_set_yc_mode(void)
2522 + struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE;
2523 + u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl);
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);
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);
2545 + * writes the color values for contrast, brightness,
2546 + * saturation and hue into the appropriate Marvin
2549 +void ci_isp_col_set_color_processing(
2550 + const struct ci_isp_color_settings *col)
2552 + struct isp_register *mrv_reg =
2553 + (struct isp_register *) MEM_MRV_REG_BASE;
2555 + if (col == NULL) {
2556 + /* disable color processing (bypass) */
2557 + mrv_reg->c_proc_ctrl = 0;
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;
2564 + /* modify color processing registers */
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;
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;
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;
2581 + if (col->flags & CI_ISP_CPROC_ENABLE) {
2582 + mrv_reg->c_proc_ctrl =
2583 + mrv_reg->c_proc_ctrl | CI_ISP_CPROC_ENABLE;
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
2598 +static u32 ci_isp_ie_tint_cx2_reg_val(u8 cx)
2604 + * apply scaling as specified in the image effects functional
2607 + temp = 128 - (s32) cx;
2608 + temp = ((temp * 64) / 110);
2610 + /* convert from two's complement to sign/value */
2617 + /* saturate at 7 bits */
2621 + /* combine sign and value to build the regiter value */
2622 + reg_val |= (u32) temp;
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
2638 +static u32 ci_isp_ie_mx_dec2_reg_val(s8 dec)
2640 + if (dec <= (-6)) {
2641 + /* equivlent to -8 */
2643 + } else if (dec <= (-3)) {
2644 + /* equivlent to -4 */
2646 + } else if (dec == (-2)) {
2647 + /* equivlent to -2 */
2649 + } else if (dec == (-1)) {
2650 + /* equivlent to -1 */
2652 + } else if (dec == 0) {
2653 + /* equivlent to 0 (entry not used) */
2655 + } else if (dec == 1) {
2656 + /* equivlent to 1 */
2658 + } else if (dec == 2) {
2659 + /* equivlent to 2 */
2661 + } else if (dec < 6) {
2662 + /* equivlent to 4 */
2665 + /* equivlent to 8 */
2671 + * translates the values of the given configuration
2672 + * structure into register settings for the image effects
2673 + * submodule and loads the registers.
2675 +int ci_isp_ie_set_config(const struct ci_isp_ie_config *ie_config)
2677 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
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);
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);
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);
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);
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);
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);
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);
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);
2737 + return CI_STATUS_OUTOFRANGE;
2740 + /* use next frame sync update */
2741 + REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_CFG_UPD, ON);
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));
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));
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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);
2821 + /* frame synchronous update of shadow registers */
2822 + REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON);
2825 + return CI_STATUS_SUCCESS;
2829 + * Applies the new image stabilisation settings to the module.
2831 +int ci_isp_is_set_config(const struct ci_isp_is_config *is_config)
2833 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2836 + eprintk("is_config NULL");
2837 + return CI_STATUS_NULL_POINTER;
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));
2845 + REG_SET_SLICE(mrv_reg->isp_is_max_dx, MRV_IS_IS_MAX_DX,
2846 + (u32) (is_config->max_dx));
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));
2854 + REG_SET_SLICE(mrv_reg->isp_is_max_dy, MRV_IS_IS_MAX_DY,
2855 + (u32) (is_config->max_dy));
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));
2865 + REG_SET_SLICE(mrv_reg->isp_is_h_size, MRV_IS_IS_H_SIZE,
2866 + (u32) (is_config->mrv_is_window.hsize));
2868 + REG_SET_SLICE(mrv_reg->isp_is_v_size, MRV_IS_IS_V_SIZE,
2869 + (u32) (is_config->mrv_is_window.vsize));
2871 + return CI_STATUS_SUCCESS;
2874 +static int ci_isp_bls_set_fixed_values(const struct ci_isp_bls_subtraction
2877 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2879 + if (!bls_subtraction)
2880 + return CI_STATUS_NULL_POINTER;
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;
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);
2903 + return CI_STATUS_SUCCESS;
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.
2911 +int ci_isp_bls_set_config(const struct ci_isp_bls_config *bls_config)
2913 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
2914 + u32 isp_bls_ctrl = 0;
2916 + int error = CI_STATUS_FAILURE;
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;
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;
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);
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;
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);
2979 + if (bls_config->bls_samples > MRV_BLS_BLS_SAMPLES_MAX) {
2980 + return CI_STATUS_OUTOFRANGE;
2982 + REG_SET_SLICE(mrv_reg->isp_bls_samples, MRV_BLS_BLS_SAMPLES,
2983 + bls_config->bls_samples);
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)
2994 + if ((bls_config->disable_h) || (bls_config->disable_v))
2995 + return CI_STATUS_OUTOFRANGE;
2997 + isp_bls_ctrl = REG_READ(mrv_reg->isp_bls_ctrl);
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));
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);
3011 + /* enable module */
3012 + REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_BLS_ENABLE, ENABLE);
3014 + /* write into register */
3015 + REG_WRITE(mrv_reg->isp_bls_ctrl, isp_bls_ctrl);
3017 + return CI_STATUS_SUCCESS;
3020 +#define RSZ_FLAGS_MASK (RSZ_UPSCALE_ENABLE | RSZ_SCALER_BYPASS)
3023 + * writes the scaler values to the appropriate Marvin registers.
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)
3029 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
3030 + u32 mrsz_ctrl = REG_READ(mrv_reg->mrsz_ctrl);
3032 + int upscaling = false;
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));
3042 + /* horizontal luminance scale factor */
3043 + dprintk(1, "scale_hy = %d( %x )", scale->scale_hy, scale->scale_hy);
3045 + if (scale->scale_hy & RSZ_SCALER_BYPASS) {
3046 + /* disable (bypass) scaler */
3047 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_ENABLE, DISABLE);
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);
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 */
3065 + /* disable upscaling mode */
3066 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_UP,
3067 + MRV_MRSZ_SCALE_HY_UP_DOWNSCALE);
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);
3075 + if (scale->scale_hcb & RSZ_SCALER_BYPASS) {
3076 + /* disable (bypass) scaler */
3077 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_ENABLE, DISABLE);
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);
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 */
3096 + /* disable upscaling mode */
3097 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_UP,
3098 + MRV_MRSZ_SCALE_HC_UP_DOWNSCALE);
3102 + /* vertical luminance scale factor */
3103 + dprintk(1, "scale_vy = %d ( %x )", scale->scale_vy, scale->scale_vy);
3105 + if (scale->scale_vy & RSZ_SCALER_BYPASS) {
3106 + /* disable (bypass) scaler */
3107 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_ENABLE,
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);
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 */
3125 + /* disable upscaling mode */
3126 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_UP,
3127 + MRV_MRSZ_SCALE_VY_UP_DOWNSCALE);
3131 + /* vertical chrominance scale factor */
3132 + dprintk(1, "scale_vc = %d( %x )", scale->scale_vc, scale->scale_vc);
3134 + if (scale->scale_vc & RSZ_SCALER_BYPASS) {
3135 + /* disable (bypass) scaler */
3136 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_ENABLE,
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);
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 */
3154 + /* disable upscaling mode */
3155 + REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_UP,
3156 + MRV_MRSZ_SCALE_VC_UP_DOWNSCALE);
3160 + /* apply upscaling lookup table */
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]);
3169 + } else if (upscaling) {
3170 + eprintk("Upscaling requires lookup table!");
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);
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);
3186 + case CI_ISP_CFG_UPDATE_LATER:
3188 + /* no update from within this function */
3189 + REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl);
3195 + * writes the scaler values to the appropriate Marvin registers.
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)
3201 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
3202 + u32 srsz_ctrl = REG_READ(mrv_reg->srsz_ctrl);
3204 + int upscaling = false;
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));
3214 + /* horizontal luminance scale factor */
3215 + dprintk(1, "scale_hy = %d,%x", scale->scale_hy, scale->scale_hy);
3217 + if (scale->scale_hy & RSZ_SCALER_BYPASS) {
3218 + /* disable (bypass) scaler */
3219 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_ENABLE,
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);
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 */
3237 + /* disable upscaling mode */
3238 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_UP,
3239 + MRV_SRSZ_SCALE_HY_UP_DOWNSCALE);
3243 + /* horizontal chrominance scale factors */
3244 + WARN_ON(!((scale->scale_hcb & RSZ_FLAGS_MASK) == (scale->scale_hcr &
3245 + RSZ_FLAGS_MASK)));
3247 + dprintk(1, "scale_hcb = %d,%x", scale->scale_hcb, scale->scale_hcb);
3249 + if (scale->scale_hcb & RSZ_SCALER_BYPASS) {
3250 + /* disable (bypass) scaler */
3251 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_ENABLE,
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);
3262 + REG_SET_SLICE(mrv_reg->srsz_phase_hc, MRV_SRSZ_PHASE_HC,
3263 + (u32) scale->phase_hc);
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 */
3271 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_UP,
3272 + MRV_SRSZ_SCALE_HC_UP_DOWNSCALE);
3276 + /* vertical luminance scale factor */
3277 + dprintk(1, "scale_vy = %d,%x", scale->scale_vy, scale->scale_vy);
3279 + if (scale->scale_vy & RSZ_SCALER_BYPASS) {
3280 + /* disable (bypass) scaler */
3281 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_ENABLE,
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);
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 */
3299 + /* disable upscaling mode */
3300 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_UP,
3301 + MRV_SRSZ_SCALE_VY_UP_DOWNSCALE);
3305 + /* vertical chrominance scale factor */
3306 + dprintk(1, "scale_vc = %d,%x", scale->scale_vc, scale->scale_vc);
3308 + if (scale->scale_vc & RSZ_SCALER_BYPASS) {
3309 + /* disable (bypass) scaler */
3310 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_ENABLE,
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);
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 */
3328 + /* disable upscaling mode */
3329 + REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_UP,
3330 + MRV_SRSZ_SCALE_VC_UP_DOWNSCALE);
3334 + /* apply upscaling lookup table */
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]);
3343 + } else if (upscaling) {
3344 + eprintk("Upscaling requires lookup table!");
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,
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);
3361 + case CI_ISP_CFG_UPDATE_LATER:
3363 + /* no update from within this function */
3364 + REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl);
3371 +/* bad pixel table */
3372 +static struct ci_sensor_bp_table bp_table = { 0 };
3375 + * Initialization of the Bad Pixel Detection and Correction.
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)
3380 + int error = CI_STATUS_SUCCESS;
3382 + /* number of table elements */
3383 + /* number of table elements */
3384 +#define MRVSLS_BPINIT_MAX_TABLE 2048
3386 + /* check the parameters */
3387 + if (!bp_corr_config || !bp_det_config)
3388 + return CI_STATUS_NULL_POINTER;
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;
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();
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);
3417 + return CI_STATUS_NOTSUPP;
3424 + * Disable the Bad Pixel Detection and Correction.
3426 +int ci_bp_end(const struct ci_isp_bp_corr_config *bp_corr_config)
3428 + int uiResult = CI_STATUS_SUCCESS;
3430 + /* check the parameter */
3431 + if (!bp_corr_config)
3432 + return CI_STATUS_NULL_POINTER;
3434 + /* disable badpixel correction */
3435 + uiResult |= ci_isp_set_bp_correction(NULL);
3437 + /* disable badpixel detection */
3438 + uiResult |= ci_isp_set_bp_detection(NULL);
3440 + if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_TABLE) {
3441 + /* Clear Interrupt Status */
3442 + uiResult |= ci_isp_clear_bp_int();
3444 + /* deallocate BP Table */
3445 + kfree(bp_table.bp_table_elem);
3446 + bp_table.bp_table_elem = NULL;
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
3455 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c
3458 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
3460 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
3462 + * Copyright (c) Silicon Image 2008 www.siliconimage.com
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.
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.
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.
3479 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
3482 +#include "mrstisp_stdinc.h"
3484 +int mrst_isp_set_color_conversion_ex(void)
3486 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
3498 + return CI_STATUS_SUCCESS;
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.
3506 +enum ci_isp_path ci_isp_select_path(const struct ci_sensor_config *isi_cfg,
3507 + u8 *words_per_pixel)
3510 + enum ci_isp_path ret_val;
3512 + switch (isi_cfg->mode) {
3513 + case SENSOR_MODE_DATA:
3514 + ret_val = CI_ISP_PATH_RAW;
3517 + case SENSOR_MODE_PICT:
3518 + ret_val = CI_ISP_PATH_RAW;
3521 + case SENSOR_MODE_RGB565:
3522 + ret_val = CI_ISP_PATH_RAW;
3525 + case SENSOR_MODE_BT601:
3526 + ret_val = CI_ISP_PATH_YCBCR;
3529 + case SENSOR_MODE_BT656:
3530 + ret_val = CI_ISP_PATH_YCBCR;
3533 + case SENSOR_MODE_BAYER:
3534 + ret_val = CI_ISP_PATH_BAYER;
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;
3547 + case SENSOR_SMIA_MODE_YUV_422:
3548 + ret_val = CI_ISP_PATH_YCBCR;
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:
3559 + ret_val = CI_ISP_PATH_RAW;
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;
3573 + case SENSOR_MIPI_MODE_YUV422_8:
3574 + case SENSOR_MIPI_MODE_YUV422_10:
3575 + ret_val = CI_ISP_PATH_YCBCR;
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:
3591 + ret_val = CI_ISP_PATH_RAW;
3596 + case SENSOR_MODE_BAY_BT656:
3597 + ret_val = CI_ISP_PATH_BAYER;
3600 + case SENSOR_MODE_RAW_BT656:
3601 + ret_val = CI_ISP_PATH_RAW;
3605 + ret_val = CI_ISP_PATH_UNKNOWN;
3609 + if (words_per_pixel)
3610 + *words_per_pixel = words ;
3615 + * configures the input acquisition according to the
3616 + * given config structure
3618 +int ci_isp_set_input_aquisition(const struct ci_sensor_config *isi_cfg)
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 */
3625 + /* number of additional black lines at frame start */
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;
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);
3639 + case SENSOR_MODE_PICT:
3640 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3641 + MRV_ISP_ISP_MODE_RAW);
3643 + case SENSOR_MODE_RGB565:
3644 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3645 + MRV_ISP_ISP_MODE_RAW);
3647 + case SENSOR_MODE_BT601:
3648 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3649 + MRV_ISP_ISP_MODE_601);
3651 + case SENSOR_MODE_BT656:
3652 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3653 + MRV_ISP_ISP_MODE_656);
3655 + case SENSOR_MODE_BAYER:
3656 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3657 + MRV_ISP_ISP_MODE_RGB);
3659 + case SENSOR_MODE_BAY_BT656:
3660 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3661 + MRV_ISP_ISP_MODE_RGB656);
3663 + case SENSOR_MODE_RAW_BT656:
3664 + REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE,
3665 + MRV_ISP_ISP_MODE_RAW656);
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;
3685 + return CI_STATUS_NOTSUPP;
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);
3696 + return CI_STATUS_NOTSUPP;
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);
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);
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);
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);
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);
3725 + /* 101...111 reserved */
3727 + return CI_STATUS_NOTSUPP;
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);
3735 + case SENSOR_FIELDSEL_EVEN:
3736 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION,
3737 + MRV_ISP_FIELD_SELECTION_EVEN);
3739 + case SENSOR_FIELDSEL_BOTH:
3740 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION,
3741 + MRV_ISP_FIELD_SELECTION_BOTH);
3744 + return CI_STATUS_NOTSUPP;
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);
3752 + case SENSOR_YCSEQ_CBYCRY:
3753 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3754 + MRV_ISP_CCIR_SEQ_CBYCRY);
3756 + case SENSOR_YCSEQ_YCRYCB:
3757 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3758 + MRV_ISP_CCIR_SEQ_YCRYCB);
3760 + case SENSOR_YCSEQ_YCBYCR:
3761 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ,
3762 + MRV_ISP_CCIR_SEQ_YCBYCR);
3765 + return CI_STATUS_NOTSUPP;
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);
3774 + case SENSOR_CONV422_NOCOSITED:
3775 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422,
3776 + MRV_ISP_CONV_422_NONCO);
3778 + case SENSOR_CONV422_COSITED:
3779 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422,
3780 + MRV_ISP_CONV_422_CO);
3783 + return CI_STATUS_NOTSUPP;
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);
3791 + case SENSOR_BPAT_GBGBRGRG:
3792 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3793 + MRV_ISP_BAYER_PAT_GB);
3795 + case SENSOR_BPAT_GRGRBGBG:
3796 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3797 + MRV_ISP_BAYER_PAT_GR);
3799 + case SENSOR_BPAT_RGRGGBGB:
3800 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT,
3801 + MRV_ISP_BAYER_PAT_RG);
3804 + return CI_STATUS_NOTSUPP;
3807 + switch (isi_cfg->vpol) {
3808 + case SENSOR_VPOL_POS:
3809 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_VSYNC_POL, 1);
3811 + case SENSOR_VPOL_NEG:
3812 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_VSYNC_POL, 0);
3815 + return CI_STATUS_NOTSUPP;
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);
3826 + case SENSOR_HPOL_SYNCNEG:
3827 + /* trigger on positive edge */
3828 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 0);
3830 + case SENSOR_HPOL_REFPOS:
3831 + /* trigger on positive edge */
3832 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 0);
3834 + case SENSOR_HPOL_REFNEG:
3835 + /* trigger on negative edge */
3836 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 1);
3839 + return CI_STATUS_NOTSUPP;
3842 + switch (isi_cfg->edge) {
3843 + case SENSOR_EDGE_RISING:
3844 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_SAMPLE_EDGE, 1);
3846 + case SENSOR_EDGE_FALLING:
3847 + REG_SET_SLICE(isp_acq_prop, MRV_ISP_SAMPLE_EDGE, 0);
3850 + return CI_STATUS_NOTSUPP;
3852 + dprintk(2, "isp_acq_prop = 0x%x", isp_acq_prop);
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);
3858 + /* number of additional black lines at frame start */
3859 + switch (isi_cfg->bls) {
3860 + case SENSOR_BLS_OFF:
3863 + case SENSOR_BLS_TWO_LINES:
3866 + case SENSOR_BLS_FOUR_LINES:
3870 + return CI_STATUS_NOTSUPP;
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);
3877 + dprintk(2, "res = %x", isi_cfg->res);
3878 + switch (isi_cfg->res) {
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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,
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,
4054 + case SENSOR_RES_RAWMAX:
4055 + REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE,
4057 + REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE,
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,
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,
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,
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,
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,
4097 + return CI_STATUS_NOTSUPP;
4100 + return CI_STATUS_SUCCESS;
4104 + * sets output window
4106 +void ci_isp_set_output_formatter(const struct ci_isp_window *window,
4107 + enum ci_isp_conf_update_time update_time)
4109 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4112 + /* set output window */
4113 + REG_SET_SLICE(mrv_reg->isp_out_h_offs, MRV_IS_IS_H_OFFS,
4115 + REG_SET_SLICE(mrv_reg->isp_out_v_offs, MRV_IS_IS_V_OFFS,
4117 + REG_SET_SLICE(mrv_reg->isp_out_h_size, MRV_IS_IS_H_SIZE,
4119 + REG_SET_SLICE(mrv_reg->isp_out_v_size, MRV_IS_IS_V_SIZE,
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,
4126 + REG_SET_SLICE(mrv_reg->isp_is_v_size, MRV_IS_IS_V_SIZE,
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);
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);
4140 + case CI_ISP_CFG_UPDATE_LATER:
4141 + /* no update from within this function */
4150 + * programs the given Bayer pattern demosaic parameters
4152 +void ci_isp_set_demosaic(enum ci_isp_demosaic_mode demosaic_mode,
4155 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4156 + u32 isp_demosaic = REG_READ(mrv_reg->isp_demosaic);
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);
4164 + case CI_ISP_DEMOSAIC_ENHANCED:
4165 + REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_MODE,
4166 + MRV_ISP_DEMOSAIC_MODE_ENH);
4169 + WARN_ON(!(false));
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);
4178 + * Sets the dedicated AWB block mode.
4180 +int ci_isp_set_wb_mode(enum ci_isp_awb_mode wb_mode)
4182 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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,
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,
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,
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,
4220 + return CI_STATUS_FAILURE;
4223 + return CI_STATUS_SUCCESS;
4226 +int ci_isp_get_wb_mode(enum ci_isp_awb_mode *wb_mode)
4228 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4231 + return CI_STATUS_NULL_POINTER;
4233 + if (REG_GET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE) ==
4235 + *wb_mode = CI_ISP_AWB_COMPLETELY_OFF;
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;
4243 + case MRV_ISP_AWB_MODE_NOMEAS:
4244 + *wb_mode = CI_ISP_AWB_MAN_NOMEAS;
4247 + *wb_mode = CI_ISP_AWB_COMPLETELY_OFF;
4248 + return CI_STATUS_FAILURE;
4251 + return CI_STATUS_SUCCESS;
4253 +int ci_isp_set_wb_meas_config(const struct ci_isp_wb_meas_config
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);
4259 + if (!wb_meas_config)
4260 + return CI_STATUS_NULL_POINTER;
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);
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,
4277 + REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN,
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));
4296 + /* amount of measurement frames */
4297 + REG_SET_SLICE(mrv_reg->isp_awb_frames, MRV_ISP_AWB_FRAMES,
4298 + (u32) wb_meas_config->frames);
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));
4304 + return CI_STATUS_SUCCESS;
4307 +int ci_isp_get_wb_meas_config(struct ci_isp_wb_meas_config *wb_meas_config)
4309 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4311 + if (!wb_meas_config)
4312 + return CI_STATUS_NULL_POINTER;
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);
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);
4339 + /* amount of measurement frames */
4340 + wb_meas_config->frames =
4341 + (u8) REG_GET_SLICE(mrv_reg->isp_awb_frames, MRV_ISP_AWB_FRAMES);
4343 + /* overwrite max_y if the feature is disabled */
4344 + if (REG_GET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN) ==
4346 + wb_meas_config->max_y = 0;
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;
4355 +int ci_isp_get_wb_meas(struct ci_sensor_awb_mean *awb_mean)
4357 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4359 + if (awb_mean == NULL)
4360 + return CI_STATUS_NULL_POINTER;
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;
4374 + * calculates left-top and right-bottom register values
4375 + * for a given AF measurement window
4377 +static int ci_isp_afm_wnd2_regs(const struct ci_isp_window *wnd, u32 *lt,
4380 + WARN_ON(!((wnd != NULL) && (lt != NULL) && (rb != NULL)));
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;
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;
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);
4409 + return CI_STATUS_SUCCESS;
4412 +int ci_isp_set_auto_focus(const struct ci_isp_af_config *af_config)
4415 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4416 + u32 result = CI_STATUS_SUCCESS;
4418 + /* disable measurement module */
4419 + REG_SET_SLICE(mrv_reg->isp_afm_ctrl, MRV_AFM_AFM_EN, DISABLE);
4424 + result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_a),
4426 + /* set measurement window boundaries */
4427 + if (result != CI_STATUS_SUCCESS)
4430 + REG_WRITE(mrv_reg->isp_afm_lt_a, lt);
4431 + REG_WRITE(mrv_reg->isp_afm_rb_a, rb);
4433 + result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_b),
4436 + if (result != CI_STATUS_SUCCESS)
4439 + REG_WRITE(mrv_reg->isp_afm_lt_b, lt);
4440 + REG_WRITE(mrv_reg->isp_afm_rb_b, rb);
4442 + result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_c),
4445 + if (result != CI_STATUS_SUCCESS)
4448 + REG_WRITE(mrv_reg->isp_afm_lt_c, lt);
4449 + REG_WRITE(mrv_reg->isp_afm_rb_c, rb);
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));
4459 + /* enable measurement module */
4460 + REG_SET_SLICE(mrv_reg->isp_afm_ctrl, MRV_AFM_AFM_EN, ENABLE);
4467 +void ci_isp_get_auto_focus_meas(struct ci_isp_af_meas *af_meas)
4469 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4471 + WARN_ON(!(af_meas != NULL));
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);
4487 +int ci_isp_set_ls_correction(struct ci_sensor_ls_corr_config *ls_corr_config)
4489 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4492 + int enabled = false;
4494 + if (!ls_corr_config) {
4495 + /* disable lens shading module */
4496 + REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, DISABLE);
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 */
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);
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)));
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
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
4540 + REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_1,
4541 + ls_corr_config->ls_gdata_tbl
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
4549 + REG_WRITE(mrv_reg->isp_lsc_b_table_data, data);
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);
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]);
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]);
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]);
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]);
4641 + /* switch on lens chading correction */
4642 + REG_SET_SLICE(mrv_reg->isp_lsc_ctrl,
4643 + MRV_LSC_LSC_EN, ENABLE);
4647 + return CI_STATUS_SUCCESS;
4650 +int ci_isp_ls_correction_on_off(int ls_corr_on_off)
4652 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
4658 + /* switch off lens chading correction */
4659 + REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, DISABLE);
4662 + return CI_STATUS_SUCCESS;
4666 + * Sets the Bad Pixel Correction configuration
4668 +int ci_isp_set_bp_correction(const struct ci_isp_bp_corr_config
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);
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);
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);
4685 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_COR_TYPE,
4686 + MRV_BP_COR_TYPE_DIRECT);
4688 + WARN_ON(!(!REG_GET_SLICE(mrv_reg->isp_bp_ctrl,
4689 + MRV_BP_BP_DET_EN)));
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);
4703 + /* use bad pixel table */
4704 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_COR_TYPE,
4705 + MRV_BP_COR_TYPE_TABLE);
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);
4713 + /* use best neighbour */
4714 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_REP_APPR,
4715 + MRV_BP_REP_APPR_NEAREST);
4718 + switch (bp_corr_config->bp_corr_mode) {
4719 + case CI_ISP_BP_CORR_HOT_EN:
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);
4725 + case CI_ISP_BP_CORR_DEAD_EN:
4727 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, DISABLE);
4729 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, ENABLE);
4731 + case CI_ISP_BP_CORR_HOT_DEAD_EN:
4734 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, ENABLE);
4736 + REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, ENABLE);
4741 + REG_WRITE(mrv_reg->isp_bp_ctrl, isp_bp_ctrl);
4743 + return CI_STATUS_SUCCESS;
4748 + * Sets the Bad Pixel configuration for detection
4750 +int ci_isp_set_bp_detection(const struct ci_isp_bp_det_config *bp_det_config)
4752 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4754 + if (!bp_det_config) {
4755 + /* disable measurement module */
4756 + REG_SET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_BP_DET_EN, DISABLE);
4758 + WARN_ON(!(REG_GET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_COR_TYPE)
4759 + == MRV_BP_COR_TYPE_TABLE));
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);
4765 + /* enable measurement module */
4766 + REG_SET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_BP_DET_EN, ENABLE);
4769 + return CI_STATUS_SUCCESS;
4772 +int ci_isp_clear_bp_int(void)
4774 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
4780 + return CI_STATUS_SUCCESS;
4784 + * Initializes Isp filter registers with default reset values.
4786 +static int ci_isp_initialize_filter_registers(void)
4788 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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;
4802 + return CI_STATUS_SUCCESS;
4805 +int ci_isp_activate_filter(int activate_filter)
4807 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4808 + int retval = CI_STATUS_SUCCESS;
4810 + /* Initialize ISP filter control registers first */
4811 + retval = ci_isp_initialize_filter_registers();
4812 + if (retval != CI_STATUS_SUCCESS)
4815 + /* Activate or deactivate filter algorythm */
4816 + REG_SET_SLICE(mrv_reg->isp_filt_mode, MRV_FILT_FILT_ENABLE,
4817 + (activate_filter) ? ENABLE : DISABLE);
4823 + * Write coefficient and threshold values into Isp filter
4824 + * registers for noise, sharpness and blurring filtering.
4826 +int ci_isp_set_filter_params(u8 noise_reduc_level, u8 sharp_level)
4828 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
4829 + u32 isp_filt_mode = 0;
4831 + if (!REG_GET_SLICE(mrv_reg->isp_filt_mode, MRV_FILT_FILT_ENABLE))
4832 + return CI_STATUS_CANCELED;
4834 + REG_WRITE(mrv_reg->isp_filt_mode, isp_filt_mode);
4836 + if (((noise_reduc_level <= 10) || (noise_reduc_level == 99))
4837 + && (sharp_level <= 10)) {
4838 + switch (noise_reduc_level) {
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
5054 + return CI_STATUS_OUTOFRANGE;
5057 + switch (sharp_level) {
5058 + /* SharpLevel = 0; no sharp enhancement */
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);
5072 + /* SharpLevel = 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);
5086 + /* SharpLevel = 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);
5100 + /* SharpLevel = 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);
5114 + /* SharpLevel = 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);
5128 + /* SharpLevel = 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);
5142 + /* SharpLevel = 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);
5156 + /* SharpLevel = 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);
5170 + /* SharpLevel = 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,
5181 + REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5182 + MRV_FILT_FILT_FAC_SH1, 0x0000002C);
5184 + REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5185 + MRV_FILT_FILT_FAC_SH0, 0x00000024);
5187 + REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5188 + MRV_FILT_FILT_FAC_MID, 0x0000001D);
5190 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5191 + MRV_FILT_FILT_FAC_BL0, 0x00000015);
5193 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5194 + MRV_FILT_FILT_FAC_BL1, 0x0000000D);
5197 + /* SharpLevel = 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,
5208 + REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5209 + MRV_FILT_FILT_FAC_SH1, 0x00000030);
5211 + REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5212 + MRV_FILT_FILT_FAC_SH0, 0x0000002A);
5214 + REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5215 + MRV_FILT_FILT_FAC_MID, 0x00000022);
5217 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5218 + MRV_FILT_FILT_FAC_BL0, 0x0000001A);
5220 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5221 + MRV_FILT_FILT_FAC_BL1, 0x00000014);
5224 + /* SharpLevel = 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) */
5231 + /* REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1,
5232 + * MRV_FILT_FILT_THRESH_SH1, 0x0000008A); */
5236 + REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1,
5237 + MRV_FILT_FILT_FAC_SH1, 0x0000003F);
5239 + REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0,
5240 + MRV_FILT_FILT_FAC_SH0, 0x00000030);
5242 + REG_SET_SLICE(mrv_reg->isp_filt_fac_mid,
5243 + MRV_FILT_FILT_FAC_MID, 0x00000028);
5245 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5246 + MRV_FILT_FILT_FAC_BL0, 0x00000024);
5248 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5249 + MRV_FILT_FILT_FAC_BL1, 0x00000020);
5253 + return CI_STATUS_OUTOFRANGE;
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);
5265 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5266 + MRV_FILT_FILT_FAC_BL0,
5267 + (filt_fac_bl0) >> 1);
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->
5279 + MRV_FILT_FILT_FAC_BL1);
5281 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0,
5282 + MRV_FILT_FILT_FAC_BL0,
5283 + (filt_fac_bl0 * 3) >> 2);
5285 + REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1,
5286 + MRV_FILT_FILT_FAC_BL1,
5287 + (filt_fac_bl1) >> 1);
5291 + /* Set ISP filter mode register values */
5292 + REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_MODE,
5293 + MRV_FILT_FILT_MODE_DYNAMIC);
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);
5299 + return CI_STATUS_SUCCESS;
5301 + /* At least one function parameter is out of range */
5302 + return CI_STATUS_OUTOFRANGE;
5306 +int ci_isp_meas_exposure_initialize_module(void)
5308 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
5315 + return CI_STATUS_SUCCESS;
5320 + * Configures the exposure measurement module.
5322 +int ci_isp_meas_exposure_set_config(const struct ci_isp_window *wnd,
5323 + const struct ci_isp_exp_ctrl *isp_exp_ctrl)
5325 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5328 + /* stop loop if running */
5329 + REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_AUTOSTOP, ON);
5331 + REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_START, OFF);
5332 + return CI_STATUS_SUCCESS;
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;
5343 + /* configure measurement windows */
5344 + REG_SET_SLICE(mrv_reg->isp_exp_h_size, MRV_AE_ISP_EXP_H_SIZE,
5346 + REG_SET_SLICE(mrv_reg->isp_exp_v_size, MRV_AE_ISP_EXP_V_SIZE,
5348 + REG_SET_SLICE(mrv_reg->isp_exp_h_offset, MRV_AE_ISP_EXP_H_OFFSET,
5350 + REG_SET_SLICE(mrv_reg->isp_exp_v_offset, MRV_AE_ISP_EXP_V_OFFSET,
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);
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);
5363 + return CI_STATUS_SUCCESS;
5367 + * Programs the given gamma curve for the input gamma
5368 + * block. Enables or disables gamma processing for the
5369 + * input gamma block.
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)
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);
5385 + * Note: gamma curve increments are already register conform,
5386 + * so REG_WRITE is used instead of REG_SET_SLICE
5390 + * better would be split into 16 separate values to be
5391 + * register independant
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);
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);
5411 + REG_SET_SLICE(mrv_reg->isp_ctrl,
5412 + MRV_ISP_ISP_GAMMA_IN_ENABLE, ENABLE);
5414 + REG_SET_SLICE(mrv_reg->isp_ctrl,
5415 + MRV_ISP_ISP_GAMMA_IN_ENABLE, DISABLE);
5420 + * Programs the given gamma curve for the output gamma
5421 + * block. Enables or disables gamma processing for the
5422 + * output gamma block.
5424 +void ci_isp_set_gamma2(const struct ci_isp_gamma_out_curve *gamma)
5426 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5430 + WARN_ON(!(MRV_ISP_GAMMA_OUT_Y_ARR_SIZE ==
5431 + CI_ISP_GAMMA_OUT_CURVE_ARR_SIZE));
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]);
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,
5445 + REG_SET_SLICE(mrv_reg->isp_ctrl,
5446 + MRV_ISP_ISP_GAMMA_OUT_ENABLE, DISABLE);
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
5454 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c
5457 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
5459 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
5461 + * Copyright (c) Silicon Image 2008 www.siliconimage.com
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.
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.
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.
5478 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
5481 +#include "mrstisp_stdinc.h"
5483 +int ci_isp_jpe_init_ex(u16 hsize, u16 vsize, u8 compression_ratio, u8 jpe_scale)
5485 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5488 + * Reset JPEG-Encoder. In contrast to other software resets
5489 + * this triggers the modules asynchronous reset resulting
5490 + * in loss of all data.
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);
5496 + /* set configuration for the Jpeg capturing */
5497 + ci_isp_jpe_set_config(hsize, vsize, jpe_scale);
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.
5508 + * Note: this func is called when holding spin lock,
5509 + * so can not change to msleep.
5513 + /* program tables */
5514 + ci_isp_jpe_set_tables(compression_ratio);
5516 + /* choose tables */
5517 + ci_isp_jpe_select_tables();
5519 + return CI_STATUS_SUCCESS;
5523 + * initialization of JPEG encoder
5525 +int ci_isp_jpe_init(u32 resolution, u8 compression_ratio, int jpe_scale)
5530 + switch (resolution) {
5531 + case SENSOR_RES_BP1:
5533 + hsize = BP1_SIZE_H;
5535 + vsize = BP1_SIZE_V;
5537 + case SENSOR_RES_S_AFM:
5539 + hsize = S_AFM_SIZE_H;
5541 + vsize = S_AFM_SIZE_V;
5543 + case SENSOR_RES_M_AFM:
5545 + hsize = M_AFM_SIZE_H;
5547 + vsize = M_AFM_SIZE_V;
5549 + case SENSOR_RES_L_AFM:
5551 + hsize = L_AFM_SIZE_H;
5553 + vsize = L_AFM_SIZE_V;
5555 + case SENSOR_RES_QQCIF:
5557 + hsize = QQCIF_SIZE_H;
5559 + vsize = QQCIF_SIZE_V;
5561 + case SENSOR_RES_QQVGA:
5563 + hsize = QQVGA_SIZE_H;
5565 + vsize = QQVGA_SIZE_V;
5567 + case SENSOR_RES_QCIF:
5569 + hsize = QCIF_SIZE_H;
5571 + vsize = QCIF_SIZE_V;
5573 + case SENSOR_RES_QVGA:
5575 + hsize = QVGA_SIZE_H;
5577 + vsize = QVGA_SIZE_V;
5579 + case SENSOR_RES_CIF:
5581 + hsize = CIF_SIZE_H;
5583 + vsize = CIF_SIZE_V;
5585 + case SENSOR_RES_VGA:
5587 + hsize = VGA_SIZE_H;
5589 + vsize = VGA_SIZE_V;
5591 + case SENSOR_RES_SVGA:
5593 + hsize = SVGA_SIZE_H;
5595 + vsize = SVGA_SIZE_V;
5597 + case SENSOR_RES_XGA:
5599 + hsize = XGA_SIZE_H;
5601 + vsize = XGA_SIZE_V;
5603 + case SENSOR_RES_XGA_PLUS:
5605 + hsize = XGA_PLUS_SIZE_H;
5607 + vsize = XGA_PLUS_SIZE_V;
5609 + case SENSOR_RES_SXGA:
5611 + hsize = SXGA_SIZE_H;
5613 + vsize = SXGA_SIZE_V;
5615 + case SENSOR_RES_UXGA:
5617 + hsize = UXGA_SIZE_H;
5619 + vsize = UXGA_SIZE_V;
5621 + case SENSOR_RES_QXGA:
5623 + hsize = QXGA_SIZE_H;
5625 + vsize = QXGA_SIZE_V;
5627 + case SENSOR_RES_QSXGA:
5629 + hsize = QSXGA_SIZE_H;
5631 + vsize = QSXGA_SIZE_V;
5633 + case SENSOR_RES_QSXGA_PLUS:
5635 + hsize = QSXGA_PLUS_SIZE_H;
5637 + vsize = QSXGA_PLUS_SIZE_V;
5639 + case SENSOR_RES_QSXGA_PLUS2:
5641 + hsize = QSXGA_PLUS2_SIZE_H;
5643 + vsize = QSXGA_PLUS2_SIZE_V;
5645 + case SENSOR_RES_QSXGA_PLUS3:
5647 + hsize = QSXGA_PLUS3_SIZE_H;
5649 + vsize = QSXGA_PLUS3_SIZE_V;
5651 + case SENSOR_RES_WQSXGA:
5653 + hsize = WQSXGA_SIZE_H;
5655 + vsize = WQSXGA_SIZE_V;
5657 + case SENSOR_RES_QUXGA:
5659 + hsize = QUXGA_SIZE_H;
5661 + vsize = QUXGA_SIZE_V;
5663 + case SENSOR_RES_WQUXGA:
5665 + hsize = WQUXGA_SIZE_H;
5667 + vsize = WQUXGA_SIZE_V;
5669 + case SENSOR_RES_HXGA:
5671 + hsize = HXGA_SIZE_H;
5673 + vsize = HXGA_SIZE_V;
5676 + eprintk("resolution not supported");
5677 + return CI_STATUS_NOTSUPP;
5680 + return ci_isp_jpe_init_ex(hsize, vsize, compression_ratio, jpe_scale);
5683 +void ci_isp_jpe_set_tables(u8 compression_ratio)
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;
5690 + const u8 *yqtable = NULL;
5691 + const u8 *uvqtable = NULL;
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;
5698 + case CI_ISP_JPEG_01_PERCENT:
5699 + yqtable = ci_isp_yq_table01_per_cent;
5700 + uvqtable = ci_isp_uv_qtable01_per_cent;
5702 + case CI_ISP_JPEG_20_PERCENT:
5703 + yqtable = ci_isp_yq_table20_per_cent;
5704 + uvqtable = ci_isp_uv_qtable20_per_cent;
5706 + case CI_ISP_JPEG_30_PERCENT:
5707 + yqtable = ci_isp_yq_table30_per_cent;
5708 + uvqtable = ci_isp_uv_qtable30_per_cent;
5710 + case CI_ISP_JPEG_40_PERCENT:
5711 + yqtable = ci_isp_yq_table40_per_cent;
5712 + uvqtable = ci_isp_uv_qtable40_per_cent;
5714 + case CI_ISP_JPEG_50_PERCENT:
5715 + yqtable = ci_isp_yq_table50_per_cent;
5716 + uvqtable = ci_isp_uv_qtable50_per_cent;
5718 + case CI_ISP_JPEG_60_PERCENT:
5719 + yqtable = ci_isp_yq_table60_per_cent;
5720 + uvqtable = ci_isp_uv_qtable60_per_cent;
5722 + case CI_ISP_JPEG_70_PERCENT:
5723 + yqtable = ci_isp_yq_table70_per_cent;
5724 + uvqtable = ci_isp_uv_qtable70_per_cent;
5726 + case CI_ISP_JPEG_80_PERCENT:
5727 + yqtable = ci_isp_yq_table80_per_cent;
5728 + uvqtable = ci_isp_uv_qtable80_per_cent;
5730 + case CI_ISP_JPEG_90_PERCENT:
5731 + yqtable = ci_isp_yq_table90_per_cent;
5732 + uvqtable = ci_isp_uv_qtable90_per_cent;
5734 + case CI_ISP_JPEG_99_PERCENT:
5735 + yqtable = ci_isp_yq_table99_per_cent;
5736 + uvqtable = ci_isp_uv_qtable99_per_cent;
5738 + case CI_ISP_JPEG_HIGH_COMPRESSION:
5741 + * in the case an unknown value is set,
5742 + * use CI_JPEG_HIGH_COMPRESSION
5744 + yqtable = ci_isp_yq_table75_per_cent;
5745 + uvqtable = ci_isp_uv_qtable75_per_cent;
5749 + /* Y q-table 0 programming */
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,
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);
5765 + /* U/V q-table 0 programming */
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,
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);
5781 + /* Y AC-table 0 programming */
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);
5797 + /* U/V AC-table 1 programming */
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);
5813 + /* Y DC-table 0 programming */
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);
5829 + /* U/V DC-table 1 programming */
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);
5847 + * selects tables to be used by encoder
5849 +void ci_isp_jpe_select_tables(void)
5851 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
5879 + * configure JPEG encoder
5881 +void ci_isp_jpe_set_config(u16 hsize, u16 vsize, int jpe_scale)
5883 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5885 + /* JPEG image size */
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);
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,
5894 + REG_SET_SLICE(mrv_reg->jpe_cbcr_scale_en,
5895 + MRV_JPE_CBCR_SCALE_EN, ENABLE);
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);
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);
5910 +int ci_isp_jpe_generate_header(struct mrst_isp_device *intel, u8 header_mode)
5912 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5914 + WARN_ON(!((header_mode == MRV_JPE_HEADER_MODE_JFIF)
5915 + || (header_mode == MRV_JPE_HEADER_MODE_NO)));
5917 + /* clear jpeg gen_header_done interrupt */
5918 + /* since we poll them later to detect command completion */
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,
5924 + /* start header generation */
5925 + REG_SET_SLICE(mrv_reg->jpe_gen_header, MRV_JPE_GEN_HEADER, ON);
5927 + return ci_isp_jpe_wait_for_header_gen_done(intel);
5930 +void ci_isp_jpe_prep_enc(enum ci_isp_jpe_enc_mode jpe_enc_mode)
5932 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5933 + u32 jpe_encode = REG_READ(mrv_reg->jpe_encode);
5935 + /* clear jpeg encode_done interrupt */
5936 + /* since we poll them later to detect command completion */
5938 + REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ENCODE_DONE, 1);
5939 + REG_SET_SLICE(jpe_encode, MRV_JPE_ENCODE, ON);
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);
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);
5953 + /* single shot JPEG */
5954 + REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE,
5955 + MRV_JPE_CONT_MODE_STOP);
5959 + REG_WRITE(mrv_reg->jpe_encode, jpe_encode);
5960 + REG_SET_SLICE(mrv_reg->jpe_init, MRV_JPE_JP_INIT, 1);
5964 + * wait until JPG Header is generated (MRV_JPGINT_GEN_HEADER_DONE
5965 + * interrupt occurs)
5966 + * waiting for JPG Header to be generated
5968 +int ci_isp_jpe_wait_for_header_gen_done(struct mrst_isp_device *intel)
5970 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
5972 + mrst_timer_start();
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;
5983 + mrst_timer_stop();
5985 + return CI_STATUS_SUCCESS;
5989 + * wait until JPG Encoder is done (MRV_JPGINT_ENCODE_DONE
5990 + * interrupt occurs) waiting for the JPG Encoder to be done
5992 +int ci_isp_jpe_wait_for_encode_done(struct mrst_isp_device *intel)
5996 + INIT_COMPLETION(intel->jpe_complete);
5997 + ret = wait_for_completion_interruptible_timeout(&intel->jpe_complete,
5999 + if ((ret == 0) | (intel->irq_stat == IRQ_JPE_ERROR)) {
6000 + eprintk("timeout");
6001 + return CI_STATUS_FAILURE;
6004 + return CI_STATUS_SUCCESS;
6006 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
6007 + mrst_timer_start();
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;
6018 + mrst_timer_stop();
6020 + /* clear jpeg encode_done interrupt */
6021 + REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ENCODE_DONE, 1);
6023 + return CI_STATUS_SUCCESS;
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
6029 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_main.c
6032 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
6034 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
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.
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.
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.
6051 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
6054 +#include "mrstisp_stdinc.h"
6055 +#include "ci_isp_fmts_common.h"
6057 +#define GPIO_SCLK_25 44
6058 +#define GPIO_STDBY1_PIN 48
6059 +#define GPIO_STDBY2_PIN 49
6060 +#define GPIO_RESET_PIN 50
6063 +module_param(mrstisp_debug, int, 0644);
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;
6074 +void intel_timer_start(void)
6076 + jiffies_start = jiffies;
6078 +void intel_timer_stop(void)
6080 + jiffies_start = 0;
6082 +unsigned long intel_get_micro_sec(void)
6084 + unsigned long time_diff = 0;
6086 + time_diff = jiffies - jiffies_start;
6088 + return jiffies_to_msecs(time_diff);
6092 +static inline struct mrst_isp_device *to_isp(struct v4l2_device *dev)
6094 + return container_of(dev, struct mrst_isp_device, v4l2_dev);
6097 +static struct mrst_camera mrst_camera_table[] = {
6099 + .type = MRST_CAMERA_SOC,
6101 + .sensor_addr = 0x30,
6104 + .type = MRST_CAMERA_SOC,
6106 + .sensor_addr = 0x30,
6109 + .type = MRST_CAMERA_RAW,
6111 + .sensor_addr = 0x36,
6112 + .motor_name = "ov5630_motor",
6113 + .motor_addr = (0x18 >> 1),
6116 + .type = MRST_CAMERA_RAW,
6118 + .sensor_addr = 0x36,
6119 + .motor_name = "s5k4e1_motor",
6120 + .motor_addr = (0x18 >> 1),
6124 +#define N_CAMERA (ARRAY_SIZE(mrst_camera_table))
6126 +struct videobuf_dma_contig_memory {
6129 + dma_addr_t dma_handle;
6130 + unsigned long size;
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)); \
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;
6143 +static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd)
6145 + return container_of(sd, struct ci_sensor_config, sd);
6148 +/* g45-th20-b5 gamma out curve with enhanced black level */
6149 +static struct ci_isp_gamma_out_curve g45_th20_b5 = {
6151 + 0x0000, 0x0014, 0x003C, 0x0064,
6152 + 0x00A0, 0x0118, 0x0171, 0x01A7,
6153 + 0x01D8, 0x0230, 0x027A, 0x02BB,
6154 + 0x0323, 0x0371, 0x03AD, 0x03DB,
6160 +static void print_snr_cfg(struct ci_sensor_config *cfg)
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);
6188 +static int mrst_isp_defcfg_all_load(struct ci_isp_config *isp_config)
6193 + /* demosaic mode */
6194 + isp_config->demosaic_mode = CI_ISP_DEMOSAIC_ENHANCED;
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;
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;
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;
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;
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;
6270 + isp_config->color.contrast = 128;
6271 + isp_config->color.brightness = 0;
6272 + isp_config->color.saturation = 128;
6273 + isp_config->color.hue = 0;
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;
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;
6317 + isp_config->view_finder.flags = VFFLAG_HWRGB;
6319 + isp_config->afm_mode = 1;
6320 + isp_config->filter_level_noise_reduc = 4;
6321 + isp_config->filter_level_sharp = 4;
6323 + isp_config->jpeg_enc_ratio = 1;
6329 +static void mrst_isp_update_marvinvfaddr(struct mrst_isp_device *isp,
6331 + enum ci_isp_conf_update_time update_time)
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;
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));
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;
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;
6353 + if (isp->sys_conf.jpg_review_enable) {
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;
6360 + bufsize = jpg_review->width * jpg_review->height;
6362 + /* buffer size in bytes */
6363 + if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV420
6364 + || jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420) {
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;
6371 + } else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV422P) {
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;
6378 + } else if (jpg_review->pix_fmt == V4L2_PIX_FMT_NV12) {
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;
6386 + printk(KERN_ERR "mrstisp: no support jpg review fmt\n");
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;
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;
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;
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;
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) {
6425 + bufsize = isp->frame_size;
6427 + /* buffer size in bytes */
6428 + if (isp->pixelformat == V4L2_PIX_FMT_YUV420
6429 + || isp->pixelformat == V4L2_PIX_FMT_YVU420) {
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) {
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) {
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;
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;
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;
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;
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;
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;
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);
6489 + ci_isp_mif_set_self_buffer(&isp_mi_path_conf, update_time);
6493 +static int mrst_isp_setup_viewfinder_path(struct mrst_isp_device *isp,
6494 + struct ci_sensor_config *isi_config,
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;
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;
6511 + if (sys_conf->isp_cfg.flags.ycbcr_full_range)
6512 + jpe_scale = false;
6516 + memset(&dp_main, 0, sizeof(struct ci_isp_datapath_desc));
6517 + memset(&dp_self, 0, sizeof(struct ci_isp_datapath_desc));
6521 + self_rect.w = isp->bufwidth; /* 640 */
6522 + self_rect.h = isp->bufheight; /* 480 */
6524 + if (isp->pixelformat == V4L2_PIX_FMT_JPEG) {
6526 + dprintk(1, "jpeg fmt");
6528 + dp_main.flags = CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPJPEG;
6529 + config->view_finder.flags |= VFFLAG_USE_MAINPATH;
6531 + dp_main.out_w = (u16) isp->bufwidth;
6532 + dp_main.out_h = (u16) isp->bufheight;
6534 + if (isp->sys_conf.jpg_review_enable) {
6536 + dprintk(1, "jpg_review enabled in VF");
6538 + self_rect.w = jpg_review->width;
6539 + self_rect.h = jpg_review->height;
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;
6555 + dprintk(1, "dp_self.flags is 0x%x", dp_self.flags);
6558 + } else if (isp->pixelformat == INTEL_PIX_FMT_RAW08) {
6560 + dp_main.flags = CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPRAW;
6561 + config->view_finder.flags |= VFFLAG_USE_MAINPATH;
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));
6568 + dprintk(1, "RAW08 dp_main.flags is 0x%x", dp_main.flags);
6570 + } else if (isp->pixelformat == INTEL_PIX_FMT_RAW10
6571 + || isp->pixelformat == INTEL_PIX_FMT_RAW12) {
6573 + dp_main.flags = (CI_ISP_DPD_ENABLE
6574 + | CI_ISP_DPD_MODE_ISPRAW_16B);
6575 + config->view_finder.flags |= VFFLAG_USE_MAINPATH;
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));
6582 + dprintk(1, "RAW10 dp_main.flags is 0x%x", dp_main.flags);
6584 + } /*else if (isp->bufwidth >= 640 && isp->bufheight >= 480) {*/
6585 + else if (isp->bufwidth >= 32 && isp->bufheight >= 16) {
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;
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;
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;
6605 + dprintk(1, "YUV dp_main.flags is 0x%x", dp_main.flags);
6607 + } /* else if (isp->bufwidth <= 640 && isp->bufheight <= 480) {
6609 + dp_self.flags = (CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPYC);
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;
6626 + dprintk(1, "YUV dp_self.flags is 0x%x", dp_self.flags);
6630 + dprintk(1, "sensor_res = %x", isi_config->res);
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);
6638 + /* no stretching/squeezing */
6639 + if (dp_self.flags && CI_ISP_DPD_ENABLE)
6640 + dp_self.flags |= CI_ISP_DPD_KEEPRATIO;
6642 + dp_main.flags |= CI_ISP_DPD_KEEPRATIO;
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;
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;
6656 + if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_MIRROR)
6657 + dp_self.flags |= CI_ISP_DPD_H_FLIP;
6660 + if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_V_FLIP)
6661 + dp_self.flags |= CI_ISP_DPD_V_FLIP;
6664 + if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_ROT90_CCW)
6665 + dp_self.flags |= CI_ISP_DPD_90DEG_CCW;
6667 + /* setup self & main path with zoom */
6669 + zoom = sys_conf->isp_cfg.view_finder.zoom;
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)
6685 + /* to use crop mode, set crop_flag */
6687 + dp_main.flags |= CI_ISP_DPD_NORESIZE;
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");
6699 +static int mrst_isp_init_mrv_image_effects(struct ci_pl_system_config *sys_conf,
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");
6712 + (void)ci_isp_ie_set_config(NULL);
6713 + res = CI_STATUS_SUCCESS;
6720 +static int mrst_isp_init_mrvisp_lensshade(struct ci_pl_system_config *sys_conf,
6724 + ci_isp_set_ls_correction(&sys_conf->isp_cfg.lsc_cfg);
6725 + ci_isp_ls_correction_on_off(1);
6727 + ci_isp_ls_correction_on_off(0);
6729 + return CI_STATUS_SUCCESS;
6732 +static int mrst_isp_init_mrvisp_badpixel(const struct ci_pl_system_config
6733 + *sys_conf, int enable)
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);
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);
6743 + return CI_STATUS_SUCCESS;
6746 +static int mrst_isp_init_mrv_ispfilter(const struct ci_pl_system_config
6747 + *sys_conf, int enable)
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");
6762 + ci_isp_activate_filter(false);
6763 + res = CI_STATUS_SUCCESS;
6770 +static int mrst_isp_init_mrvisp_cac(const struct ci_pl_system_config *sys_conf,
6776 +static int mrst_isp_initbls(const struct ci_pl_system_config *sys_conf)
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);
6783 +static int mrst_isp_dp_init(struct ci_pl_system_config *sys_conf,
6784 + struct ci_sensor_config *isi_config)
6787 + u8 words_per_pixel;
6791 + /* base initialisation of Marvin */
6794 + /* setup input acquisition according to image sensor settings */
6795 + print_snr_cfg(isi_config);
6796 + error = ci_isp_set_input_aquisition(isi_config);
6798 + printk(KERN_ERR "mrstisp: error setting input acquisition\n");
6802 + /* setup functional blocks for Bayer pattern processing */
6803 + if (ci_isp_select_path(isi_config, &words_per_pixel)
6804 + == CI_ISP_PATH_BAYER) {
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");
6814 + ci_isp_bls_set_config(NULL);
6818 + if (sys_conf->isp_cfg.flags.gamma2) {
6819 + dprintk(1, "setting gamma 2 ");
6820 + ci_isp_set_gamma2(&g45_th20_b5);
6822 + dprintk(1, "no setting gamma 2 ");
6823 + ci_isp_set_gamma2(NULL);
6827 + ci_isp_set_demosaic(sys_conf->isp_cfg.demosaic_mode,
6828 + sys_conf->isp_cfg.demosaic_th);
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");
6845 + if (sys_conf->isp_cfg.flags.af)
6846 + ci_isp_set_auto_focus(&sys_conf->isp_cfg.af_cfg);
6848 + ci_isp_set_auto_focus(NULL);
6851 + mrst_isp_init_mrv_ispfilter(sys_conf, true);
6854 + mrst_isp_init_mrvisp_cac(sys_conf, true);
6858 + * disable color processing for now (will be set under user control
6859 + * in the main loop)
6861 + ci_isp_col_set_color_processing(NULL);
6863 + /* configure image effects */
6864 + mrst_isp_init_mrv_image_effects(sys_conf, true);
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);
6873 + mrst_isp_init_mrvisp_lensshade(sys_conf,
6874 + sys_conf->isp_cfg.flags.lsc);
6876 + /* configure bad pixel detection/correction */
6877 + mrst_isp_init_mrvisp_badpixel(sys_conf, true);
6880 + return CI_STATUS_SUCCESS;
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)
6887 + u32 mipi_data_id = 1;
6888 + struct isp_register *mrv_reg =
6889 + (struct isp_register *) MEM_MRV_REG_BASE;
6891 + ci_isp_jpe_prep_enc(mrv_jpe_encMode);
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);
6897 + while (mipi_data_id)
6899 + REG_READ_EX(mrv_reg->mipi_cur_data_id);
6903 + ci_isp_start(1, update_time);
6905 + return ci_isp_jpe_wait_for_encode_done(intel);
6908 +/* capture one frame */
6909 +u32 ci_jpe_capture(struct mrst_isp_device *isp,
6910 + enum ci_isp_conf_update_time update_time)
6912 + int retval = CI_STATUS_SUCCESS;
6914 + /* generate header */
6915 + retval = ci_isp_jpe_generate_header(isp, MRV_JPE_HEADER_MODE_JFIF);
6916 + if (retval != CI_STATUS_SUCCESS)
6919 + /* now encode JPEG */
6920 + retval = ci_jpe_encode(isp, update_time, CI_ISP_JPE_SINGLE_SHOT);
6921 + if (retval != CI_STATUS_SUCCESS)
6924 + /* return ci_isp_mif_get_byte_cnt(); */
6928 +static int mrst_ci_capture(struct mrst_isp_device *isp)
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;
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);
6940 + ci_isp_reset_interrupt_status();
6941 + mrst_isp_enable_interrupt(isp);
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,
6948 + ci_jpe_capture(isp, CI_ISP_CFG_UPDATE_FRAME_SYNC);
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;
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);
6966 + /* update captured frame status */
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);
6980 + v4l2_subdev_call(isp->sensor_curr, video, s_stream, 1);
6982 + while (mipi_data_id) {
6984 + REG_READ_EX(mrv_reg->mipi_cur_data_id);
6985 + dprintk(5, "mipi_cur_data_id = %x",
6991 + ci_isp_start(0, CI_ISP_CFG_UPDATE_FRAME_SYNC);
6996 +static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
6997 + unsigned int *size)
6999 + struct mrst_isp_fh *fh = vq->priv_data;
7000 + struct mrst_isp_device *isp = fh->dev;
7002 + u32 w = isp->bufwidth;
7003 + u32 h = isp->bufheight;
7004 + u32 depth = isp->depth;
7005 + u32 fourcc = isp->pixelformat;
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;
7016 + *size = (w * h * depth)/8;
7019 + isp->frame_size = *size;
7020 + isp->num_frames = *count;
7025 + while (*size * *count > isp->mb1_size)
7028 + dprintk(1, "count=%d, size=%d", *count, *size);
7032 +static void free_buffer(struct videobuf_queue *vq, struct mrst_isp_buffer *buf)
7034 + struct videobuf_buffer *vb = &buf->vb;
7036 + dprintk(1, "(vb=0x%p) baddr = 0x%08lx bsize = %d", vb,
7037 + vb->baddr, vb->bsize);
7039 + videobuf_dma_contig_free(vq, vb);
7041 + buf->vb.state = VIDEOBUF_NEEDS_INIT;
7042 + dprintk(1, "free_buffer: freed");
7045 +static int buffer_prepare(struct videobuf_queue *vq,
7046 + struct videobuf_buffer *vb, enum v4l2_field field)
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,
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;
7063 + vb->size = isp->frame_size;
7065 + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
7066 + ret = videobuf_iolock(vq, vb, NULL);
7069 + vb->state = VIDEOBUF_PREPARED;
7075 + printk(KERN_ERR "mrstisp: error calling videobuf_iolock");
7076 + free_buffer(vq, buf);
7080 +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
7082 + struct mrst_isp_fh *fh = vq->priv_data;
7083 + struct mrst_isp_device *isp = fh->dev;
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); */
7099 + mrst_isp_enable_interrupt(isp);
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);
7109 + isp->stopflag = 0;
7110 + } else if (!isp->active) {
7111 + dprintk(1, "no active queue");
7113 + isp->active->state = VIDEOBUF_ACTIVE;
7114 + mrst_isp_to_do_mblk_line = 1;
7115 + mrst_ci_capture(isp);
7117 + dprintk(1, "capture to active queue");
7118 + list_add_tail(&vb->queue, &isp->capture);
7124 +static void buffer_release(struct videobuf_queue *vq,
7125 + struct videobuf_buffer *vb)
7127 + struct mrst_isp_buffer *buf = container_of(vb,
7128 + struct mrst_isp_buffer, vb);
7130 + free_buffer(vq, buf);
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,
7141 +static int mrst_isp_open(struct file *file)
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;
7152 + printk(KERN_ERR "null in mrst_isp_open\n");
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;
7163 + dprintk(0, "cur sensor raw");
7164 + isp->sensor_curr = isp->sensor_raw;
7169 + ret = v4l2_subdev_call(isp->sensor_curr, video, g_fmt,
7172 + printk(KERN_ERR "can't get current pix from sensor!\n");
7177 + dprintk(1, "current sensor format: %d x %d",
7178 + sensor_format.fmt.pix.width,
7179 + sensor_format.fmt.pix.height);
7181 + fh = kzalloc(sizeof(*fh), GFP_KERNEL);
7183 + printk(KERN_ERR "no mem for fh \n");
7188 + file->private_data = fh;
7191 + videobuf_queue_dma_contig_init(&fh->vb_q, &mrst_isp_videobuf_qops,
7192 + vdev->parent, &isp->lock,
7193 + V4L2_BUF_TYPE_VIDEO_CAPTURE,
7195 + sizeof(struct mrst_isp_buffer), fh);
7198 + mutex_unlock(&isp->mutex);
7203 +static int mrst_isp_close(struct file *file)
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;
7211 + mutex_lock(&isp->mutex);
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;
7221 + spin_lock_irqsave(&isp->lock, flags);
7222 + INIT_LIST_HEAD(&isp->capture);
7223 + isp->active = NULL;
7225 + isp->sys_conf.isp_hal_enable = 0;
7226 + isp->sys_conf.jpg_review_enable = 0;
7227 + spin_unlock_irqrestore(&isp->lock, flags);
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;
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);
7239 + kfree(file->private_data);
7241 + mutex_unlock(&isp->mutex);
7244 + if (isp->open == 0)
7251 +static ssize_t mrst_isp_read(struct file *file, char __user *buf,
7252 + size_t count, loff_t *ppos)
7257 +static void mrst_isp_videobuf_vm_open(struct vm_area_struct *vma)
7259 + struct videobuf_mapping *map = vma->vm_private_data;
7261 + dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
7262 + map, map->count, vma->vm_start, vma->vm_end);
7267 +static void mrst_isp_videobuf_vm_close(struct vm_area_struct *vma)
7269 + struct videobuf_mapping *map = vma->vm_private_data;
7270 + struct videobuf_queue *q = map->q;
7273 + dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
7274 + map, map->count, vma->vm_start, vma->vm_end);
7277 + if (0 == map->count) {
7278 + struct videobuf_dma_contig_memory *mem;
7280 + dprintk(2, "munmap %p q=%p\n", map, q);
7281 + mutex_lock(&q->vb_lock);
7283 + /* We need first to cancel streams, before unmapping */
7285 + videobuf_queue_cancel(q);
7287 + for (i = 0; i < VIDEO_MAX_FRAME; i++) {
7288 + if (NULL == q->bufs[i])
7291 + if (q->bufs[i]->map != map)
7294 + mem = q->bufs[i]->priv;
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.
7302 + MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
7304 + /* vfree is not atomic - can't be
7305 + called with IRQ's disabled
7307 + dprintk(2, "buf[%d] freeing %p\n",
7311 + dma_free_coherent(q->dev, mem->size,
7312 + mem->vaddr, mem->dma_handle);
7314 + mem->vaddr = NULL;
7317 + q->bufs[i]->map = NULL;
7318 + q->bufs[i]->baddr = 0;
7323 + mutex_unlock(&q->vb_lock);
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,
7332 +static int mrst_isp_mmap_mapper(struct videobuf_queue *q,
7333 + struct vm_area_struct *vma)
7335 + struct videobuf_dma_contig_memory *mem;
7336 + struct videobuf_mapping *map;
7337 + unsigned int first;
7339 + unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT;
7341 + struct mrst_isp_fh *fh = q->priv_data;
7342 + struct mrst_isp_device *isp = fh->dev;
7346 + if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
7349 + /* look for first buffer to map */
7350 + for (first = 0; first < VIDEO_MAX_FRAME; first++) {
7351 + if (!q->bufs[first])
7354 + if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
7356 + if (q->bufs[first]->boff == offset) {
7357 + dprintk(1, "buff id %d is mapped", first);
7361 + if (VIDEO_MAX_FRAME == first) {
7362 + eprintk("invalid user space offset [offset=0x%lx]", offset);
7366 + /* create mapping + update buffer list */
7367 + map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
7371 + q->bufs[first]->map = map;
7372 + map->start = vma->vm_start;
7373 + map->end = vma->vm_end;
7376 + q->bufs[first]->baddr = vma->vm_start;
7378 + mem = q->bufs[first]->priv;
7380 + MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
7382 + mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
7383 + mem->dma_handle = isp->mb1 + (mem->size * first);
7384 + mem->vaddr = (void *)0x1;
7386 + mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
7387 + &mem->dma_handle, GFP_KERNEL);
7389 + if (mem->size > isp->mb1_size) {
7390 + eprintk("to big size, can not be mmapped");
7394 + /* Try to remap memory */
7396 + size = vma->vm_end - vma->vm_start;
7397 + size = (size < mem->size) ? size : mem->size;
7399 + dprintk(1, "vm_end - vm_start = %ld, mem-size = %ld", size, mem->size);
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);
7406 + eprintk("mmap: remap failed with error %d. ", retval);
7410 + vma->vm_ops = &mrst_isp_videobuf_vm_ops;
7411 + vma->vm_flags |= VM_DONTEXPAND;
7412 + vma->vm_private_data = map;
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);
7419 + mrst_isp_videobuf_vm_open(vma);
7427 +int mrst_isp_videobuf_mmap_mapper(struct videobuf_queue *q,
7428 + struct vm_area_struct *vma)
7430 + MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
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);
7440 +static int mrst_isp_mmap(struct file *file, struct vm_area_struct *vma)
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;
7453 + /* temporarily put here */
7454 + if (isp->open > 1) {
7455 + printk(KERN_ERR "ISP already opened...");
7459 + fh = file->private_data;
7461 + if (!(vma->vm_flags & (VM_WRITE | VM_READ))
7462 + || !(vma->vm_flags & VM_SHARED)) {
7463 + printk(KERN_ERR "mrstisp: wrong vma flag");
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 ----");
7471 + map_by_myself = 1;
7472 + } else if (offset == 0 && size == isp->mb1_size) {
7473 + dprintk(1, "---- map bar1 ----");
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;
7483 + dprintk(1, "----map one certain buffer----");
7484 + map_by_myself = 0;
7487 + if (map_by_myself) {
7488 + vma->vm_flags |= VM_IO;
7489 + vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
7491 + page = page >> PAGE_SHIFT;
7493 + if (remap_pfn_range(vma, vma->vm_start, page, size,
7495 + printk(KERN_ERR "fail to put MMAP buffer to user space\n");
7502 + if (size > isp->num_frames * PAGE_ALIGN(isp->frame_size)) {
7503 + eprintk("length is larger than num * size");
7507 + ret = mrst_isp_videobuf_mmap_mapper(&fh->vb_q, vma);
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);
7517 +static int mrst_isp_g_fmt_cap(struct file *file, void *priv,
7518 + struct v4l2_format *f)
7520 + struct video_device *dev = video_devdata(file);
7521 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7524 + WARN_ON(priv != file->private_data);
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;
7540 + dprintk(1, "get fmt %d x %d ", f->fmt.pix.width, f->fmt.pix.height);
7545 +static struct intel_fmt *fmt_by_fourcc(unsigned int fourcc)
7549 + for (i = 0; i < NUM_FORMATS; i++)
7550 + if (fmts[i].fourcc == fourcc)
7555 +static int mrst_isp_try_fmt_cap(struct file *file, void *priv,
7556 + struct v4l2_format *f)
7558 + struct video_device *dev = video_devdata(file);
7559 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7561 + struct intel_fmt *fmt;
7565 + WARN_ON(priv != file->private_data);
7569 + mutex_lock(&isp->mutex);
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");
7578 + w = f->fmt.pix.width;
7579 + h = f->fmt.pix.height;
7581 + dprintk(1, "sensor name %s: before w = %d, h = %d",
7582 + isp->sensor_curr->name, w, h);
7584 + ret = v4l2_subdev_call(isp->sensor_curr, video, try_fmt, f);
7589 + w = f->fmt.pix.width;
7590 + h = f->fmt.pix.height;
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;
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;
7615 + f->fmt.pix.width = w;
7616 + f->fmt.pix.height = h;
7618 + f->fmt.pix.field = V4L2_FIELD_NONE;
7619 + f->fmt.pix.bytesperline = (w * h)/8;
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;
7626 + dprintk(3, "after w = %d, h = %d", w, h);
7630 + mutex_unlock(&isp->mutex);
7636 +static int mrst_isp_s_fmt_cap(struct file *file, void *priv,
7637 + struct v4l2_format *f)
7639 + struct video_device *dev = video_devdata(file);
7640 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7641 + struct intel_fmt *fmt;
7643 + unsigned int width_o, height_o;
7644 + unsigned short width_sensor, height_sensor;
7645 + unsigned int w, h;
7647 + WARN_ON(priv != file->private_data);
7653 + w = f->fmt.pix.width;
7654 + h = f->fmt.pix.height;
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;
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;
7679 + f->fmt.pix.width = w;
7680 + f->fmt.pix.height = h;
7682 + width_o = f->fmt.pix.width;
7683 + height_o = f->fmt.pix.height;
7685 + (void)ci_sensor_res2size(to_sensor_config(isp->sensor_curr)->res,
7686 + &width_sensor, &height_sensor);
7688 + ret = mrst_isp_try_fmt_cap(file, priv, f);
7690 + printk(KERN_ERR "mrstisp: set format failed\n");
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);
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);
7707 + isp->pixelformat = fmt->fourcc;
7708 + isp->depth = fmt->depth;
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;
7722 + isp->bufwidth = f->fmt.pix.width;
7723 + isp->bufheight = f->fmt.pix.height;
7727 + * check if buf res is larger than
7728 + * sensor real res(1304x980)
7729 + * if yes, down buf res to VGA
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;
7739 + mutex_unlock(&isp->mutex);
7741 + dprintk(1, "----------set fmt only to isp: w %d, h%d, "
7742 + "fourcc: %lx", isp->bufwidth,
7743 + isp->bufheight, fmt->fourcc);
7746 + /* set fmt for both isp and sensor */
7747 + mutex_lock(&isp->mutex);
7748 + fmt = fmt_by_fourcc(f->fmt.pix.pixelformat);
7750 + isp->pixelformat = fmt->fourcc;
7751 + isp->depth = fmt->depth;
7752 + isp->bufwidth = width_o;
7753 + isp->bufheight = height_o;
7755 + mutex_unlock(&isp->mutex);
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);
7762 + ret = v4l2_subdev_call(isp->sensor_curr, video, s_fmt, f);
7769 +static int mrst_isp_enum_framesizes(struct file *file, void *priv,
7770 + struct v4l2_frmsizeenum *arg)
7772 + struct video_device *dev = video_devdata(file);
7773 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7778 + WARN_ON(priv != file->private_data);
7780 + ret = v4l2_subdev_call(isp->sensor_curr, video, enum_framesizes, arg);
7786 +static int mrst_isp_enum_frameintervals(struct file *file, void *priv,
7787 + struct v4l2_frmivalenum *arg)
7789 + struct video_device *dev = video_devdata(file);
7790 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7795 + WARN_ON(priv != file->private_data);
7797 + ret = v4l2_subdev_call(isp->sensor_curr, video, enum_frameintervals,
7803 +static int mrst_isp_queryctrl(struct file *file, void *priv,
7804 + struct v4l2_queryctrl *c)
7806 + struct video_device *vdev = video_devdata(file);
7807 + struct mrst_isp_device *isp = video_get_drvdata(vdev);
7809 + WARN_ON(priv != file->private_data);
7813 + if (!v4l2_subdev_call(isp->sensor_curr, core, queryctrl, c))
7815 + else if (!v4l2_subdev_call(isp->motor, core, queryctrl, c))
7818 + /* No controls supported */
7822 +static int mrst_isp_g_ctrl(struct file *file, void *priv,
7823 + struct v4l2_control *c)
7825 + struct video_device *dev = video_devdata(file);
7826 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7829 + WARN_ON(priv != file->private_data);
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);
7837 + ret = v4l2_subdev_call(isp->sensor_curr, core, g_ctrl, c);
7838 + dprintk(2, "get other cotrol from senrsor : %d", c->value);
7843 +static int mrst_isp_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
7845 + struct video_device *dev = video_devdata(file);
7846 + struct mrst_isp_device *isp = video_get_drvdata(dev);
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);
7854 + dprintk(2, "setting other ctrls, value = %d", c->value);
7855 + return v4l2_subdev_call(isp->sensor_curr, core, s_ctrl, c);
7859 +static int mrst_isp_index_to_camera(struct mrst_isp_device *isp, u32 index)
7861 + int camera = MRST_CAMERA_NONE;
7863 + if (isp->sensor_soc && isp->sensor_raw) {
7866 + camera = isp->sensor_soc_index;
7869 + camera = isp->sensor_raw_index;
7872 + } else if (isp->sensor_soc) {
7875 + camera = isp->sensor_soc_index;
7878 + } else if (isp->sensor_raw) {
7881 + camera = isp->sensor_raw_index;
7889 +static int mrst_isp_enum_input(struct file *file, void *priv,
7890 + struct v4l2_input *i)
7892 + struct video_device *vdev = video_devdata(file);
7893 + struct mrst_isp_device *isp = video_get_drvdata(vdev);
7898 + WARN_ON(priv != file->private_data);
7900 + camera = mrst_isp_index_to_camera(isp, i->index);
7901 + if (MRST_CAMERA_NONE == camera)
7904 + i->type = V4L2_INPUT_TYPE_CAMERA;
7905 + i->std = V4L2_STD_UNKNOWN;
7906 + strcpy(i->name, mrst_camera_table[camera].name);
7911 +static int mrst_isp_g_input(struct file *file, void *priv, unsigned int *i)
7913 + struct video_device *vdev = video_devdata(file);
7914 + struct mrst_isp_device *isp = video_get_drvdata(vdev);
7918 + WARN_ON(priv != file->private_data);
7920 + if (isp->sensor_soc && isp->sensor_raw)
7921 + if (isp->sensor_curr == isp->sensor_soc)
7932 +static int mrst_isp_s_input(struct file *file, void *priv, unsigned int i)
7934 + struct video_device *vdev = video_devdata(file);
7935 + struct mrst_isp_device *isp = video_get_drvdata(vdev);
7941 + if (isp->streaming) {
7942 + printk(KERN_WARNING "VIDIOC_S_INPUT error: ISP is streaming\n");
7946 + camera = mrst_isp_index_to_camera(isp, i);
7947 + if (MRST_CAMERA_NONE == camera)
7950 + if (mrst_camera_table[camera].type == MRST_CAMERA_SOC)
7951 + isp->sensor_curr = isp->sensor_soc;
7953 + isp->sensor_curr = isp->sensor_raw;
7955 + dprintk(1, "set sensor %s as input", isp->sensor_curr->name);
7961 +static int mrst_isp_g_ext_ctrls(struct file *file,
7963 + struct v4l2_ext_controls *c)
7965 + struct video_device *dev = video_devdata(file);
7966 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7968 + int ret = -EINVAL;
7972 + if (c->ctrl_class != V4L2_CTRL_CLASS_CAMERA) {
7973 + printk(KERN_ERR "Invalid control class\n");
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");
7990 +static int mrst_isp_s_ext_ctrls(struct file *file, void *fh,
7991 + struct v4l2_ext_controls *c)
7993 + struct video_device *dev = video_devdata(file);
7994 + struct mrst_isp_device *isp = video_get_drvdata(dev);
7996 + int ret = -EINVAL;
8000 + if (c->ctrl_class != V4L2_CTRL_CLASS_CAMERA) {
8001 + printk(KERN_INFO "Invalid control class\n");
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");
8018 +static int mrst_isp_s_std(struct file *filp, void *priv, v4l2_std_id *a)
8025 +static int mrst_isp_querycap(struct file *file, void *priv,
8026 + struct v4l2_capability *cap)
8028 + struct video_device *dev = video_devdata(file);
8032 + strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
8033 + strlcpy(cap->card, dev->name, sizeof(cap->card));
8035 + cap->version = INTEL_VERSION(0, 5, 0);
8036 + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
8043 +static int mrst_isp_cropcap(struct file *file, void *priv,
8044 + struct v4l2_cropcap *cap)
8046 + struct video_device *dev = video_devdata(file);
8047 + struct mrst_isp_device *isp = video_get_drvdata(dev);
8049 + WARN_ON(priv != file->private_data);
8053 + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
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;
8069 +static int mrst_isp_enum_fmt_cap(struct file *file, void *priv,
8070 + struct v4l2_fmtdesc *f)
8072 + struct video_device *dev = video_devdata(file);
8073 + struct mrst_isp_device *isp = video_get_drvdata(dev);
8075 + unsigned int index;
8081 + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8084 + if (isp->sensor_curr == isp->sensor_soc)
8087 + if (index >= sizeof(fmts) / sizeof(*fmts))
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;
8105 +#define ALIGN4(x) ((((long)(x)) & 0x3) == 0)
8107 +static int mrst_isp_reqbufs(struct file *file, void *priv,
8108 + struct v4l2_requestbuffers *req)
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);
8115 + WARN_ON(priv != file->private_data);
8118 + if (req->count == 0)
8122 + * if (req->count > 3)
8126 + if (req->memory != V4L2_MEMORY_MMAP) {
8127 + eprintk("wrong memory type");
8130 + ret = videobuf_reqbufs(&fh->vb_q, req);
8132 + eprintk("err calling videobuf_reqbufs ret = %d", ret);
8135 + isp->buffer_required = 1;
8141 +static int mrst_isp_querybuf(struct file *file, void *priv,
8142 + struct v4l2_buffer *buf)
8145 + struct mrst_isp_fh *fh = file->private_data;
8147 + WARN_ON(priv != file->private_data);
8150 + ret = videobuf_querybuf(&fh->vb_q, buf);
8156 +static int mrst_isp_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
8159 + struct mrst_isp_fh *fh = file->private_data;
8161 + WARN_ON(priv != file->private_data);
8164 + ret = videobuf_qbuf(&fh->vb_q, buf);
8165 + /* identify which video buffer was q-ed */
8167 + fh->qbuf_flag |= (1<<buf->index);
8168 + dprintk(1, "q-ed index = %d", buf->index);
8175 +static int mrst_isp_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
8178 + struct mrst_isp_fh *fh = file->private_data;
8180 + WARN_ON(priv != file->private_data);
8184 + if (frame_cnt == 0) {
8185 + printk(KERN_WARNING "timer start\n");
8186 + intel_timer_start();
8192 + if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8194 + if (b->memory != V4L2_MEMORY_MMAP)
8196 + if (fh->qbuf_flag == 0) {
8197 + dprintk(1, "no buffer can be dq-ed\n");
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 */
8206 + fh->qbuf_flag &= ~(1<<b->index);
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());
8217 + dprintk(1, "dq-ed index = %d", b->index);
8222 +static int mrst_isp_streamon(struct file *file, void *priv,
8223 + enum v4l2_buf_type type)
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);
8232 + if (!isp->buffer_required) {
8233 + eprintk("buffer is not required, can not stream on ");
8237 + dprintk(2, "gamma2 = %d", isp->sys_conf.isp_cfg.flags.gamma2);
8238 + WARN_ON(priv != file->private_data);
8240 + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8243 + mutex_lock(&isp->mutex);
8245 + if (!to_sensor_config(isp->sensor_curr)->mipi_mode)
8246 + v4l2_subdev_call(isp->sensor_curr, video, s_stream, 1);
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);
8252 + ret = videobuf_streamon(&fh->vb_q);
8253 + isp->streaming = 1;
8255 + mutex_unlock(&isp->mutex);
8257 + dprintk(1, "isp->active = %p", isp->active);
8262 +static int mrst_isp_streamoff(struct file *file, void *priv,
8263 + enum v4l2_buf_type type)
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);
8269 + unsigned long flags;
8274 + WARN_ON(priv != file->private_data);
8276 + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
8279 + mutex_lock(&isp->mutex);
8281 + ret = videobuf_streamoff(&fh->vb_q);
8282 + dprintk(1, "ret of videobuf_streamoff = %d", ret);
8283 + isp->streaming = 0;
8285 + spin_lock_irqsave(&isp->lock, flags);
8286 + INIT_LIST_HEAD(&isp->capture);
8287 + isp->active = 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;
8295 + spin_unlock_irqrestore(&isp->lock, flags);
8297 + v4l2_subdev_call(isp->sensor_curr, video, s_stream, 0);
8298 + ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC);
8300 + mutex_unlock(&isp->mutex);
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,
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,
8345 +static struct video_device mrst_isp_vdev = {
8346 + .name = "mrst_isp",
8348 + .fops = &mrst_isp_fops,
8349 + .ioctl_ops = &mrst_isp_ioctl_ops,
8350 + .release = video_device_release_empty,
8353 +static int mrst_ci_sensor_probe(struct mrst_isp_device *isp)
8355 + struct v4l2_subdev *sensor = NULL, *motor = NULL;
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");
8366 + dprintk(1, "got sensor i2c adapter: %s", isp->adapter_sensor->name);
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");
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); */
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);
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);
8397 + sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8398 + isp->adapter_sensor,
8399 + name, name, addr, NULL);
8402 + if (sensor == NULL) {
8403 + dprintk(2, "sensor %s not found", name);
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);
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);
8418 + sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8419 + isp->adapter_sensor,
8420 + name, name, addr, NULL);
8423 + if (sensor == NULL) {
8424 + dprintk(2, "sensor %s not found", name);
8427 + isp->sensor_raw = sensor;
8428 + isp->sensor_raw_index = i;
8429 + dprintk(0, "raw camera sensor %s successfully found",
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);
8438 + motor = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8439 + isp->adapter_sensor,
8440 + name, name, addr, NULL);
8443 + if (motor == NULL)
8444 + dprintk(2, "motor %s not found", name);
8446 + isp->motor = motor;
8447 + dprintk(0, "motor %s successfully found", name);
8452 + if (!isp->sensor_soc && !isp->sensor_raw) {
8453 + dprintk(0, "no camera sensor device attached");
8456 + if (isp->sensor_soc)
8457 + isp->sensor_curr = isp->sensor_soc;
8459 + isp->sensor_curr = isp->sensor_raw;
8464 +static int mrst_ci_flash_probe(struct mrst_isp_device *isp)
8466 + struct v4l2_subdev *flash = NULL;
8467 + char *name = "mrst_camera_flash";
8469 + gpio_request(45, "Camera Flash");
8470 + gpio_direction_output(45, 0);
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");
8478 + dprintk(1, "got flash i2c adapter: %s", isp->adapter_flash->name);
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);
8485 + flash = v4l2_i2c_new_subdev(&isp->v4l2_dev,
8486 + isp->adapter_flash,
8487 + name, name, 0x53, NULL);
8490 + if (flash == NULL) {
8491 + dprintk(0, "no flash IC found\n");
8495 + dprintk(0, "flash IC found");
8500 +static irqreturn_t mrst_isp_irq_handler(int this_irq, void *dev_id)
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;
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;
8517 + u32 jpe_status_irq;
8518 + u32 jpe_error_irq;
8523 + isp_irq = REG_READ_EX(mrv_reg->isp_ris) & isp_mask;
8524 + mi_irq = REG_READ_EX(mrv_reg->mi_ris) & mi_mask;
8526 + mblk_line = REG_READ_EX(mrv_reg->mi_ris) & mblk_line_mask;
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;
8531 + mipi_irq = REG_READ_EX(mrv_reg->mipi_ris) & 0x00f00000;
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);
8537 + if (!(isp_irq | mi_irq | jpe_status_irq | jpe_error_irq | mblk_line
8539 + dprintk(2, "unknown interrupt");
8540 + return IRQ_HANDLED;
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);
8550 + /* Currently we don't reset hardware even error detect */
8551 + dprintk(3, "ISP error IRQ received %x", isp_irq);
8553 + isp_error_flag |= isp_irq;
8554 + return IRQ_HANDLED;
8558 + dprintk(3, "error in mipi_irq %x", mipi_irq);
8560 + mipi_error_flag |= mipi_irq;
8561 + return IRQ_HANDLED;
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");
8568 + if (!(isp->active && !isp->next)) {
8569 + dprintk(3, "wrong isq status");
8571 + dprintk(2, "actie->i = %d", isp->active->i);
8573 + dprintk(2, "actie = NULL");
8575 + dprintk(2, "next->i = %d", isp->next->i);
8577 + dprintk(2, "next = NULL");
8578 + return IRQ_HANDLED;
8581 + spin_lock_irqsave(&isp->lock, flags);
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",
8593 + isp->stopflag = 1;
8594 + dprintk(0, "stop isp");
8597 + mrst_isp_to_do_mblk_line = 0;
8599 + spin_unlock_irqrestore(&isp->lock, flags);
8601 + /* return IRQ_HANDLED; */
8604 + if (mi_irq && isp->pixelformat != V4L2_PIX_FMT_JPEG &&
8605 + !jpe_status_irq) {
8606 + dprintk(1, "view finding case");
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;
8615 + spin_lock_irqsave(&isp->lock, flags);
8617 + /* update captured frame status */
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++;
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);
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",
8638 + mrst_isp_to_do_mblk_line = 1;
8639 + REG_SET_SLICE(mrv_reg->mi_imsc,
8640 + MRV_MI_MBLK_LINE, ON);
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");
8649 + isp->active = isp->next;
8650 + list_del_init(&isp->next->queue);
8652 + dprintk(1, "active = next = %d, next = NULL",
8654 + mrst_isp_to_do_mblk_line = 1;
8655 + REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON);
8658 + spin_unlock_irqrestore(&isp->lock, flags);
8659 + return IRQ_HANDLED;
8662 + if (jpe_status_irq) {
8663 + dprintk(2, "jpeg capture case");
8666 + return IRQ_HANDLED;
8668 + spin_lock_irqsave(&isp->lock, flags);
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;
8678 + dprintk(2, "index =%d, bufsize = %lx", vb->i, vb->size);
8680 + spin_unlock_irqrestore(&isp->lock, flags);
8682 + return IRQ_HANDLED;
8685 + if (jpe_error_irq)
8686 + dprintk(2, "entered jpe_error_irq");
8688 + return IRQ_HANDLED;
8692 +static void __devexit mrst_isp_pci_remove(struct pci_dev *pdev)
8694 + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
8695 + struct mrst_isp_device *isp = to_isp(v4l2_dev);
8699 + ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC);
8700 + mrst_isp_disable_interrupt(isp);
8703 + free_irq(pdev->irq, isp);
8707 + dprintk(2, "isp->vdev = %p", isp->vdev);
8708 + video_unregister_device(isp->vdev);
8711 + dma_release_declared_memory(&pdev->dev);
8713 + iounmap(isp->regs);
8715 + pci_release_regions(pdev);
8717 + pci_disable_device(pdev);
8719 + v4l2_device_unregister(&isp->v4l2_dev);
8726 +static int __devinit mrst_isp_pci_probe(struct pci_dev *pdev,
8727 + const struct pci_device_id *pci_id)
8729 + struct mrst_isp_device *isp;
8730 + unsigned int start = 0;
8731 + unsigned int len = 0;
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");
8744 + /* register v4l2 device */
8745 + ret = v4l2_device_register(&pdev->dev, &isp->v4l2_dev);
8747 + printk(KERN_ERR "mrstisp: fail to register v4l2 device\n");
8748 + goto exit_free_isp;
8751 + /* PCI operations */
8752 + ret = pci_enable_device(pdev);
8754 + printk(KERN_ERR "mrstisp: can't enable isp\n");
8755 + goto exit_unregister_v4l2;
8758 + pci_set_master(pdev);
8760 + ret = pci_request_regions(pdev, "mrst isp");
8762 + printk(KERN_ERR "mrstisp: can't request regions\n");
8763 + goto exit_disable_isp;
8767 + start = isp->mb0 = pci_resource_start(pdev, 0);
8768 + len = isp->mb0_size = pci_resource_len(pdev, 0);
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;
8777 + dprintk(1, "isp mb0 = %lx, mb0_size = %lx, regs = %p",
8778 + isp->mb0, isp->mb0_size, isp->regs);
8781 + start = isp->mb1 = pci_resource_start(pdev, 1);
8782 + len = isp->mb1_size = pci_resource_len(pdev, 1);
8784 + dprintk(1, "isp mb1 = %lx, mb1_size = %lx", isp->mb1, isp->mb1_size);
8786 + ret = dma_declare_coherent_memory(&pdev->dev, start,
8787 + /* start, len - 640 * 480 * 2, */
8792 + | DMA_MEMORY_EXCLUSIVE);
8795 + dprintk(0, "failed to declare dma memory");
8797 + goto exit_iounmap;
8800 + /* init device struct */
8801 + INIT_LIST_HEAD(&isp->capture);
8802 + spin_lock_init(&isp->lock);
8803 + mutex_init(&isp->mutex);
8805 + pci_read_config_word(pdev, PCI_VENDOR_ID, &isp->vendorID);
8806 + pci_read_config_word(pdev, PCI_DEVICE_ID, &isp->deviceID);
8808 + mrst_isp_defcfg_all_load(&isp->sys_conf.isp_cfg);
8810 + isp->bufwidth = 640;
8811 + isp->bufheight = 480;
8813 + isp->pixelformat = V4L2_PIX_FMT_YVU420;
8814 + isp->streaming = 0;
8815 + isp->buffer_required = 0;
8818 + /* probe sensor */
8819 + ret = mrst_ci_sensor_probe(isp);
8821 + dprintk(0, "failed to sensor probe\n");
8822 + goto exit_dma_release;
8825 + /* regiter video device */
8826 + isp->vdev = &mrst_isp_vdev;
8827 + isp->vdev->parent = &pdev->dev;
8828 + video_set_drvdata(isp->vdev, isp);
8830 + ret = video_register_device(isp->vdev, VFL_TYPE_GRABBER, -1);
8832 + dprintk(0, "fail to register video deivice");
8833 + goto exit_dma_release;
8836 + dprintk(0, "registered dev/video%d", isp->vdev->num);
8837 + dprintk(0, "isp->vdev = %p", isp->vdev);
8841 + ret = request_irq(pdev->irq, mrst_isp_irq_handler, IRQF_SHARED,
8842 + /* pci_name(pdev), isp); */
8843 + "mrst_camera_imaging", isp);
8845 + dprintk(0, "fail to request irq");
8846 + goto exit_unregister_video;
8849 + mrst_isp_disable_interrupt(isp);
8853 + mrst_ci_flash_probe(isp);
8855 + mrst_isp_to_do_mblk_line = 0;
8857 + dprintk(0, "mrstisp driver module successfully loaded");
8860 +exit_unregister_video:
8861 + video_unregister_device(isp->vdev);
8863 + dma_release_declared_memory(&pdev->dev);
8865 + iounmap(isp->regs);
8866 +exit_release_regions:
8867 + pci_release_regions(pdev);
8869 + pci_disable_device(pdev);
8870 +exit_unregister_v4l2:
8871 + v4l2_device_unregister(&isp->v4l2_dev);
8879 +static int mrst_isp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
8881 + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
8882 + struct mrst_isp_device *isp = to_isp(v4l2_dev);
8889 + ret = pci_save_state(pdev);
8891 + printk(KERN_ERR "mrstisp: pci_save_state failed %d\n", ret);
8895 + ret = pci_set_power_state(pdev, PCI_D3cold);
8897 + printk(KERN_ERR "mrstisp: fail to set power state\n");
8902 + ret = ci_sensor_suspend();
8904 + printk(KERN_ERR "mrstisp: Fail to suspend sensor\n");
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);
8917 +static int mrst_isp_pci_resume(struct pci_dev *pdev)
8919 + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
8920 + struct mrst_isp_device *isp = to_isp(v4l2_dev);
8925 + pci_set_power_state(pdev, PCI_D0);
8926 + pci_restore_state(pdev);
8928 + ret = pci_enable_device(pdev);
8930 + printk(KERN_ERR "mrstisp: fail to enable device in resume\n");
8935 + ret = ci_sensor_resume();
8937 + printk(KERN_ERR "mrstisp: Fail to resume sensor\n");
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);
8953 +static struct pci_device_id mrst_isp_pci_tbl[] __devinitdata = {
8954 + { PCI_DEVICE(0x8086, 0x080B) },
8958 +MODULE_DEVICE_TABLE(pci, mrst_isp_pci_tbl);
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,
8966 + .suspend = mrst_isp_pci_suspend,
8967 + .resume = mrst_isp_pci_resume,
8971 +static int __init mrst_isp_pci_init(void)
8977 + ret = pci_register_driver(&mrst_isp_pci_driver);
8979 + printk(KERN_ERR "mrstisp: Unable to register driver\n");
8984 + dprintk(1, "Unable to register flash driver");
8990 +static void __exit mrst_isp_pci_exit(void)
8994 + pci_unregister_driver(&mrst_isp_pci_driver);
8999 +module_init(mrst_isp_pci_init);
9000 +/* late_initcall(mrst_isp_pci_init); */
9001 +module_exit(mrst_isp_pci_exit);
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");
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
9012 +++ b/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c
9015 + * Support for Moorestown Langwell Camera Imaging ISP subsystem.
9017 + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
9019 + * Copyright (c) Silicon Image 2008 www.siliconimage.com
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.
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.
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.
9036 + * Xiaolin Zhang <xiaolin.zhang@intel.com>
9039 +#include "mrstisp_stdinc.h"
9042 + * sets all main picture and self picture buffer offsets back to 0
9044 +void ci_isp_mif_reset_offsets(enum ci_isp_conf_update_time update_time)
9046 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
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);
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);
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);
9065 + switch (update_time) {
9066 + case CI_ISP_CFG_UPDATE_FRAME_SYNC:
9068 + case CI_ISP_CFG_UPDATE_IMMEDIATE:
9069 + REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9071 + case CI_ISP_CFG_UPDATE_LATER:
9079 + * This function get the byte count from the last JPEG or raw data transfer
9081 +u32 ci_isp_mif_get_byte_cnt(void)
9083 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9085 + return (u32) REG_GET_SLICE(mrv_reg->mi_byte_cnt, MRV_MI_BYTE_CNT);
9089 + * Sets the desired self picture orientation, if possible.
9091 +static int ci_isp_mif_set_self_pic_orientation(enum ci_isp_mif_sp_mode
9093 + int activate_self_path)
9096 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9097 + u32 mi_ctrl = REG_READ(mrv_reg->mi_ctrl);
9099 + u32 output_format = REG_GET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT);
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);
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);
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);
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);
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);
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);
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);
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);
9148 + eprintk("unknown value for mrv_mif_sp_mode");
9149 + return CI_STATUS_NOTSUPP;
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 */
9161 + eprintk("rotation is only allowed for RGB modes.");
9162 + return CI_STATUS_NOTSUPP;
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);
9171 + return CI_STATUS_SUCCESS;
9175 + * Checks the main or self picture path buffer structure.
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)
9180 + if (!isp_mi_path_conf) {
9181 + eprintk("isp_mi_path_conf is NULL");
9182 + return CI_STATUS_NULL_POINTER;
9185 + if (!isp_mi_path_conf->ybuffer.pucbuffer) {
9186 + eprintk("isp_mi_path_conf->ybuffer.pucbuffer is NULL");
9187 + return CI_STATUS_NULL_POINTER;
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)
9194 + ((isp_mi_path_conf->ybuffer.size
9195 + & ~(MRV_MI_MP_Y_SIZE_INIT_VALID_MASK)) != 0)
9197 + ((isp_mi_path_conf->ybuffer.size
9198 + & (MRV_MI_MP_Y_SIZE_INIT_VALID_MASK)) == 0)
9200 + ((isp_mi_path_conf->ybuffer.offs
9201 + & ~(MRV_MI_MP_Y_OFFS_CNT_INIT_VALID_MASK)) != 0)) {
9202 + return CI_STATUS_OUTOFRANGE;
9205 + if ((((unsigned long) isp_mi_path_conf->ybuffer.pucbuffer
9206 + & ~(MRV_MI_SP_Y_BASE_AD_INIT_VALID_MASK)) != 0)
9208 + ((isp_mi_path_conf->ybuffer.size &
9209 + ~(MRV_MI_SP_Y_SIZE_INIT_VALID_MASK)) != 0)
9211 + ((isp_mi_path_conf->ybuffer.size &
9212 + (MRV_MI_SP_Y_SIZE_INIT_VALID_MASK)) == 0)
9214 + ((isp_mi_path_conf->ybuffer.offs &
9215 + ~(MRV_MI_SP_Y_OFFS_CNT_INIT_VALID_MASK)) !=
9218 + ((isp_mi_path_conf->llength &
9219 + ~(MRV_MI_SP_Y_LLENGTH_VALID_MASK)) != 0)
9221 + ((isp_mi_path_conf->
9222 + llength & (MRV_MI_SP_Y_LLENGTH_VALID_MASK)) == 0)) {
9223 + return CI_STATUS_OUTOFRANGE;
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)) !=
9234 + ((isp_mi_path_conf->cb_buffer.size &
9235 + ~(MRV_MI_MP_CB_SIZE_INIT_VALID_MASK)) != 0)
9237 + ((isp_mi_path_conf->cb_buffer.size &
9238 + (MRV_MI_MP_CB_SIZE_INIT_VALID_MASK)) == 0)
9240 + ((isp_mi_path_conf->cb_buffer.offs &
9241 + ~(MRV_MI_MP_CB_OFFS_CNT_INIT_VALID_MASK)) !=
9243 + return CI_STATUS_OUTOFRANGE;
9246 + if ((((unsigned long)
9247 + isp_mi_path_conf->cb_buffer.pucbuffer
9248 + & ~(MRV_MI_SP_CB_BASE_AD_INIT_VALID_MASK)) !=
9251 + ((isp_mi_path_conf->cb_buffer.size &
9252 + ~(MRV_MI_SP_CB_SIZE_INIT_VALID_MASK)) != 0)
9254 + ((isp_mi_path_conf->cb_buffer.size &
9255 + (MRV_MI_SP_CB_SIZE_INIT_VALID_MASK)) == 0)
9257 + ((isp_mi_path_conf->cb_buffer.offs &
9258 + ~(MRV_MI_SP_CB_OFFS_CNT_INIT_VALID_MASK)) !=
9260 + return CI_STATUS_OUTOFRANGE;
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)) !=
9272 + ((isp_mi_path_conf->cr_buffer.size &
9273 + ~(MRV_MI_MP_CR_SIZE_INIT_VALID_MASK)) != 0)
9275 + ((isp_mi_path_conf->cr_buffer.size &
9276 + (MRV_MI_MP_CR_SIZE_INIT_VALID_MASK)) == 0)
9278 + ((isp_mi_path_conf->cr_buffer.offs &
9279 + ~(MRV_MI_MP_CR_OFFS_CNT_INIT_VALID_MASK)) !=
9281 + return CI_STATUS_OUTOFRANGE;
9284 + if ((((unsigned long)
9285 + isp_mi_path_conf->cr_buffer.pucbuffer
9286 + & ~(MRV_MI_SP_CR_BASE_AD_INIT_VALID_MASK))
9289 + ((isp_mi_path_conf->cr_buffer.size &
9290 + ~(MRV_MI_SP_CR_SIZE_INIT_VALID_MASK)) != 0)
9292 + ((isp_mi_path_conf->cr_buffer.size &
9293 + (MRV_MI_SP_CR_SIZE_INIT_VALID_MASK)) == 0)
9295 + ((isp_mi_path_conf->cr_buffer.offs &
9296 + ~(MRV_MI_SP_CR_OFFS_CNT_INIT_VALID_MASK)) != 0)) {
9297 + return CI_STATUS_OUTOFRANGE;
9302 + return CI_STATUS_SUCCESS;
9306 + * Configures the main picture path buffers of the MI.
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)
9312 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9313 + int error = CI_STATUS_FAILURE;
9315 + error = ci_isp_mif_check_mi_path_conf(isp_mi_path_conf, true);
9316 + if (error != CI_STATUS_SUCCESS)
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);
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.
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);
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.
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);
9356 + * update base and offset registers during next immediate or
9357 + * automatic update request
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);
9362 + switch (update_time) {
9363 + case CI_ISP_CFG_UPDATE_FRAME_SYNC:
9365 + * frame synchronous update of shadow registers,
9366 + * update is done after the curr frame
9368 + REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON);
9370 + case CI_ISP_CFG_UPDATE_IMMEDIATE:
9372 + * immediate update of shadow registers
9373 + * (will disturb an ongoing frame processing)
9375 + REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9377 + case CI_ISP_CFG_UPDATE_LATER:
9378 + /* no update from within this function */
9388 + * Configures the self picture path buffers of the MI.
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)
9395 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9396 + int error = CI_STATUS_FAILURE;
9398 + error = ci_isp_mif_check_mi_path_conf(isp_mi_path_conf, false);
9399 + if (error != CI_STATUS_SUCCESS)
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);
9413 + * llength is counted in pixels and this value could be stored
9414 + * directly into the register
9416 + REG_SET_SLICE(mrv_reg->mi_sp_y_llength, MRV_MI_SP_Y_LLENGTH,
9417 + isp_mi_path_conf->llength);
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.
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);
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.
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);
9445 + if ((!isp_mi_path_conf->ypic_width)
9446 + || (!isp_mi_path_conf->ypic_height)) {
9447 + return CI_STATUS_FAILURE;
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);
9459 + * update base and offset registers during next immediate or
9460 + * automatic update request
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);
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,
9470 + case CI_ISP_CFG_UPDATE_IMMEDIATE:
9471 + REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);
9473 + case CI_ISP_CFG_UPDATE_LATER:
9483 + * Configures the DMA path of the MI.
9486 +int ci_isp_mif_set_path_and_orientation(const struct ci_isp_mi_ctrl
9489 + struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE;
9490 + int error = CI_STATUS_OUTOFRANGE;
9493 + if (!mrv_mi_ctrl) {
9494 + eprintk("mrv_mi_ctrl is NULL");
9495 + return CI_STATUS_NULL_POINTER;
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");
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);
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);
9512 + case CI_ISP_PATH_ON:
9513 + REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, ON);
9515 + case CI_ISP_PATH_JPE:
9516 + REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, ON);
9518 + case CI_ISP_PATH_RAW8:
9519 + REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, ON);
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);
9527 + eprintk("bad mrv_mi_ctrl->main_path value");
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);
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);
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);
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);
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);
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);
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);
9563 + eprintk("bad mrv_mi_ctrl->mrv_mif_sp_out_form value");
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);
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);
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);
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);
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:
9589 + eprintk("bad mrv_mi_ctrl->mrv_mif_sp_in_form value");
9593 + error = CI_STATUS_SUCCESS;
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);
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);
9609 + error = CI_STATUS_NOTSUPP;
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);
9618 + error = CI_STATUS_NOTSUPP;
9622 + error = CI_STATUS_OUTOFRANGE;
9627 + if (error != CI_STATUS_SUCCESS) {
9628 + eprintk("bad mrv_mi_ctrl->mrv_mif_sp_pic_form value");
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);
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);
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);
9649 + error = CI_STATUS_OUTOFRANGE;
9654 + if (error != CI_STATUS_SUCCESS) {
9655 + eprintk("bad mrv_mi_ctrl->mrv_mif_mp_pic_form value");
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);
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);
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);
9675 + error = CI_STATUS_OUTOFRANGE;
9679 + REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM,
9680 + MRV_MI_BURST_LEN_CHROM_16);
9682 + if (error != CI_STATUS_SUCCESS) {
9683 + eprintk("bad mrv_mi_ctrl->burst_length_chrom value");
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);
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);
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);
9703 + error = CI_STATUS_OUTOFRANGE;
9707 + REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM,
9708 + MRV_MI_BURST_LEN_LUM_16);
9710 + if (error != CI_STATUS_SUCCESS) {
9711 + eprintk("bad mrv_mi_ctrl->burst_length_lum value");
9715 + /* enable updating of the shadow registers for main and self picture
9716 + * to their init values
9718 + switch (mrv_mi_ctrl->init_vals) {
9719 + case CI_ISP_MIF_NO_INIT_VALS:
9721 + case CI_ISP_MIF_INIT_OFFS:
9722 + REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE);
9724 + case CI_ISP_MIF_INIT_BASE:
9725 + REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE);
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);
9732 + error = CI_STATUS_OUTOFRANGE;
9736 + if (error != CI_STATUS_SUCCESS) {
9737 + eprintk("bad mrv_mi_ctrl->init_vals value");
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);
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);
9749 + /* now write settings into register */
9750 + REG_WRITE(mrv_reg->mi_ctrl, mi_ctrl);
9752 + dprintk(2, "mi_ctrl = 0x%x", mi_ctrl);
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)) {
9758 + /* do not call if not supported */
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
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));
9769 + eprintk("bad mrv_mi_ctrl->self_path value");
9770 + error = CI_STATUS_OUTOFRANGE;
9773 + REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON);