diff options
author | Saul Wold <Saul.Wold@intel.com> | 2010-09-24 15:36:24 -0700 |
---|---|---|
committer | Saul Wold <Saul.Wold@intel.com> | 2010-09-24 16:43:21 -0700 |
commit | 239a368d5715d8f5b7733f9400339c2350c49369 (patch) | |
tree | 2953f12b45e590d9e14b6f72f8e4ee7188e41508 /meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.35-moorestown-camera-driver-10.0-2-3.patch | |
parent | c5b9525263dac6844d152e40acf8cee4d27b60bc (diff) | |
download | openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.tar.gz openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.tar.bz2 openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.tar.xz openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.zip |
netbook: Correct netbook build by moving netbook configuration from moblin to meta
Signed-off-by: Saul Wold <Saul.Wold@intel.com>
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.35-moorestown-camera-driver-10.0-2-3.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.35-moorestown-camera-driver-10.0-2-3.patch | 9779 |
1 files changed, 0 insertions, 9779 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.35-moorestown-camera-driver-10.0-2-3.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.35-moorestown-camera-driver-10.0-2-3.patch deleted file mode 100644 index f3e8159eb..000000000 --- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.35-moorestown-camera-driver-10.0-2-3.patch +++ /dev/null @@ -1,9779 +0,0 @@ -From b5dc72f2a0bc509a241e03eea51e739204315f93 Mon Sep 17 00:00:00 2001 -From: Zheng Ba <zheng.ba@intel.com> -Date: Thu, 1 Apr 2010 16:24:20 +0800 -Subject: [PATCH 2/3] Moorestown Camera Imaging driver Beta 10.0 - -Patch-mainline: 2.6.35? - -Changes from Beta 9.0: -1. Fixed hsd sighting - 3469638 3469639 3469710 3469822 (high) - 3469697 (medium) - -Changes from Beta 8.0: -1. Fixed hsd sighting - 3469056 3469058 (critical) - 3469705 3469696 3469709 3469510 (medium) - -Changes from Beta 7.0: -1. Fixed hsd sighting 3469681,3469682,3469683 (high) - -Changes from Beta 6.0: -1. Fixed hsd sighting 3469668 (high) -2. Fixed ov5630 v4l2 view-finding dark issue -3. Enabled support for popular v4l2 applications (cheese, skype, ffmpeg) - -Changes from Beta 5.1: -1. Fixed CRITICAL sighting 3469558 -- ciapp fails to launch with segment fault -2. Fixed HIGH sighting 3479513 -- ov5630 AWB unstable -3. Improved KMOT sensor 720p fps from 30 to 40 - -Changes from Beta 5.0: -Fixed a critical issue of camera driver not loading -- hsd 3469557 - -Main changes from Beta 4.0: -Fixed 4 HSD sightings: 3469392,3469099,3469470,3469500 - -Main changes from Beta 3.0: -Fixed 7 HSD sightings: 3469264,3469112,3469395,3469103,3469105,3469471,3469484 - -Main changes from Beta 2.0: -Fixed 6 HSD sightings: 3469047,3469315,3469317,3469101,3468409,3469391 - -Main changes from Beta 1.1: -1. Added interrupt mode for jpeg capture and KMOT viewfinding -2. Fixed HSD sighting 3469228 and 3469147 - -Main changes from Alpha2: -Enabled MIPI interface in ISP driver and KMOT sensor s5k4e1. -Enabled FIFO in ISP driver, which doubled the fps in view-finding mode. -Enabled Subdev Framework in CI kernel driver. -Enabled AF Continuous Mode. -Enabled AE scene evaluation. - -Enabled the camera drivers in kernel: -Device Drivers --> Multimedia support --> Video For Linux -Device Drivers --> Mulitmedia support --> Video capture adapters --> ---> Moorestown Langwell Camera Imaging Subsystem support. - -Kernel configs: -1. camera driver depends on GPIO library and I2C driver. -CONFIG_GENERIC_GPIO=y -CONFIG_I2C=y -CONFIG_GPIOLIB=y -2. camera driver depends on videobuf-core and videobuf-dma-contig. -VIDEOBUF_GEN=y -VIDEOBUF_DMA_CONTIG=y -3. enable multimedia support and video capture. -CONFIG_MEDIA_SUPPORT=y -CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -CONFIG_VIDEO_MEDIA=y -CONFIG_VIDEO_V4L2=y -4. camera drivers incluing ISP, 5630, 5630-motor, s5k4e1, s5k4e1-motor, 2650, -9665, flash. -CONFIG_VIDEO_MRSTCI=y -CONFIG_VIDEO_MRST_ISP=y -CONFIG_VIDEO_MRST_OV5630=y -CONFIG_VIDEO_MRST_OV5630_MOTOR=y -CONFIG_VIDEO_MRST_S5K4E1=y -CONFIG_VIDEO_MRST_S5K4E1_MOTOR=y -CONFIG_VIDEO_MRST_FLASH=y -CONFIG_VIDEO_MRST_OV2650=y -CONFIG_VIDEO_MRST_OV9665=y - -Signed-off-by: Zheng Ba <zheng.ba@intel.com> ---- - drivers/media/video/mrstci/Kconfig | 26 + - drivers/media/video/mrstci/Makefile | 8 + - drivers/media/video/mrstci/mrstisp/Kconfig | 10 + - drivers/media/video/mrstci/mrstisp/Makefile | 7 + - .../video/mrstci/mrstisp/__mrstisp_private_ioctl.c | 324 +++ - drivers/media/video/mrstci/mrstisp/mrstisp_dp.c | 1301 +++++++++ - drivers/media/video/mrstci/mrstisp/mrstisp_hw.c | 1622 +++++++++++ - drivers/media/video/mrstci/mrstisp/mrstisp_isp.c | 1993 +++++++++++++ - drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c | 569 ++++ - drivers/media/video/mrstci/mrstisp/mrstisp_main.c | 2977 ++++++++++++++++++++ - drivers/media/video/mrstci/mrstisp/mrstisp_mif.c | 763 +++++ - 11 files changed, 9600 insertions(+), 0 deletions(-) - create mode 100644 drivers/media/video/mrstci/Kconfig - create mode 100644 drivers/media/video/mrstci/Makefile - create mode 100644 drivers/media/video/mrstci/mrstisp/Kconfig - create mode 100644 drivers/media/video/mrstci/mrstisp/Makefile - create mode 100644 drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c - create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_dp.c - create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_hw.c - create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_isp.c - create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c - create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_main.c - create mode 100644 drivers/media/video/mrstci/mrstisp/mrstisp_mif.c - -diff --git a/drivers/media/video/mrstci/Kconfig b/drivers/media/video/mrstci/Kconfig -new file mode 100644 -index 0000000..9ac7065 ---- /dev/null -+++ b/drivers/media/video/mrstci/Kconfig -@@ -0,0 +1,26 @@ -+menuconfig VIDEO_MRSTCI -+ bool "Moorestown Langwell Camera Imaging Subsystem support" -+ depends on VIDEO_V4L2 -+ default y -+ -+ ---help--- -+ Say Y here to enable selecting the Intel Moorestown Langwell Camera Imaging Subsystem for webcams. -+ -+if VIDEO_MRSTCI && VIDEO_V4L2 -+ -+source "drivers/media/video/mrstci/mrstisp/Kconfig" -+ -+source "drivers/media/video/mrstci/mrstov5630/Kconfig" -+source "drivers/media/video/mrstci/mrstov5630_motor/Kconfig" -+ -+source "drivers/media/video/mrstci/mrsts5k4e1/Kconfig" -+source "drivers/media/video/mrstci/mrsts5k4e1_motor/Kconfig" -+ -+source "drivers/media/video/mrstci/mrstflash/Kconfig" -+ -+source "drivers/media/video/mrstci/mrstov2650/Kconfig" -+ -+source "drivers/media/video/mrstci/mrstov9665/Kconfig" -+ -+endif # VIDEO_MRSTCI -+ -diff --git a/drivers/media/video/mrstci/Makefile b/drivers/media/video/mrstci/Makefile -new file mode 100644 -index 0000000..9d3449e ---- /dev/null -+++ b/drivers/media/video/mrstci/Makefile -@@ -0,0 +1,8 @@ -+obj-$(CONFIG_VIDEO_MRST_OV2650) += mrstov2650/ -+obj-$(CONFIG_VIDEO_MRST_OV9665) += mrstov9665/ -+obj-$(CONFIG_VIDEO_MRST_OV5630) += mrstov5630/ -+obj-$(CONFIG_VIDEO_MRST_OV5630_MOTOR) += mrstov5630_motor/ -+obj-$(CONFIG_VIDEO_MRST_S5K4E1) += mrsts5k4e1/ -+obj-$(CONFIG_VIDEO_MRST_S5K4E1_MOTOR) += mrsts5k4e1_motor/ -+obj-$(CONFIG_VIDEO_MRST_FLASH) += mrstflash/ -+obj-$(CONFIG_VIDEO_MRST_ISP) += mrstisp/ -diff --git a/drivers/media/video/mrstci/mrstisp/Kconfig b/drivers/media/video/mrstci/mrstisp/Kconfig -new file mode 100644 -index 0000000..8e58a87 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/Kconfig -@@ -0,0 +1,10 @@ -+config VIDEO_MRST_ISP -+ tristate "Moorstown Marvin - ISP Driver" -+ depends on VIDEO_V4L2 -+ select VIDEOBUF_DMA_CONTIG -+ default y -+ ---help--- -+ Say Y here if you want support for cameras based on the Intel Moorestown platform. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called mrstisp.ko. -diff --git a/drivers/media/video/mrstci/mrstisp/Makefile b/drivers/media/video/mrstci/mrstisp/Makefile -new file mode 100644 -index 0000000..30f4e62 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/Makefile -@@ -0,0 +1,7 @@ -+mrstisp-objs := mrstisp_main.o mrstisp_hw.o mrstisp_isp.o \ -+ mrstisp_dp.o mrstisp_mif.o mrstisp_jpe.o \ -+ __mrstisp_private_ioctl.o -+ -+obj-$(CONFIG_VIDEO_MRST_ISP) += mrstisp.o -+ -+EXTRA_CFLAGS += -I$(src)/../include -I$(src)/include -diff --git a/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c b/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c -new file mode 100644 -index 0000000..85cc482 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/__mrstisp_private_ioctl.c -@@ -0,0 +1,324 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+ -+/* -+static u32 copy_sensor_config_from_user(struct ci_sensor_config *des, -+ struct ci_sensor_config *src) -+{ -+ u32 ret = 0; -+ ret = copy_from_user((void *)des, (const void *)src, -+ sizeof(struct ci_sensor_config)); -+ if (ret) -+ return -EFAULT; -+ return ret; -+} -+ -+static u32 copy_sensor_caps_from_user(struct ci_sensor_caps *des, -+ struct ci_sensor_caps *src) -+{ -+ u32 ret = 0; -+ ret = copy_from_user((void *)des, (const void *)src, -+ sizeof(struct ci_sensor_caps)); -+ if (ret) -+ return -EFAULT; -+ return ret; -+} -+ -+static u32 copy_isp_config_from_user(struct ci_isp_config *des, -+ struct ci_isp_config *src) -+{ -+ int ret = 0; -+ ret = copy_from_user((void *)des, (const void *)src, -+ sizeof(struct ci_isp_config)); -+ if (ret) { -+ eprintk("returning %d", ret); -+ return ret; -+ } -+ return 0; -+} -+*/ -+ -+static void print_bls_cfg(struct ci_isp_config *isp_cfg) -+{ -+ struct ci_isp_bls_config *bls_cfg = &isp_cfg->bls_cfg; -+ -+ dprintk(4, "print_bls_cfg:"); -+ dprintk(4, "enable_automatic:%d", (bls_cfg->enable_automatic ? 1 : 0)); -+ dprintk(4, "disable_h:%d", (bls_cfg->disable_h ? 1 : 0)); -+ dprintk(4, "disable_v:%d", (bls_cfg->disable_v ? 1 : 0)); -+ dprintk(4, "enable_window1:%d", -+ (bls_cfg->isp_bls_window1.enable_window ? 1 : 0)); -+ dprintk(4, "start_h:%d", (int)bls_cfg->isp_bls_window1.start_h); -+ dprintk(4, "stop_h:%d", (int)bls_cfg->isp_bls_window1.stop_h); -+ dprintk(4, "start_v:%d", (int)bls_cfg->isp_bls_window1.start_v); -+ dprintk(4, "stop_v:%d", (int)bls_cfg->isp_bls_window1.stop_v); -+ dprintk(4, "enable_window2: %d", -+ (bls_cfg->isp_bls_window2.enable_window ? 1 : 0)); -+ dprintk(4, "start_h%d", (int)bls_cfg->isp_bls_window2.start_h); -+ dprintk(4, "stop_h%d", (int)bls_cfg->isp_bls_window2.stop_h); -+ dprintk(4, "start_v%d", (int)bls_cfg->isp_bls_window2.start_v); -+ dprintk(4, "stop_v%d", (int)bls_cfg->isp_bls_window2.stop_v); -+ dprintk(4, "bls_samples%d", (int)bls_cfg->bls_samples); -+ dprintk(4, "fixed_a0x%02x", (int)bls_cfg->bls_subtraction.fixed_a); -+ dprintk(4, "fixed_b0x%02x", (int)bls_cfg->bls_subtraction.fixed_b); -+ dprintk(4, "fixed_c0x%02x", (int)bls_cfg->bls_subtraction.fixed_c); -+ dprintk(4, "fixed_d0x%02x", (int)bls_cfg->bls_subtraction.fixed_d); -+ dprintk(4, "\n"); -+} -+ -+static int mrst_isp_set_cfg(struct file *file, void *priv, -+ struct ci_pl_system_config *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ if (arg == NULL) { -+ eprintk("NULL pointer of arg"); -+ return 0; -+ } -+ mutex_lock(&isp->mutex); -+ -+ /* -+ if (arg->isi_config != NULL) { -+ dprintk(2, "sync isi cfg"); -+ copy_sensor_config_from_user(isp->sys_conf.isi_config, -+ arg->isi_config); -+ } else { -+ eprintk("NULL arg->isi_config"); -+ ret = CI_STATUS_NULL_POINTER; -+ goto exit_unlock; -+ } -+ -+ if (arg->isi_caps != NULL) { -+ dprintk(2, "sync isi caps"); -+ copy_sensor_caps_from_user(isp->sys_conf.isi_caps, -+ arg->isi_caps); -+ } else { -+ eprintk("NULL arg->isi_caps"); -+ ret = CI_STATUS_NULL_POINTER; -+ goto exit_unlock; -+ } -+ */ -+ -+ memcpy(&isp->sys_conf.isp_cfg, &arg->isp_cfg, -+ sizeof(struct ci_isp_config)); -+ -+ print_bls_cfg(&isp->sys_conf.isp_cfg); -+ -+ dprintk(2, "gammagamma2 = %d", arg->isp_cfg.flags.gamma2); -+ dprintk(2, "gammagamma2 now = %d", isp->sys_conf.isp_cfg.flags.gamma2); -+ mutex_unlock(&isp->mutex); -+ -+ isp->sys_conf.isp_hal_enable = 1; -+ -+ DBG_leaving; -+ return 0; -+} -+ -+/* for buffer sharing between CI and VA */ -+static int mrst_isp_get_frame_info(struct file *file, void *priv, -+ struct ci_frame_info *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ mutex_lock(&isp->mutex); -+ -+ arg->width = isp->bufwidth; -+ arg->height = isp->bufheight; -+ arg->fourcc = isp->pixelformat; -+ arg->stride = isp->bufwidth; /* should be 64 bit alignment*/ -+ arg->offset = arg->frame_id * PAGE_ALIGN(isp->frame_size); -+#if 0 -+ if (isp->bufwidth == 640 && isp->bufheight == 480) -+ arg->offset = arg->frame_id * 0x71000; -+ else if (isp->bufwidth == 1280 && isp->bufheight == 720) -+ arg->offset = arg->frame_id * 0x152000; -+#endif -+ -+ -+ dprintk(2, "w=%d, h=%d, 4cc =%x, stride=%d, offset=%d,fsize=%d", -+ arg->width, arg->height, arg->fourcc, arg->stride, -+ arg->offset, isp->frame_size); -+ -+ mutex_unlock(&isp->mutex); -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_set_jpg_enc_ratio(struct file *file, void *priv, int *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ dprintk(2, "set jpg compression ratio is %d", *arg); -+ -+ mutex_lock(&isp->mutex); -+ isp->sys_conf.isp_cfg.jpeg_enc_ratio = *arg; -+ mutex_unlock(&isp->mutex); -+ -+ DBG_leaving; -+ return 0; -+} -+ -+int mrst_isp_get_isp_mem_info(struct file *file, void *priv, -+ struct ci_isp_mem_info *arg) -+{ -+ u32 ret = 0; -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ mutex_lock(&isp->mutex); -+ arg->isp_bar0_pa = isp->mb0; -+ arg->isp_bar0_size = isp->mb0_size; -+ arg->isp_bar1_pa = isp->mb1; -+ arg->isp_bar1_size = isp->mb1_size; -+ mutex_unlock(&isp->mutex); -+ -+ DBG_leaving; -+ return ret; -+} -+ -+int mrst_isp_create_jpg_review_frame(struct file *file, void *priv, -+ struct v4l2_jpg_review_buffer *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ u32 width = arg->width; -+ u32 height = arg->height; -+ u32 pix_fmt = arg->pix_fmt; -+ u32 jpg_frame = arg->jpg_frame; -+ -+ static struct v4l2_jpg_review_buffer *jpg_review; -+ -+ jpg_review = &isp->sys_conf.jpg_review; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ if (width > 640 || height > 480 || width < 32 || height < 16) { -+ eprintk("unsupported resolution: %d * %d", width, height); -+ return -EINVAL; -+ } -+ -+ if (jpg_frame >= isp->num_frames) { -+ eprintk("error jpeg frame id"); -+ return -1; -+ } -+ -+ jpg_review->width = width; -+ jpg_review->height = height; -+ jpg_review->pix_fmt = pix_fmt; -+ jpg_review->jpg_frame = jpg_frame; -+ -+ switch (arg->pix_fmt) { -+ case V4L2_PIX_FMT_YUV422P: -+ jpg_review->bytesperline = width * 2; -+ jpg_review->frame_size = width * height * 2; -+ break; -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ case V4L2_PIX_FMT_NV12: -+ jpg_review->bytesperline = width * 3/2; -+ jpg_review->frame_size = width * height * 3/2; -+ break; -+ default: -+ eprintk("unsupported pix_fmt: %d", arg->pix_fmt); -+ return -EINVAL; -+ } -+ -+ jpg_review->offset = isp->mb1_size - 640*480*2; -+ -+ isp->sys_conf.jpg_review_enable = 1; /* enable jpg review flag */ -+ -+ /* set user space data */ -+ arg->bytesperline = jpg_review->bytesperline; -+ arg->frame_size = jpg_review->frame_size; -+ arg->offset = jpg_review->offset; -+ -+ dprintk(1, "create jpg review frame successfully: " -+ "bytesperline = %d, frame_size = %d," -+ " offset = %d\n", arg->bytesperline, -+ arg->frame_size, arg->offset); -+ -+ DBG_leaving; -+ return 0; -+} -+ -+/* isp private ioctl for libci */ -+long mrst_isp_vidioc_default(struct file *file, void *fh, -+ int cmd, void *arg) -+{ -+ void *priv = file->private_data; -+ -+ DBG_entering; -+ -+ switch (cmd) { -+ case VIDIOC_GET_ISP_MEM_INFO: -+ return mrst_isp_get_isp_mem_info(file, priv, -+ (struct ci_isp_mem_info *)arg); -+ -+ case VIDIOC_SET_SYS_CFG: -+ return mrst_isp_set_cfg(file, priv, -+ (struct ci_pl_system_config *)arg); -+ -+ case VIDIOC_SET_JPG_ENC_RATIO: -+ return mrst_isp_set_jpg_enc_ratio(file, priv, (int *)arg); -+ -+ case ISP_IOCTL_GET_FRAME_INFO: -+ return mrst_isp_get_frame_info(file, priv, -+ (struct ci_frame_info *)arg); -+ -+ case VIDIOC_CREATE_JPG_REVIEW_BUF: -+ return mrst_isp_create_jpg_review_frame(file, priv, -+ (struct v4l2_jpg_review_buffer *)arg); -+ default: -+ v4l_print_ioctl("lnw_isp", cmd); -+ dprintk(2, "VIDIOC_SET_SYS_CFG = %x", VIDIOC_SET_SYS_CFG); -+ return -EINVAL; -+ } -+ -+ DBG_leaving; -+ return 0; -+} -diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c b/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c -new file mode 100644 -index 0000000..dd892fb ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/mrstisp_dp.c -@@ -0,0 +1,1301 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * Copyright (c) Silicon Image 2008 www.siliconimage.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+ -+/* mask for all chroma subsampling settings */ -+#define CI_ISP_DPD_CSS_MASK (CI_ISP_DPD_CSS_H_MASK | CI_ISP_DPD_CSS_V_MASK) -+ -+#define SCALER_COFFS_COSITED 0x400 -+#define FIXEDPOINT_ONE 0x1000 -+ -+/* limitations of main and self scaler */ -+#define MAIN_SCALER_WIDTH_MAX 2600 -+ -+#define SELF_SCALER_WIDTH_MAX 640 -+#define SCALER_MIN 16 -+ -+#define SELF_UPSCALE_FACTOR_MAX 5 -+ -+#define MAIN_UPSCALE_FACTOR_MAX 5 -+ -+/* -+ * upscale lookup table for smooth edges -+ * (linear interpolation between pixels) -+ */ -+ -+/* smooth edges */ -+static const struct ci_isp_rsz_lut isp_rsz_lut_smooth_lin = { -+ { -+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, -+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, -+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, -+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, -+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, -+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, -+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F -+ } -+}; -+ -+/* -+ * upscale lookup table for sharp edges -+ * (no interpolation, just duplicate pixels) -+ */ -+ -+/* sharp edges */ -+static const struct ci_isp_rsz_lut isp_rsz_lut_sharp = { -+ { -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, -+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, -+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, -+ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F -+ } -+}; -+ -+/* structure combining virtual ISP windows settings */ -+struct ci_isp_virtual_isp_wnds { -+ struct ci_isp_window wnd_blacklines; -+ struct ci_isp_window wnd_zoom_crop; -+}; -+ -+/* static storage to remember last applied virtual ISP window settings */ -+static struct ci_isp_virtual_isp_wnds last_isp_wnds; -+ -+/* -+ * Calculates the value to program into the struct ci_isp_scale or -+ * tsMrvSScale structures to scale from in pixels to out pixels. -+ * -+ * The formulas are taken from the MARVIN / MARVIN3PLUS user -+ * manuals (fixed-point calculation using 32 bit during -+ * processing, will overflow at an output size of 1048575 pixels). -+ */ -+static u32 ci_get_scale_reg(u16 in, u16 out) -+{ -+ if (in > out) { -+ /* downscaling */ -+ return (u32) (((((u32) out - 1) * RSZ_SCALER_BYPASS) / -+ (u32) (in - 1)) + 1); -+ } else if (in < out) { -+ /* upscaling */ -+ return (u32) (((((u32) in - 1) * RSZ_SCALER_BYPASS) / -+ (u32) (out - 1)) | (u32) RSZ_UPSCALE_ENABLE); -+ } -+ -+ /* no scaling */ -+ return RSZ_SCALER_BYPASS; -+} -+ -+/* -+ * Calculates the values of the ci_isp_scale structure for the -+ * given input size and data path descriptor. -+ */ -+static u32 ci_calc_scale_factors(const struct ci_isp_datapath_desc *source, -+ const struct ci_isp_datapath_desc *path, -+ struct ci_isp_scale *scale, int implementation) -+{ -+ u32 scaler_output_format; -+ u32 cssflags; -+ u32 scaler_input_format; -+ -+ u16 chroma_in_w; -+ u16 chroma_in_h; -+ u16 chroma_out_wcr; -+ u16 chroma_out_wcb; -+ u16 chroma_out_h; -+ -+ memset(scale, 0, sizeof(struct ci_isp_scale)); -+ dprintk(1, "srcw %d, srch %d;", source->out_w, source->out_h); -+ dprintk(1, "dstw %d, dsth %d", path->out_w, path->out_h); -+ -+ /* calculate Y scale factors */ -+ scale->scale_hy = ci_get_scale_reg(source->out_w, path->out_w); -+ scale->scale_vy = ci_get_scale_reg(source->out_h, path->out_h); -+ -+ /* figure out the color input format of the scaler */ -+ switch (path->flags & CI_ISP_DPD_MODE_MASK) { -+ case CI_ISP_DPD_MODE_DMAYC_DIRECT: -+ case CI_ISP_DPD_MODE_DMAYC_ISP: -+ case CI_ISP_DPD_MODE_DMAJPEG_DIRECT: -+ case CI_ISP_DPD_MODE_DMAJPEG_ISP: -+ /* DMA-read originated data */ -+ scaler_input_format = path->flags & CI_ISP_DPD_DMA_IN_MASK; -+ break; -+ default: -+ /* ISP originated data */ -+ scaler_input_format = CI_ISP_DPD_DMA_IN_422; -+ break; -+ } -+ -+ dprintk(1, "scaler_input_format is 0x%x", scaler_input_format); -+ -+ switch (scaler_input_format) { -+ case CI_ISP_DPD_DMA_IN_422: -+ chroma_in_w = source->out_w / 2; -+ chroma_in_h = source->out_h; -+ chroma_out_wcr = path->out_w / 2; -+ chroma_out_wcb = (path->out_w + 1) / 2; -+ chroma_out_h = path->out_h; -+ break; -+ case CI_ISP_DPD_DMA_IN_420: -+ chroma_in_w = source->out_w / 2; -+ chroma_in_h = source->out_h / 2; -+ chroma_out_wcr = path->out_w / 2; -+ chroma_out_wcb = (path->out_w + 1) / 2; -+ chroma_out_h = path->out_h / 2; -+ break; -+ case CI_ISP_DPD_DMA_IN_411: -+ chroma_in_w = source->out_w / 4; -+ chroma_in_h = source->out_h; -+ chroma_out_wcr = path->out_w / 4; -+ chroma_out_wcb = (path->out_w + 2) / 4; -+ chroma_out_h = path->out_h; -+ break; -+ case CI_ISP_DPD_DMA_IN_444: -+ default: -+ chroma_in_w = source->out_w; -+ chroma_in_h = source->out_h; -+ chroma_out_wcb = chroma_out_wcr = path->out_w; -+ chroma_out_h = path->out_h; -+ break; -+ } -+ -+ /* calculate chrominance scale factors */ -+ switch (path->flags & CI_ISP_DPD_CSS_H_MASK) { -+ case CI_ISP_DPD_CSS_H2: -+ chroma_out_wcb /= 2; -+ chroma_out_wcr /= 2; -+ break; -+ case CI_ISP_DPD_CSS_H4: -+ chroma_out_wcb /= 4; -+ chroma_out_wcr /= 4; -+ break; -+ case CI_ISP_DPD_CSS_HUP2: -+ chroma_out_wcb *= 2; -+ chroma_out_wcr *= 2; -+ break; -+ case CI_ISP_DPD_CSS_HUP4: -+ chroma_out_wcb *= 4; -+ chroma_out_wcr *= 4; -+ break; -+ default: -+ /*leave chroma_out_w untouched*/ -+ break; -+ } -+ -+ scale->scale_hcr = ci_get_scale_reg(chroma_in_w, chroma_out_wcr); -+ scale->scale_hcb = ci_get_scale_reg(chroma_in_w, chroma_out_wcb); -+ scale->scale_hcb = scale->scale_hcr; -+ -+ switch (path->flags & CI_ISP_DPD_CSS_V_MASK) { -+ case CI_ISP_DPD_CSS_V2: -+ chroma_out_h /= 2; -+ break; -+ case CI_ISP_DPD_CSS_V4: -+ chroma_out_h /= 4; -+ break; -+ case CI_ISP_DPD_CSS_VUP2: -+ chroma_out_h *= 2; -+ break; -+ case CI_ISP_DPD_CSS_VUP4: -+ chroma_out_h *= 4; -+ break; -+ default: -+ /* leave chroma_out_h untouched */ -+ break; -+ } -+ -+ scale->scale_vc = ci_get_scale_reg(chroma_in_h, chroma_out_h); -+ -+ /* additional chrominance phase shifts */ -+ if (path->flags & CI_ISP_DPD_CSS_HSHIFT) -+ scale->phase_hc = SCALER_COFFS_COSITED; -+ if (path->flags & CI_ISP_DPD_CSS_VSHIFT) -+ scale->phase_vc = SCALER_COFFS_COSITED; -+ -+ /* additional luminance phase shifts */ -+ if (path->flags & CI_ISP_DPD_LUMA_HSHIFT) -+ scale->phase_hy = SCALER_COFFS_COSITED; -+ if (path->flags & CI_ISP_DPD_LUMA_VSHIFT) -+ scale->phase_vy = SCALER_COFFS_COSITED; -+ -+ /* try to figure out the outcoming YCbCr format */ -+ cssflags = path->flags & CI_ISP_DPD_CSS_MASK; -+ if (cssflags == (CI_ISP_DPD_CSS_H_OFF | CI_ISP_DPD_CSS_V_OFF)) { -+ /* trivial case: the output format is not changed */ -+ scaler_output_format = scaler_input_format; -+ } else { -+ /* output format gets changed by the scaler setting */ -+ /* assume invalid format by default */ -+ scaler_output_format = (u32) (-1); -+ switch (scaler_input_format) { -+ case CI_ISP_DPD_DMA_IN_444: -+ if (cssflags == (CI_ISP_DPD_CSS_H2 -+ | CI_ISP_DPD_CSS_V_OFF)) { -+ /* conversion 444 -> 422 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_422; -+ } else if (cssflags == (CI_ISP_DPD_CSS_H4 -+ | CI_ISP_DPD_CSS_V_OFF)) { -+ /* conversion 444 -> 411 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_411; -+ } else if (cssflags == (CI_ISP_DPD_CSS_H2 -+ | CI_ISP_DPD_CSS_V2)) { -+ /* conversion 444 -> 420 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_420; -+ } -+ break; -+ -+ case CI_ISP_DPD_DMA_IN_422: -+ if (cssflags == (CI_ISP_DPD_CSS_HUP2 -+ | CI_ISP_DPD_CSS_V_OFF)) { -+ /* conversion 422 -> 444 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_444; -+ } else if (cssflags == (CI_ISP_DPD_CSS_H2 -+ | CI_ISP_DPD_CSS_V_OFF)) { -+ /* conversion 422 -> 411 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_411; -+ } else if (cssflags == (CI_ISP_DPD_CSS_H_OFF -+ | CI_ISP_DPD_CSS_V2)) { -+ /* conversion 422 -> 420 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_420; -+ } -+ break; -+ -+ case CI_ISP_DPD_DMA_IN_420: -+ if (cssflags == (CI_ISP_DPD_CSS_HUP2 -+ | CI_ISP_DPD_CSS_VUP2)) { -+ /* conversion 420 -> 444 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_444; -+ } else if (cssflags == (CI_ISP_DPD_CSS_H2 -+ | CI_ISP_DPD_CSS_VUP2)) { -+ /* conversion 420 -> 411 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_411; -+ } else if (cssflags == (CI_ISP_DPD_CSS_H_OFF -+ | CI_ISP_DPD_CSS_VUP2)) { -+ /* conversion 420 -> 422 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_422; -+ } -+ break; -+ -+ case CI_ISP_DPD_DMA_IN_411: -+ if (cssflags == (CI_ISP_DPD_CSS_HUP4 -+ | CI_ISP_DPD_CSS_V_OFF)) { -+ /* conversion 411 -> 444 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_444; -+ } else if (cssflags == (CI_ISP_DPD_CSS_HUP2 -+ | CI_ISP_DPD_CSS_V_OFF)) { -+ /* conversion 411 -> 422 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_422; -+ } else if (cssflags == (CI_ISP_DPD_CSS_HUP2 -+ | CI_ISP_DPD_CSS_V2)) { -+ /* conversion 411 -> 420 */ -+ scaler_output_format = CI_ISP_DPD_DMA_IN_420; -+ } -+ break; -+ -+ default: -+ /* DMA input format not supported */ -+ break; -+ } -+ } -+ -+ return scaler_output_format; -+} -+ -+/* -+ * Returns the address of up-scaling lookup table to use for -+ * the given data path flags. -+ */ -+static const struct ci_isp_rsz_lut *ci_get_rsz_lut(u32 flags) -+{ -+ const struct ci_isp_rsz_lut *ret_val; -+ switch (flags & CI_ISP_DPD_UPSCALE_MASK) { -+ case CI_ISP_DPD_UPSCALE_SHARP: -+ ret_val = &isp_rsz_lut_sharp; -+ break; -+ default: -+ ret_val = &isp_rsz_lut_smooth_lin; -+ break; -+ } -+ return ret_val; -+} -+ -+/* -+ * Fills in scale factors and MI configuration for the main path. -+ * Note that only self path related settings will be written into -+ * the MI configuration struct, so this routine can be used for -+ * both ISP and DMA originated data path setups. -+ * -+ * Following fields are being filled in: -+ * scale_main: [all fields] -+ * mrv_mi_ctrl: mrv_mif_mp_pic_form main_path -+ */ -+static int ci_calc_main_path_settings(const struct ci_isp_datapath_desc *source, -+ const struct ci_isp_datapath_desc *main, -+ struct ci_isp_scale *scale_main, -+ struct ci_isp_mi_ctrl *mrv_mi_ctrl) -+{ -+ u32 main_flag; -+ -+ WARN_ON(!(source != NULL)); -+ WARN_ON(!(scale_main != NULL)); -+ WARN_ON(!(mrv_mi_ctrl != NULL)); -+ -+ /* assume datapath deactivation if no selfpath pointer is given) */ -+ if (main) -+ main_flag = main->flags; -+ else -+ main_flag = 0; -+ -+ /* initialize the given parameters */ -+ memset(scale_main, 0, sizeof(struct ci_isp_scale)); -+ scale_main->scale_hy = RSZ_SCALER_BYPASS; -+ scale_main->scale_hcb = RSZ_SCALER_BYPASS; -+ scale_main->scale_hcr = RSZ_SCALER_BYPASS; -+ scale_main->scale_vy = RSZ_SCALER_BYPASS; -+ scale_main->scale_vc = RSZ_SCALER_BYPASS; -+ -+ if (main_flag & CI_ISP_DPD_ENABLE) { -+ switch (main_flag & CI_ISP_DPD_MODE_MASK) { -+ case CI_ISP_DPD_MODE_ISPYC: -+ case CI_ISP_DPD_MODE_DMAYC_ISP: -+ mrv_mi_ctrl->main_path = CI_ISP_PATH_ON; -+ break; -+ case CI_ISP_DPD_MODE_ISPJPEG: -+ case CI_ISP_DPD_MODE_DMAJPEG_DIRECT: -+ case CI_ISP_DPD_MODE_DMAJPEG_ISP: -+ mrv_mi_ctrl->main_path = CI_ISP_PATH_JPE; -+ break; -+ case CI_ISP_DPD_MODE_ISPRAW: -+ mrv_mi_ctrl->main_path = CI_ISP_PATH_RAW8; -+ break; -+ case CI_ISP_DPD_MODE_ISPRAW_16B: -+ mrv_mi_ctrl->main_path = CI_ISP_PATH_RAW816; -+ break; -+ default: -+ eprintk("unsupported mode for main path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if (main_flag & (CI_ISP_DPD_H_FLIP | CI_ISP_DPD_V_FLIP | -+ CI_ISP_DPD_90DEG_CCW)) { -+ eprintk("not supported for main path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if (main_flag & CI_ISP_DPD_NORESIZE) { -+ if (main_flag & CI_ISP_DPD_CSS_MASK) { -+ eprintk("main path needs rezizer"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if (main_flag & -+ (CI_ISP_DPD_LUMA_HSHIFT | CI_ISP_DPD_LUMA_VSHIFT)) { -+ eprintk("main path needs rezizer"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } else { -+ if ((mrv_mi_ctrl->main_path == CI_ISP_PATH_RAW8) -+ || (mrv_mi_ctrl->main_path == CI_ISP_PATH_RAW8)) { -+ eprintk("scaler not in RAW mode"); -+ return CI_STATUS_NOTSUPP; -+ } -+ /* changed to avoid LINT warnings (Warning 613) */ -+ if (main != NULL) { -+ if ((((u32) (source->out_w) * -+ MAIN_UPSCALE_FACTOR_MAX) < main->out_w) -+ || -+ (((u32) (source->out_h) * -+ MAIN_UPSCALE_FACTOR_MAX) < -+ main->out_h)) { -+ eprintk("main upscaling exceeded"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if ((main->out_w > -+ MAIN_SCALER_WIDTH_MAX) -+ || (main->out_w < SCALER_MIN) -+ || (main->out_h < SCALER_MIN)) { -+ eprintk("main scaler ange exceeded"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } else { -+ WARN_ON(main == NULL); -+ } -+ -+ if (source->out_w & 0x01) { -+ eprintk("input width must be even!"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* calculate scale factors. */ -+ (void)ci_calc_scale_factors(source, main, scale_main, -+ MARVIN_FEATURE_MSCALE_FACTORCALC); -+ } -+ } else { -+ mrv_mi_ctrl->main_path = CI_ISP_PATH_OFF; -+ } -+ -+ /* hardcoded MI settings */ -+ dprintk(1, "main_flag is 0x%x", main_flag); -+ if (main_flag & CI_ISP_DPD_HWRGB_MASK) { -+ switch (main_flag & CI_ISP_DPD_HWRGB_MASK) { -+ case CI_ISP_DPD_YUV_420: -+ case CI_ISP_DPD_YUV_422: -+ mrv_mi_ctrl->mrv_mif_mp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ break; -+ case CI_ISP_DPD_YUV_NV12: -+ mrv_mi_ctrl->mrv_mif_mp_pic_form = -+ CI_ISP_MIF_PIC_FORM_SEMI_PLANAR; -+ break; -+ case CI_ISP_DPD_YUV_YUYV: -+ mrv_mi_ctrl->mrv_mif_mp_pic_form = -+ CI_ISP_MIF_PIC_FORM_INTERLEAVED; -+ break; -+ default: -+ mrv_mi_ctrl->mrv_mif_mp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ } -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Fills in scale factors and MI configuration for the self -+ * path. Note that only self path related settings will be written into -+ * the MI config struct, so this routine can be used for both ISP and DMA -+ * originated datapath setups. -+ * -+ * Following fields are being filled in: -+ * scale_flag : -+ * [all fields] -+ * mrv_mi_ctrl : -+ * mrv_mif_sp_out_form -+ * mrv_mif_sp_in_form -+ * mrv_mif_sp_pic_form -+ * mrv_mif_sp_mode -+ * self_path -+ */ -+static int ci_calc_self_path_settings(const struct ci_isp_datapath_desc *source, -+ const struct ci_isp_datapath_desc *self, -+ struct ci_isp_scale *scale_flag, -+ struct ci_isp_mi_ctrl *mrv_mi_ctrl) -+{ -+ u32 scaler_out_col_format; -+ u32 self_flag; -+ -+ WARN_ON(!(source != NULL)); -+ WARN_ON(!(scale_flag != NULL)); -+ WARN_ON(!(mrv_mi_ctrl != NULL)); -+ -+ /* assume datapath deactivation if no selfpath pointer is given) */ -+ if (self) -+ self_flag = self->flags; -+ else -+ self_flag = 0; -+ -+ /* initialize the given parameters */ -+ memset(scale_flag, 0, sizeof(struct ci_isp_scale)); -+ scale_flag->scale_hy = RSZ_SCALER_BYPASS; -+ scale_flag->scale_hcb = RSZ_SCALER_BYPASS; -+ scale_flag->scale_hcr = RSZ_SCALER_BYPASS; -+ scale_flag->scale_vy = RSZ_SCALER_BYPASS; -+ scale_flag->scale_vc = RSZ_SCALER_BYPASS; -+ -+ if (self_flag & CI_ISP_DPD_ENABLE) { -+ -+ switch (self_flag & CI_ISP_DPD_MODE_MASK) { -+ case CI_ISP_DPD_MODE_ISPYC: -+ mrv_mi_ctrl->self_path = CI_ISP_PATH_ON; -+ scaler_out_col_format = CI_ISP_DPD_DMA_IN_422; -+ break; -+ case CI_ISP_DPD_MODE_DMAYC_ISP: -+ case CI_ISP_DPD_MODE_DMAYC_DIRECT: -+ mrv_mi_ctrl->self_path = CI_ISP_PATH_ON; -+ scaler_out_col_format = -+ self_flag & CI_ISP_DPD_DMA_IN_MASK; -+ break; -+ default: -+ eprintk("unsupported mode for self path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ if (self_flag & CI_ISP_DPD_NORESIZE) { -+ if (self_flag & CI_ISP_DPD_CSS_MASK) { -+ eprintk("in self path needs rezizer"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if (self_flag & -+ (CI_ISP_DPD_LUMA_HSHIFT | CI_ISP_DPD_LUMA_VSHIFT)) { -+ eprintk("n self path needs rezizer"); -+ return CI_STATUS_NOTSUPP; -+ } -+ /* changed to avoid LINT warnings (Warning 613) */ -+ if (self != NULL) { -+ if ((source->out_w != self->out_w) || -+ (source->out_h != self->out_h)) { -+ eprintk("sizes needs resizer"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } else { -+ WARN_ON(self == NULL); -+ } -+ } else { -+ /* changed to avoid LINT warnings (Warning 613) */ -+ if (self != NULL) { -+ /* upscaling only to factor -+ * SELF_UPSCALE_FACTOR_MAX possible -+ */ -+ if ((((u32) (source->out_w) * -+ SELF_UPSCALE_FACTOR_MAX) < -+ self->out_w) -+ || -+ (((u32) (source->out_h) * -+ SELF_UPSCALE_FACTOR_MAX) < -+ self->out_h)) { -+ eprintk("apability exceeded"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if ((self->out_w > -+ SELF_SCALER_WIDTH_MAX) -+ || (self->out_w < SCALER_MIN) -+ || (self->out_h < SCALER_MIN)) { -+ eprintk("out range exceeded"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } else { -+ WARN_ON(self == NULL); -+ } -+ /* Remember that the input picture width should be -+ * even if the scaler is used */ -+ -+ /* (otherwise the scaler may show unexpected -+ * behaviour in some rare cases) */ -+ if (source->out_w & 0x01) { -+ eprintk("width must be even!"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* calculate scale factors. */ -+ scaler_out_col_format = -+ ci_calc_scale_factors(source, self, scale_flag, -+ MARVIN_FEATURE_SSCALE_FACTORCALC); -+ } -+ -+ dprintk(2, "step1"); -+ /* figure out the input format setting */ -+ switch (scaler_out_col_format) { -+ case CI_ISP_DPD_DMA_IN_444: -+ mrv_mi_ctrl->mrv_mif_sp_in_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_444; -+ break; -+ case CI_ISP_DPD_DMA_IN_422: -+ mrv_mi_ctrl->mrv_mif_sp_in_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_422; -+ break; -+ case CI_ISP_DPD_DMA_IN_420: -+ mrv_mi_ctrl->mrv_mif_sp_in_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_420; -+ break; -+ /* no break, does not seem to be supported by HW */ -+ case CI_ISP_DPD_DMA_IN_411: -+ default: -+ eprintk("input color format not supported"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* figure out the output format setting */ -+ dprintk(2, "step2, self_flag is 0x%x", self_flag); -+ -+ switch (self_flag & CI_ISP_DPD_HWRGB_MASK) { -+ case CI_ISP_DPD_HWRGB_565: -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_RGB_565; -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ break; -+ case CI_ISP_DPD_HWRGB_666: -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_RGB_666; -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ break; -+ case CI_ISP_DPD_HWRGB_888: -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_RGB_888; -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ break; -+ case CI_ISP_DPD_YUV_420: -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_420; -+ break; -+ case CI_ISP_DPD_YUV_422: -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_422; -+ break; -+ case CI_ISP_DPD_YUV_NV12: -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_SEMI_PLANAR; -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_420; -+ break; -+ case CI_ISP_DPD_YUV_YUYV: -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_INTERLEAVED; -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ CI_ISP_MIF_COL_FORMAT_YCBCR_422; -+ break; -+ -+ case CI_ISP_DPD_HWRGB_OFF: -+ mrv_mi_ctrl->mrv_mif_sp_out_form = -+ mrv_mi_ctrl->mrv_mif_sp_in_form; -+ mrv_mi_ctrl->mrv_mif_sp_pic_form = -+ CI_ISP_MIF_PIC_FORM_PLANAR; -+ break; -+ default: -+ eprintk("output color format not supported"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* picture flipping / rotation */ -+ dprintk(2, "step3"); -+ -+ switch (self_flag & -+ (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_V_FLIP | -+ CI_ISP_DPD_H_FLIP)) { -+ case (CI_ISP_DPD_H_FLIP): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_HORIZONTAL_FLIP; -+ break; -+ case (CI_ISP_DPD_V_FLIP): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_VERTICAL_FLIP; -+ break; -+ case (CI_ISP_DPD_V_FLIP | CI_ISP_DPD_H_FLIP): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_ROTATION_180_DEG; -+ break; -+ case (CI_ISP_DPD_90DEG_CCW): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_ROTATION_090_DEG; -+ break; -+ case (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_H_FLIP): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_ROT_270_V_FLIP; -+ break; -+ case (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_V_FLIP): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_ROT_090_V_FLIP; -+ break; -+ case (CI_ISP_DPD_90DEG_CCW | CI_ISP_DPD_V_FLIP | -+ CI_ISP_DPD_H_FLIP): -+ mrv_mi_ctrl->mrv_mif_sp_mode = -+ CI_ISP_MIF_SP_ROTATION_270_DEG; -+ break; -+ default: -+ mrv_mi_ctrl->mrv_mif_sp_mode = CI_ISP_MIF_SP_ORIGINAL; -+ break; -+ } -+ -+ } else { -+ mrv_mi_ctrl->self_path = CI_ISP_PATH_OFF; -+ } -+ -+ dprintk(2, "step4"); -+ /*mrv_mi_ctrl->mrv_mif_sp_pic_form = CI_ISP_MIF_PIC_FORM_PLANAR;*/ -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Translates the given memory interface configuration struct -+ * into appropriate values to program the data path multiplexers. -+ */ -+static int ci_calc_dp_mux_settings(const struct ci_isp_mi_ctrl *mi_ctrl, -+ enum ci_isp_ycs_chn_mode *peYcsChnMode, -+ enum ci_isp_dp_switch *peDpSwitch) -+{ -+ switch (mi_ctrl->main_path) { -+ case CI_ISP_PATH_RAW8: -+ case CI_ISP_PATH_RAW816: -+ *peDpSwitch = CI_ISP_DP_RAW; -+ *peYcsChnMode = CI_ISP_YCS_MVRaw; -+ if (mi_ctrl->self_path != CI_ISP_PATH_OFF) { -+ eprintk("ombined with RAW mode of main path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ break; -+ -+ case CI_ISP_PATH_JPE: -+ *peDpSwitch = CI_ISP_DP_JPEG; -+ if (mi_ctrl->self_path != CI_ISP_PATH_OFF) -+ *peYcsChnMode = CI_ISP_YCS_MV_SP; -+ else -+ *peYcsChnMode = CI_ISP_YCS_MV; -+ break; -+ -+ case CI_ISP_PATH_ON: -+ *peDpSwitch = CI_ISP_DP_MV; -+ if (mi_ctrl->self_path != CI_ISP_PATH_OFF) -+ *peYcsChnMode = CI_ISP_YCS_MV_SP; -+ else -+ *peYcsChnMode = CI_ISP_YCS_MV; -+ break; -+ -+ case CI_ISP_PATH_OFF: -+ *peDpSwitch = CI_ISP_DP_MV; -+ if (mi_ctrl->self_path != CI_ISP_PATH_OFF) -+ *peYcsChnMode = CI_ISP_YCS_SP; -+ else -+ *peYcsChnMode = CI_ISP_YCS_OFF; -+ break; -+ -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* the windows to cut away black pixels and to zoom/crop the */ -+#define ISPWND_COMBINE_WNDS 0x00000001 -+/* image must be combined before they are applyed to the marvin registers */ -+/* call of the ci_isp_set_output_formatter() routine necessary */ -+#define ISPWND_APPLY_OUTFORM 0x00000002 -+/* call of the ci_isp_is_set_config() routine necessary */ -+#define ISPWND_APPLY_ISCONF 0x00000004 -+/* no cropping supported at all */ -+#define ISPWND_NO_CROPPING 0x00000008 -+ -+/* -+ * Returns information about how to combine black pixel and -+ * zoom/crop windows for programming the ISP output formatter and the image -+ * stabilization unit for the given marvin derivative and ISP path. -+ */ -+static u32 ci_get_isp_wnd_style(enum ci_isp_path isp_path) -+{ -+ u32 res = 0; -+ -+ /* output formatter exists at ISP input */ -+ /* image stabilization in both bayer and YCbCr paths */ -+ if ((isp_path == CI_ISP_PATH_BAYER) || -+ (isp_path == CI_ISP_PATH_YCBCR)) -+ /*we need to program the output formatter with the blackline -+ * window and */ -+ res = ISPWND_APPLY_OUTFORM | ISPWND_APPLY_ISCONF; -+ else -+ res = ISPWND_COMBINE_WNDS | ISPWND_APPLY_OUTFORM; -+ -+ return res; -+} -+ -+/* -+ * the given windows for cutting away blacklines coming from -+ * the image sensor and further cropping of the image for other -+ * purposes like e.g. digital zoom to the output formatter and/or -+ * image stabilisation modules of Marvins ISP. -+ */ -+static int ci_set_isp_windows(const struct ci_sensor_config *isi_sensor_config, -+ const struct ci_isp_window *wnd_blackline, -+ const struct ci_isp_window *wnd_zoom_crop) -+{ -+ struct ci_isp_window wnd_out_form; -+ struct ci_isp_is_config is_conf; -+ enum ci_isp_path isp_path; -+ u32 wnd_style; -+ -+ memset(&wnd_out_form, 0, sizeof(wnd_out_form)); -+ memset(&is_conf, 0, sizeof(is_conf)); -+ -+ /* -+ * figure out the path through the ISP to process the data from the -+ * image sensor -+ */ -+ isp_path = ci_isp_select_path(isi_sensor_config, NULL); -+ if (isp_path == CI_ISP_PATH_UNKNOWN) { -+ eprintk("detect marvin ISP path to use"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* -+ * get the recommended way to configure output formatter and/or -+ * image stabilization -+ */ -+ wnd_style = ci_get_isp_wnd_style(isp_path); -+ if (wnd_style & ISPWND_NO_CROPPING) { -+ /* -+ * cropping not possible -> make sure that it is *not* -+ * supposed to be used -+ */ -+ u16 isiX; -+ u16 isiY; -+ /* changed to avoid LINT warnings (Warning 534) */ -+ (void)ci_sensor_res2size(isi_sensor_config->res, &isiX, &isiY); -+ if ((wnd_zoom_crop->hsize != isiX) -+ || (wnd_zoom_crop->vsize != isiY) -+ || (wnd_zoom_crop->hoffs != 0) -+ || (wnd_zoom_crop->voffs != 0)) { -+ eprintk("in selected ISP data path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ if ((wnd_blackline->hsize != isiX) || -+ (wnd_blackline->vsize != isiY) || -+ (wnd_blackline->hoffs != 0) || -+ (wnd_blackline->voffs != 0)) { -+ eprintk("supported in selected ISP data path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } -+ -+ /* -+ * The image stabilization is allowed to move the window in both -+ * directions by the same amount of pixels we have calculated for -+ * the offsets. The initial image stabilization window is equal to -+ * the zoom/crop window -+ */ -+ is_conf.max_dx = wnd_zoom_crop->hoffs; -+ is_conf.max_dy = wnd_zoom_crop->voffs; -+ is_conf.mrv_is_window = *wnd_zoom_crop; -+ -+ /* combine both blackline and zoom/crop window */ -+ if (wnd_style & ISPWND_COMBINE_WNDS) { -+ /* combine both blackline and zoom/crop window */ -+ wnd_out_form = *wnd_zoom_crop; -+ wnd_out_form.voffs += wnd_blackline->voffs; -+ wnd_out_form.hoffs += wnd_blackline->hoffs; -+ is_conf.mrv_is_window = wnd_out_form; -+ if (wnd_style & ISPWND_APPLY_OUTFORM) { -+ /* -+ * if the output formatter is to be used, offsets -+ * are cut away there, so -+ * we don't need additional ones in the imags -+ * stabilization unit -+ */ -+ is_conf.mrv_is_window.hoffs = 0; -+ is_conf.mrv_is_window.voffs = 0; -+ } -+ } else { -+ /* -+ * do not combine windows --> blacklines done with output -+ * formatter, zoom/cropping done with image stabilization -+ */ -+ wnd_out_form = *wnd_blackline; -+ is_conf.mrv_is_window = *wnd_zoom_crop; -+ } -+ -+ /* finally, apply the settings to marvin */ -+ if (wnd_style & ISPWND_APPLY_OUTFORM) { -+ ci_isp_set_output_formatter(&wnd_out_form, -+ CI_ISP_CFG_UPDATE_IMMEDIATE); -+ } -+ if (wnd_style & ISPWND_APPLY_ISCONF) { -+ int res = ci_isp_is_set_config(&is_conf); -+ if (res != CI_STATUS_SUCCESS) { -+ eprintk("set image stabilization config"); -+ return res; -+ } -+ } -+ -+ /* success - remember our virtual settings */ -+ last_isp_wnds.wnd_blacklines = *wnd_blackline; -+ last_isp_wnds.wnd_zoom_crop = *wnd_zoom_crop; -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* sets extended YCbCr mode */ -+static int ci_ext_ycb_cr_mode(const struct ci_isp_datapath_desc *path) -+{ -+ u32 main_flag; -+ -+ WARN_ON(!(path != NULL)); -+ -+ /* assume datapath deactivation if no selfpath pointer is given) */ -+ if (path) -+ main_flag = path->flags; -+ else -+ main_flag = 0; -+ -+ /* if flag CI_ISP_DPD_YCBCREXT is set set extended YCbCr mode */ -+ if (main_flag & CI_ISP_DPD_ENABLE) { -+ if (main_flag & CI_ISP_DPD_YCBCREXT) -+ ci_isp_set_ext_ycmode(); -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Configures main and self data pathes and scaler for data coming from the ISP. -+ * -+ * Following MARVIN subsystems are programmed: -+ * - ISP output formatter -+ * - Image stabilization module -+ * - YC-Splitter -+ * - Self path DMA-read multiplexer -+ * - Main path multiplexer -+ * - Main & Self path resizer -+ * - Small output unit -+ * - Memory Interface (MI) input source, en/disable and data format -+ * -+ * Following MARVIN subsystems are *NOT* programmed: -+ * - All ISP functionality but the output formatter & image stabilization module -+ * - color Processing block -+ * - JPEG encode subsystem (quantisation tables etc.) -+ * - Memory Interface (MI) output buffer addresses and sizes -+ */ -+int ci_datapath_isp(const struct ci_pl_system_config *sys_conf, -+ const struct ci_sensor_config *isi_config, -+ const struct ci_isp_datapath_desc *main, -+ const struct ci_isp_datapath_desc *self, int zoom) -+{ -+ int res; -+ /* -+ * copy of flags for main and self path to simplify access (no -+ * pointer de-reference) -+ */ -+ u32 main_flag; -+ u32 self_flag; -+ /* resolution from sensor configuration */ -+ u16 isiX; -+ u16 isiY; -+ /* things to apply to MARVIN */ -+ struct ci_isp_scale scale_main; -+ struct ci_isp_scale scale_flag; -+ enum ci_isp_ycs_chn_mode chn_mode = 0; -+ enum ci_isp_dp_switch dp_switch = 0; -+ struct ci_isp_mi_ctrl mrv_mi_ctrl; -+ struct ci_isp_datapath_desc source; -+ /* ISP windowing because of cutting away blacklines from the sensor */ -+ struct ci_isp_window wnd_blackline; -+ /* ISP windowing because of aspect ratio change and/or zoom */ -+ struct ci_isp_window wnd_zoom_crop; -+ -+ const struct ci_isp_datapath_desc *target = NULL; -+ -+ /* assume dapapath deactivation for not provided descriptors */ -+ main_flag = 0; -+ self_flag = 0; -+ if (main) -+ main_flag = main->flags; /* 0x012 */ -+ -+ if (self) -+ self_flag = self->flags; /* 0x10015 */ -+ -+ /* initialize variables on the stack */ -+ res = CI_STATUS_SUCCESS; -+ /* changed to avoid LINT warnings (Warning 534) */ -+ (void)ci_sensor_res2size(isi_config->res, &isiX, &isiY); -+ memset(&mrv_mi_ctrl, 0, sizeof(struct ci_isp_mi_ctrl)); -+ memset(&wnd_blackline, 0, sizeof(wnd_blackline)); -+ memset(&wnd_zoom_crop, 0, sizeof(wnd_zoom_crop)); -+ -+ /* -+ * ISP Windowing - fill in wnd_out_form, apply_out_form, is_conf and -+ * apply_is_conf -+ */ -+ -+ /* -+ * by default, size of both blackline and zoom/crop window -+ * is what the camera delivers. -+ */ -+ -+ /* (no cropping, no offset) */ -+ wnd_blackline.hsize = isiX; -+ wnd_blackline.vsize = isiY; -+ wnd_zoom_crop = wnd_blackline; -+ -+ /* -+ * check if we have to crop because of aspect ratio -+ * preservement of an -+ */ -+ -+ /* output channel */ -+ if ((main_flag & CI_ISP_DPD_ENABLE) && -+ (main_flag & CI_ISP_DPD_KEEPRATIO)) { -+ target = main; -+ } -+ if ((self_flag & CI_ISP_DPD_ENABLE) && -+ (self_flag & CI_ISP_DPD_KEEPRATIO)) { -+ if (target) { -+ eprintk("only allowed for one path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ target = self; -+ } -+ -+ /* if so, calculate the cropping */ -+ if (target) { -+ u32 aspect_cam = (0x1000 * ((u32) isiX)) / isiY; -+ u32 aspect_target = (0x1000 * ((u32) (target->out_w))) / -+ target->out_h; -+ if (aspect_cam < aspect_target) { -+ /* -+ * camera aspect is more 'portrait-like' as -+ * target aspect. We have to crop the -+ * camera picture by cutting off a bit of -+ * the top & bottom changed to avoid LINT -+ * warnings (Info 734) -+ */ -+ wnd_zoom_crop.vsize = (u16) (((u32) isiX * -+ (u32) (target->out_h)) / target->out_w); -+ } else { -+ /* camera aspect is more 'landscape-like' -+ * as target aspect. We have to crop the -+ * camera picture by cutting off a bit of -+ * the left and right changed to avoid LINT -+ * warnings (Info 734) */ -+ wnd_zoom_crop.hsize = (u16) (((u32) isiY * -+ (u32) (target->out_w)) / target->out_h); -+ } -+ } -+ -+ /* -+ * now, we may also want to do digital zoom. If so, we need -+ * to shrink the ISP window by the desired zoom factor. -+ */ -+ if (zoom > 0) { -+ /* changed to avoid LINT warnings (Warning 573) */ -+ wnd_zoom_crop.vsize = (u16) (((u32) (wnd_zoom_crop.vsize) * -+ 1024) / (1024 + (u32) zoom)); -+ /* changed to avoid LINT warnings (Warning 573) */ -+ wnd_zoom_crop.hsize = (u16) (((u32) (wnd_zoom_crop.hsize) * -+ 1024) / (1024 + (u32) zoom)); -+ } -+ /* -+ * Remember that the output formatter h_size should be -+ * even if the scaler is used -+ * (otherwise the scaler may show unexpected behaviour in -+ * some rare cases) -+ */ -+ wnd_zoom_crop.hsize &= ~0x01; -+ /* -+ * At last, we care about the offset of the ISP window. We -+ * want it centered on the image data delivered by the -+ * sensor (not counting possible black lines) -+ */ -+ wnd_zoom_crop.hoffs = (isiX - wnd_zoom_crop.hsize) / 2; -+ wnd_zoom_crop.voffs = (isiY - wnd_zoom_crop.vsize) / 2; -+ /* -+ * If the image sensor delivers blacklines, we cut them -+ * away with moving wnd_blackline window by the given -+ * amount of lines -+ */ -+ switch (isi_config->bls) { -+ /* no black lines */ -+ case SENSOR_BLS_OFF: -+ break; -+ /* two black lines at frame start */ -+ case SENSOR_BLS_TWO_LINES: -+ wnd_blackline.voffs += 2; -+ break; -+ /* two black lines at frame start and two at the end */ -+ case SENSOR_BLS_FOUR_LINES: -+ wnd_blackline.voffs += 2; -+ break; -+ default: -+ eprintk("config"); -+ return CI_STATUS_NOTSUPP; -+ } -+ /* -+ * if we are instructed to show the blacklines and the -+ * sensor generates them, -+ * we have to move the ISP windows to the upper border of -+ * the whole sensor, and deny the image stabilization to -+ * move around the window in vertical direction. -+ */ -+ if (isi_config->bls != SENSOR_BLS_OFF) { -+ if (((main_flag & CI_ISP_DPD_ENABLE) -+ && (main_flag & CI_ISP_DPD_BLACKLINES_TOP)) -+ || ((self_flag & CI_ISP_DPD_ENABLE) -+ && (self_flag & CI_ISP_DPD_BLACKLINES_TOP))) { -+ if ((main_flag & CI_ISP_DPD_ENABLE) -+ && (self_flag & CI_ISP_DPD_ENABLE) -+ && ((main_flag & CI_ISP_DPD_BLACKLINES_TOP) -+ != (self_flag & CI_ISP_DPD_BLACKLINES_TOP))) { -+ eprintk("and self path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ wnd_blackline.voffs = 0; -+ wnd_zoom_crop.voffs = 0; -+ } -+ } -+ -+ source.out_w = wnd_zoom_crop.hsize; -+ source.out_h = wnd_zoom_crop.vsize; -+ source.flags = CI_ISP_DPD_DMA_IN_422; -+ -+ /*to use crop set crop_flag first*/ -+ if (crop_flag) { -+ wnd_zoom_crop.hsize = main->out_w; -+ wnd_zoom_crop.vsize = main->out_h; -+ } -+ -+ dprintk(1, "source.out_w %d, source.out_h %d", -+ source.out_w, source.out_h); -+ if (main) -+ dprintk(1, "main.out_w %d, main.out_h %d", -+ main->out_w, main->out_h); -+ if (self) -+ dprintk(1, "self.out_w %d, self.out_h %d", -+ self->out_w, self->out_h); -+ -+ /* -+ * At this point, wnd_zoom_crop and wnd_blackline contain -+ * the window sizes that reflect the users request. We have -+ * to configure the ISP output formatter and the image -+ * stabilization formatter in order to achieve this, but -+ * how they interact is highly dependant of the curr -+ * marvin derivative and which datapath of the ISP is -+ * activated. Therefore, translating wnd_zoom_crop and -+ * wnd_blackline into marvin register settings is a bit -+ * complicated and will be done by the -+ * ci_set_isp_windows() routine. -+ */ -+ -+ /* ISP Window */ -+ /* MAIN path - fill in main_path, scale_main and main_rsz_lut */ -+ /* basic selfpath settings */ -+ res = ci_calc_main_path_settings(&source, main, &scale_main, -+ &mrv_mi_ctrl); -+ if (res != CI_STATUS_SUCCESS) -+ return res; -+ -+ /* additional settings specific for main path fed from ISP */ -+ if (main_flag & CI_ISP_DPD_ENABLE) { -+ switch (main_flag & CI_ISP_DPD_MODE_MASK) { -+ case CI_ISP_DPD_MODE_ISPYC: -+ case CI_ISP_DPD_MODE_ISPRAW: -+ case CI_ISP_DPD_MODE_ISPRAW_16B: -+ case CI_ISP_DPD_MODE_ISPJPEG: -+ /* allowed cases, just proceed */ -+ break; -+ default: -+ eprintk("data coming from the ISP"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } -+ -+ /* SELF path - fill in self_path & scale_flag */ -+ /* basic selfpath settings */ -+ res = ci_calc_self_path_settings(&source, self, &scale_flag, -+ &mrv_mi_ctrl); -+ if (res != CI_STATUS_SUCCESS) -+ return res; -+ -+ if (sys_conf->isp_cfg.flags.ycbcr_non_cosited) -+ mrv_mi_ctrl.mrv_mif_sp_in_phase = mrv_mif_col_phase_non_cosited; -+ else -+ mrv_mi_ctrl.mrv_mif_sp_in_phase = mrv_mif_col_phase_cosited; -+ if (sys_conf->isp_cfg.flags.ycbcr_full_range) -+ mrv_mi_ctrl.mrv_mif_sp_in_range = mrv_mif_col_range_full; -+ else -+ mrv_mi_ctrl.mrv_mif_sp_in_range = mrv_mif_col_range_std; -+ if (self_flag & CI_ISP_DPD_ENABLE) { -+ switch (self_flag & CI_ISP_DPD_MODE_MASK) { -+ case CI_ISP_DPD_MODE_ISPYC: -+ /* only allowed case, just proceed */ -+ break; -+ default: -+ eprintk("data coming from the ISP"); -+ return CI_STATUS_NOTSUPP; -+ } -+ } -+ -+ /* Datapath multiplexers */ -+ res = ci_calc_dp_mux_settings(&mrv_mi_ctrl, &chn_mode, &dp_switch); -+ if (res != CI_STATUS_SUCCESS) -+ return res; -+ -+ /* hardcoded global settings of the memory interface */ -+ mrv_mi_ctrl.byte_swap_enable = false; -+ -+ mrv_mi_ctrl.init_vals = CI_ISP_MIF_INIT_OFFSAndBase; -+ -+ /* -+ * If we reach this point, we have collected all values to program -+ * the MARVIN for the requested datapath setup. Now all we've left -+ * to do is apply these to MARVINs register set. For this, we -+ * mostly use the low level MARVIN driver routines. -+ */ -+ /*to use crop set crop_flag first*/ -+ if (crop_flag) { -+ wnd_blackline.hsize = main->out_w; -+ wnd_blackline.vsize = main->out_h; -+ } -+ -+ res = ci_set_isp_windows(isi_config, &wnd_blackline, -+ &wnd_zoom_crop); -+ if (res != CI_STATUS_SUCCESS) { -+ eprintk("failed to set ISP window configuration"); -+ return res; -+ } -+ res = ci_isp_set_data_path(chn_mode, dp_switch); -+ if (res != CI_STATUS_SUCCESS) -+ return res; -+ -+ res = ci_isp_set_mipi_smia(isi_config->mode); -+ if (res != CI_STATUS_SUCCESS) -+ return res; -+ -+ if (mrv_mi_ctrl.self_path != CI_ISP_PATH_OFF) -+ ci_isp_res_set_self_resize(&scale_flag, -+ CI_ISP_CFG_UPDATE_IMMEDIATE, -+ ci_get_rsz_lut(self_flag)); -+ -+ if (mrv_mi_ctrl.main_path != CI_ISP_PATH_OFF) -+ ci_isp_res_set_main_resize(&scale_main, -+ CI_ISP_CFG_UPDATE_IMMEDIATE, -+ ci_get_rsz_lut(main_flag)); -+ -+ ci_isp_set_dma_read_mode(CI_ISP_DMA_RD_OFF, -+ CI_ISP_CFG_UPDATE_IMMEDIATE); -+ -+ res = ci_isp_mif_set_path_and_orientation(&mrv_mi_ctrl); -+ if (res != CI_STATUS_SUCCESS) { -+ eprintk("failed to set MI path and orientation"); -+ return res; -+ } -+ -+ /* here the extended YCbCr mode is configured */ -+ if (sys_conf->isp_cfg.flags.ycbcr_full_range) -+ res = ci_ext_ycb_cr_mode(main); -+ else -+ (void)ci_isp_set_yc_mode(); -+ -+ if (res != CI_STATUS_SUCCESS) { -+ eprintk("failed to set ISP YCbCr extended mode"); -+ return res; -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c b/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c -new file mode 100644 -index 0000000..56891c1 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/mrstisp_hw.c -@@ -0,0 +1,1622 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * Copyright (c) Silicon Image 2008 www.siliconimage.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+ -+static unsigned long jiffies_start; -+ -+void mrst_timer_start(void) -+{ -+ jiffies_start = jiffies; -+} -+ -+void mrst_timer_stop(void) -+{ -+ jiffies_start = 0; -+} -+ -+unsigned long mrst_get_micro_sec(void) -+{ -+ unsigned long time_diff = 0; -+ -+ time_diff = jiffies - jiffies_start; -+ -+ return jiffies_to_msecs(time_diff); -+} -+ -+/* -+ * Returns the ISP hardware ID. -+ */ -+static u32 ci_isp_get_ci_isp_id(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 result = 0; -+ -+ result = REG_GET_SLICE(mrv_reg->vi_id, MRV_REV_ID); -+ -+ return result; -+} -+ -+/* -+ * Gets the hardware ID and compares it with the expected one. -+ */ -+static int ci_isp_verify_chip_id(void) -+{ -+ u32 mrv_id = ci_isp_get_ci_isp_id(); -+ dprintk(1, "HW-Id: 0x%08X", mrv_id); -+ -+ if (mrv_id != MARVIN_FEATURE_CHIP_ID) { -+ eprintk("HW-Id does not match! read:0x%08X, expected:0x%08X", -+ mrv_id, MARVIN_FEATURE_CHIP_ID); -+ return CI_STATUS_FAILURE; -+ } -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Triggers an entire reset of MARVIN (equaling an asynchronous -+ * hardware reset). -+ * Checks the hardware ID. A debug warning is issued if the -+ * module ID does not match the expected ID. -+ * Enables all clocks of all sub-modules. -+ * MARVIN is in idle state afterwards. -+ */ -+void ci_isp_init(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* verify ID, but no consequences if it doesn't match */ -+ (void)ci_isp_verify_chip_id(); -+ -+ /* enable main clock */ -+ REG_SET_SLICE(mrv_reg->vi_ccl, MRV_VI_CCLFDIS, MRV_VI_CCLFDIS_ENABLE); -+ -+ /* -+ * enable all clocks to make sure that all submodules will be able to -+ * perform the reset correctly -+ */ -+ REG_SET_SLICE(mrv_reg->vi_iccl, MRV_VI_ALL_CLK_ENABLE, ENABLE); -+ -+ /* -+ * Reset of the entire MARVIN triggered by software. The minimum time -+ * permitted by mdelay ensures enough delay. -+ */ -+ -+ /* The reset bit will be cleared by the reset itself. */ -+ -+ /* -+ * The default value of the clock registers is all clocks on. So we -+ * don't have to enable the clocks again afterwards. -+ */ -+ -+ REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_MARVIN_RST, ON); -+ /*mdelay(CI_ISP_DELAY_AFTER_RESET);*/ -+ msleep(CI_ISP_DELAY_AFTER_RESET); -+} -+ -+void ci_isp_off(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* enable main clock */ -+ REG_SET_SLICE(mrv_reg->vi_ccl, MRV_VI_CCLFDIS, -+ MRV_VI_CCLFDIS_DISABLE); -+ -+ /* -+ * enable all clocks to make sure that all submodules will be able to -+ * perform the reset correctly -+ */ -+ REG_SET_SLICE(mrv_reg->vi_iccl, MRV_VI_ALL_CLK_ENABLE, DISABLE); -+} -+ -+/* -+ * Returns the mask for the frame end interrupts, which are -+ * used for Isp. -+ */ -+u32 ci_isp_get_frame_end_irq_mask_isp(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ switch (REG_GET_SLICE(mrv_reg->vi_dpcl, MRV_VI_DMA_SWITCH)) { -+ /* -+ * 2: path to image effects block (i.e. replacement for data coming -+ * from the ISP) -+ */ -+ case MRV_VI_DMA_SWITCH_IE: -+ /* datapath is used by DMA */ -+ return 0; -+ /* -+ * 0: direct path to self path mux -+ */ -+ case MRV_VI_DMA_SWITCH_SELF: -+ /* -+ * 1: path to superimpose block -+ */ -+ case MRV_VI_DMA_SWITCH_SI: -+ /* -+ * 3: direct path to JPEG encoder (R2B-buffer-less encodein mode) -+ */ -+ case MRV_VI_DMA_SWITCH_JPG: -+ default: -+ /* main and/or self path depends on the YC-splitter setting */ -+ { -+ switch (REG_GET_SLICE -+ (mrv_reg->vi_dpcl, MRV_VI_CHAN_MODE)) { -+ case MRV_VI_CHAN_MODE_MP: -+ return MRV_MI_MP_FRAME_END_MASK; -+ case MRV_VI_CHAN_MODE_SP: -+ return MRV_MI_SP_FRAME_END_MASK; -+ case MRV_VI_CHAN_MODE_MP_SP: -+ return MRV_MI_MP_FRAME_END_MASK | -+ MRV_MI_SP_FRAME_END_MASK; -+ default: -+ return 0; -+ } -+ } -+ } -+ -+} -+ -+/* -+ * Programs the number of frames to capture. Clears frame end -+ * interrupt to allow waiting in ci_isp_wait_for_frame_end(). -+ * Enables the ISP input acquisition and output formatter. -+ * If immediate=false, the hardware assures that enabling is -+ * done frame synchronously. -+ */ -+void ci_isp_start(u16 number_of_frames, -+ enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl); -+ u32 eof_irq_mask = ci_isp_get_frame_end_irq_mask_isp(); -+ -+ /* max. 10 bits allowed */ -+ WARN_ON(!(number_of_frames <= MRV_ISP_ACQ_NR_FRAMES_MAX)); -+ -+ REG_SET_SLICE(mrv_reg->isp_acq_nr_frames, MRV_ISP_ACQ_NR_FRAMES, -+ number_of_frames); -+ -+ /* clear frame end interrupt */ -+ REG_WRITE(mrv_reg->mi_icr, eof_irq_mask); -+ -+ /* Enable ISP input Acquisition and output formatter. */ -+ -+ /* -+ * Input Acquisition is always enabled synchronous to the image sensor -+ * (no configuration update required). As soon as the input -+ * acquisition is started bit in_enable_shd in the register -+ * isp_flags_shd is set by hardware. In the following a frame end -+ * recognized by the input acquisition unit leads to -+ * ris_in_frame_end=1 in isp_ris. However a recognized frame end and -+ * no signaled errors are no guarantee for a valid configuration. -+ */ -+ -+ /* -+ * The output formatter is enabled frame synchronously according to -+ * the internal sync signals. Bit MRV_GEN_CFG_UPD has to be set. Bit -+ * isp_on_shd in isp_flags_shd is set when the output formatter is -+ * started. A recognized frame end is signaled with ris_out_frame_end -+ * in isp_ris. -+ */ -+ -+ /* -+ * The configuration of the input acquisition and the output -+ * formatter has to be correct to generate proper internal sync -+ * signals and thus a proper frame-synchronous update signal. -+ */ -+ -+ /* If the output formatter does not start check the following: -+ * sync polarities -+ * sample edge -+ * mode in register isp_ctrl -+ * sampling window of input acquisition <= picture size of image -+ * sensor -+ * output formatter window <= sampling window of input -+ * acquisition -+ */ -+ -+ /* -+ * If problems with the window sizes are suspected preferably add some -+ * offsets and reduce the window sizes, so that the above relations -+ * are true by all means. -+ */ -+ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ENABLE); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ /* -+ * MRV_ISP_ISP_CFG_UPD is used instead of -+ * MRV_ISP_ISP_GEN_CFG_UPD. This updates the configuration -+ * right away and MARVIN is ready to aquire the next incoming -+ * frame. -+ */ -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CFG_UPD, ENABLE); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ /* no update from within this function -+ * but enable ISP and Input */ -+ break; -+ default: -+ break; -+ } -+ -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_INFORM_ENABLE, ENABLE); -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_ENABLE, ENABLE); -+ REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl); -+ -+ dprintk(3, "ISP_CTRL = 0x%08X", mrv_reg->isp_ctrl); -+} -+ -+/* -+ * Clear frame end interrupt to allow waiting in -+ * ci_isp_wait_for_frame_end(). Disable output formatter (frame -+ * synchronously). -+ */ -+void ci_isp_stop(enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl); -+ u32 eof_irq_mask = ci_isp_get_frame_end_irq_mask_isp(); -+ -+ /* clear frame end interrupt */ -+ REG_WRITE(mrv_reg->mi_icr, eof_irq_mask); -+ /* disable output formatter */ -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_ENABLE, DISABLE); -+ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ENABLE); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CFG_UPD, ENABLE); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ break; -+ default: -+ break; -+ } -+ -+ REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl); -+} -+ -+/* -+ * Changes the data path settings. -+ */ -+int ci_isp_set_data_path(enum ci_isp_ycs_chn_mode ycs_chn_mode, -+ enum ci_isp_dp_switch dp_switch) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 vi_dpcl = REG_READ(mrv_reg->vi_dpcl); -+ u32 vi_chan_mode; -+ u32 vi_mp_mux; -+ -+ /* get desired setting for ycs_chan_mode (or vi_chan_mode) bits */ -+ switch (ycs_chn_mode) { -+ case CI_ISP_YCS_OFF: -+ vi_chan_mode = MRV_VI_CHAN_MODE_OFF; -+ break; -+ case CI_ISP_YCS_Y: -+ vi_chan_mode = MRV_VI_CHAN_MODE_Y; -+ break; -+ case CI_ISP_YCS_MVRaw: -+ vi_chan_mode = MRV_VI_CHAN_MODE_MP_RAW; -+ break; -+ case CI_ISP_YCS_MV: -+ vi_chan_mode = MRV_VI_CHAN_MODE_MP; -+ break; -+ case CI_ISP_YCS_SP: -+ vi_chan_mode = MRV_VI_CHAN_MODE_SP; -+ break; -+ case CI_ISP_YCS_MV_SP: -+ vi_chan_mode = MRV_VI_CHAN_MODE_MP_SP; -+ break; -+ default: -+ eprintk("unknown value for ycs_chn_mode"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ if (vi_chan_mode & ~(MRV_VI_CHAN_MODE_MASK >> MRV_VI_CHAN_MODE_SHIFT)) { -+ eprintk("enum ci_isp_ycs_chn_mode not supported"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* get desired setting for vi_dp_switch (or vi_dp_mux) bits */ -+ switch (dp_switch) { -+ case CI_ISP_DP_RAW: -+ vi_mp_mux = MRV_VI_MP_MUX_RAW; -+ break; -+ case CI_ISP_DP_JPEG: -+ vi_mp_mux = MRV_VI_MP_MUX_JPEG; -+ break; -+ case CI_ISP_DP_MV: -+ vi_mp_mux = MRV_VI_MP_MUX_MP; -+ break; -+ default: -+ eprintk("unknown value for dp_switch"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ if (vi_mp_mux & ~MRV_VI_MP_MUX_MASK) { -+ eprintk("dp_switch value not supported"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* program settings into MARVIN vi_dpcl register */ -+ REG_SET_SLICE(vi_dpcl, MRV_VI_CHAN_MODE, vi_chan_mode); -+ REG_SET_SLICE(vi_dpcl, MRV_VI_MP_MUX, vi_mp_mux); -+ REG_WRITE(mrv_reg->vi_dpcl, vi_dpcl); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Changes the data path settings to SMIA or MIPI. -+ */ -+int ci_isp_set_mipi_smia(u32 mode) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 if_select; -+ -+ /* get desired setting for if_select bits */ -+ switch (mode) { -+ case SENSOR_MODE_SMIA: -+ if_select = MRV_IF_SELECT_SMIA; -+ break; -+ case SENSOR_MODE_MIPI: -+ if_select = MRV_IF_SELECT_MIPI; -+ break; -+ case SENSOR_MODE_BAYER: -+ case SENSOR_MODE_BT601: -+ case SENSOR_MODE_BT656: -+ case SENSOR_MODE_PICT: -+ case SENSOR_MODE_DATA: -+ case SENSOR_MODE_BAY_BT656: -+ case SENSOR_MODE_RAW_BT656: -+ if_select = MRV_IF_SELECT_PAR; -+ break; -+ default: -+ eprintk("unknown value for mode"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ /* program settings into MARVIN vi_dpcl register */ -+ REG_SET_SLICE(mrv_reg->vi_dpcl, MRV_IF_SELECT, if_select); -+ -+ if (if_select == MRV_IF_SELECT_MIPI) { -+ REG_WRITE(mrv_reg->mipi_ctrl, 0x1001); /*XXX FLUSH_FIFO? */ -+ /* REG_WRITE(mrv_reg->mipi_ctrl, 0x0001); FLUSH_FIFO? */ -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Waits until the specified bits becomes signaled in the mi_ris -+ * register. -+ */ -+static int ci_isp_wait_for_mi(struct mrst_isp_device *intel, u32 bit_mask) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+#if 0 -+ int ret = 0; -+ INIT_COMPLETION(intel->mi_complete); -+ ret = wait_for_completion_interruptible_timeout(&intel->mi_complete, -+ 10*HZ); -+ if (ret == 0) { -+ eprintk("time out in wait for mi"); -+ /* -+ * Try to recover. Softreset of submodules (but not -+ * entire marvin) resets processing and status -+ * information, but not configuration register -+ * content. Bits are sticky. So we have to clear them. -+ * Reset affects the MARVIN 1..2 clock cycles after -+ * the bits are set to high. So we don't have to wait -+ * in software before clearing them. -+ */ -+ -+ /* -+ * Note that only modules with clock enabled will be -+ * affected. -+ */ -+ REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_ALL_SOFT_RST, ON); -+ REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_ALL_SOFT_RST, OFF); -+ mdelay(CI_ISP_DELAY_AFTER_RESET); -+ /* -+ * isp config update, neccessary to update v/h_size -+ * into shadow registers -+ */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_CFG_UPD, ON); -+ return CI_STATUS_FAILURE; -+ } -+ return CI_STATUS_SUCCESS; -+#endif -+ u32 irq; -+ static int err_frame_cnt; -+ mrst_timer_start(); -+ /* -+ * Wait for the curr BitMask. If the BitMask is zero, then it's no -+ * waiting. -+ */ -+ while ((mrv_reg->mi_ris & bit_mask) != bit_mask) { -+ -+ irq = REG_READ(mrv_reg->isp_ris); -+ if (irq & (MRV_ISP_RIS_DATA_LOSS_MASK -+ | MRV_ISP_RIS_PIC_SIZE_ERR_MASK)){ -+ err_frame_cnt++; -+ dprintk(1, "irq = 0x%x, err rumber = %d", irq, -+ err_frame_cnt); -+ } -+ if (mrst_get_micro_sec() > 1000) { -+ /* -+ * Note: Don't use REG_READ because content of -+ * registers would be already printed here. -+ */ -+ dprintk(1, "time out"); -+ mrst_timer_stop(); -+ /* -+ * Try to recover. Softreset of submodules (but not -+ * entire marvin) resets processing and status -+ * information, but not configuration register -+ * content. Bits are sticky. So we have to clear them. -+ * Reset affects the MARVIN 1..2 clock cycles after -+ * the bits are set to high. So we don't have to wait -+ * in software before clearing them. -+ */ -+ -+ /* -+ * Note that only modules with clock enabled will be -+ * affected. -+ */ -+ REG_SET_SLICE(mrv_reg->vi_ircl, -+ MRV_VI_ALL_SOFT_RST, ON); -+ REG_SET_SLICE(mrv_reg->vi_ircl, -+ MRV_VI_ALL_SOFT_RST, OFF); -+ /*mdelay(CI_ISP_DELAY_AFTER_RESET);*/ -+ msleep(CI_ISP_DELAY_AFTER_RESET); -+ /* -+ * isp config update, neccessary to update v/h_size -+ * into shadow registers -+ */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_CFG_UPD, -+ ON); -+ return CI_STATUS_FAILURE; -+ } -+ } -+ -+ mrst_timer_stop(); -+ if (REG_GET_SLICE(mrv_reg->isp_ris, MRV_ISP_RIS_DATA_LOSS)) -+ dprintk(1, "no failure, but MRV_ISPINT_DATA_LOSS"); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Waits until a frame is written to memory (frame end -+ * interrupt occurs). -+ * Waits for the frame end interrupt of the memory -+ * interface. -+ */ -+int ci_isp_wait_for_frame_end(struct mrst_isp_device *intel) -+{ -+ return ci_isp_wait_for_mi(intel, ci_isp_get_frame_end_irq_mask_isp()); -+} -+ -+/* -+ * Writes '0xFFFFFFFF' into all *_icr registers to clear all -+ * interrupts. -+ */ -+void ci_isp_reset_interrupt_status(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* ISP interrupt clear register */ -+ REG_SET_SLICE(mrv_reg->isp_icr, MRV_ISP_ICR_ALL, ON); -+ REG_SET_SLICE(mrv_reg->isp_err_clr, MRV_ISP_ALL_ERR, ON); -+ REG_SET_SLICE(mrv_reg->mi_icr, MRV_MI_ALLIRQS, ON); -+ /* JPEG error interrupt clear register */ -+ REG_SET_SLICE(mrv_reg->jpe_error_icr, MRV_JPE_ALL_ERR, ON); -+ /* JPEG status interrupt clear register */ -+ REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ALL_STAT, ON); -+ -+ REG_WRITE(mrv_reg->mipi_icr, 0xffffffff); /*XXX replace by a macro */ -+} -+ -+void mrst_isp_disable_interrupt(struct mrst_isp_device *isp) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE; -+ REG_SET_SLICE(mrv_reg->isp_imsc, MRV_ISP_IMSC_ALL, OFF); -+ REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_ALLIRQS, OFF); -+ REG_SET_SLICE(mrv_reg->jpe_error_imr, MRV_JPE_ALL_ERR, OFF); -+ REG_SET_SLICE(mrv_reg->jpe_status_imr, MRV_JPE_ALL_STAT, OFF); -+ REG_WRITE(mrv_reg->mipi_imsc, 0x00000000); -+} -+ -+void mrst_isp_enable_interrupt(struct mrst_isp_device *isp) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE; -+ -+ REG_SET_SLICE(mrv_reg->isp_imsc, MRV_ISP_IMSC_DATA_LOSS, ON); -+ REG_SET_SLICE(mrv_reg->isp_imsc, MRV_ISP_IMSC_PIC_SIZE_ERR, ON); -+ -+ REG_WRITE(mrv_reg->mi_imsc, MRV_MI_MP_FRAME_END_MASK); -+ -+ REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON); -+ -+ REG_SET_SLICE(mrv_reg->jpe_error_imr, MRV_JPE_ALL_ERR, ON); -+ REG_SET_SLICE(mrv_reg->jpe_status_imr, MRV_JPE_ALL_STAT, ON); -+ -+ REG_WRITE(mrv_reg->mipi_imsc, 0x00f00000); -+ -+ ci_isp_reset_interrupt_status(); -+} -+ -+/* -+ * Selects DMA read mode (i.e. sink of the data read from system -+ * memory by the DMA-read block). -+ * update_time is only used on Marvin3plus, -+ * on all other Marvin derivates immediate update is made -+ */ -+void ci_isp_set_dma_read_mode(enum ci_isp_dma_read_mode mode, -+ enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ /* added to avoid LINT warnings (Info 530) */ -+ u32 vi_dma_switch = 0; -+ /* added to avoid LINT warnings (Info 530) */ -+ u32 vi_dma_spmux = 0; -+ /* added to avoid LINT warnings (Info 530) */ -+ u32 vi_dma_iemux = 0; -+ /* added to avoid LINT warnings (Info 530) */ -+ int dma_jpeg_select = false; -+ -+ u32 vi_dpcl = REG_READ(mrv_reg->vi_dpcl); -+ -+ /* -+ * DMA-read feature connected through a dedicated DMA-read -+ * multiplexer. -+ */ -+ -+ /* Programming is done via vi_dpcl register only */ -+#define DMA_READ_MODE_PROGRAMMING_VI_SPMCL 0 -+#define DMA_READ_MODE_PROGRAMMING_VI_DPCL 1 -+ WARN_ON(!((mode == CI_ISP_DMA_RD_OFF) || -+ (mode == CI_ISP_DMA_RD_SELF_PATH) || -+ (mode == CI_ISP_DMA_RD_IE_PATH) || -+ (mode == CI_ISP_DMA_RD_SUPERIMPOSE))); -+ -+ switch (mode) { -+ case CI_ISP_DMA_RD_OFF: -+ vi_dma_switch = MRV_VI_DMA_SWITCH_SELF; -+ vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM; -+ vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM; -+ dma_jpeg_select = false; -+ break; -+ case CI_ISP_DMA_RD_SELF_PATH: -+ vi_dma_switch = MRV_VI_DMA_SWITCH_SELF; -+ vi_dma_spmux = MRV_VI_DMA_SPMUX_DMA; -+ vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM; -+ dma_jpeg_select = false; -+ break; -+ case CI_ISP_DMA_RD_IE_PATH: -+ vi_dma_switch = MRV_VI_DMA_SWITCH_IE; -+ vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM; -+ vi_dma_iemux = MRV_VI_DMA_IEMUX_DMA; -+ dma_jpeg_select = false; -+ break; -+ case CI_ISP_DMA_RD_JPG_ENC: -+ vi_dma_switch = MRV_VI_DMA_SWITCH_JPG; -+ vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM; -+ vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM; -+ dma_jpeg_select = true; -+ break; -+ case CI_ISP_DMA_RD_SUPERIMPOSE: -+ vi_dma_switch = MRV_VI_DMA_SWITCH_SI; -+ vi_dma_spmux = MRV_VI_DMA_SPMUX_CAM; -+ vi_dma_iemux = MRV_VI_DMA_IEMUX_CAM; -+ dma_jpeg_select = false; -+ break; -+ default: -+ /* unknown DMA-read mode */ -+ WARN_ON(1); -+ } -+ -+ REG_SET_SLICE(vi_dpcl, MRV_VI_DMA_SWITCH, vi_dma_switch); -+ REG_SET_SLICE(vi_dpcl, MRV_VI_DMA_SPMUX, vi_dma_spmux); -+ REG_SET_SLICE(vi_dpcl, MRV_VI_DMA_IEMUX, vi_dma_iemux); -+#if ((MRV_VI_MP_MUX_JPGDIRECT & \ -+~(MRV_VI_MP_MUX_MASK >> MRV_VI_MP_MUX_SHIFT)) == 0) -+ if (dma_jpeg_select) { -+ REG_SET_SLICE(vi_dpcl, MRV_VI_MP_MUX, -+ MRV_VI_MP_MUX_JPGDIRECT); -+ } -+#else -+ /* direct DMA to JPEG not supported */ -+ UNUSED_PARAM(dma_jpeg_select); -+#endif -+ REG_WRITE(mrv_reg->vi_dpcl, vi_dpcl); -+} -+ -+/* -+ * Set extended mode with unrestricted values for YCbCr -+ * Y (0-255) CbCr (0-255) -+ */ -+void ci_isp_set_ext_ycmode(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl); -+ -+ /* modify isp_ctrl register */ -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_C_RANGE, -+ MRV_ISP_ISP_CSM_C_RANGE_FULL); -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_Y_RANGE, -+ MRV_ISP_ISP_CSM_Y_RANGE_FULL); -+ REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl); -+ -+ /* program RGB to YUV color conversion with extended range */ -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_0, MRV_ISP_CC_COEFF_0, 0x0026); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_1, MRV_ISP_CC_COEFF_1, 0x004B); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_2, MRV_ISP_CC_COEFF_2, 0x000F); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_3, MRV_ISP_CC_COEFF_3, 0x01EA); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_4, MRV_ISP_CC_COEFF_4, 0x01D6); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_5, MRV_ISP_CC_COEFF_5, 0x0040); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_6, MRV_ISP_CC_COEFF_6, 0x0040); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_7, MRV_ISP_CC_COEFF_7, 0x01CA); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_8, MRV_ISP_CC_COEFF_8, 0x01F6); -+} -+ -+void ci_isp_set_yc_mode(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE; -+ u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl); -+ -+ /* modify isp_ctrl register */ -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_C_RANGE, -+ MRV_ISP_ISP_CSM_Y_RANGE_BT601); -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_CSM_Y_RANGE, -+ MRV_ISP_ISP_CSM_Y_RANGE_BT601); -+ REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl); -+ -+ /* program RGB to YUV color conversion with extended range */ -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_0, MRV_ISP_CC_COEFF_0, 0x0021); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_1, MRV_ISP_CC_COEFF_1, 0x0040); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_2, MRV_ISP_CC_COEFF_2, 0x000D); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_3, MRV_ISP_CC_COEFF_3, 0x01ED); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_4, MRV_ISP_CC_COEFF_4, 0x01DB); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_5, MRV_ISP_CC_COEFF_5, 0x0038); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_6, MRV_ISP_CC_COEFF_6, 0x0038); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_7, MRV_ISP_CC_COEFF_7, 0x01D1); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_8, MRV_ISP_CC_COEFF_8, 0x01F7); -+} -+ -+/* -+ * writes the color values for contrast, brightness, -+ * saturation and hue into the appropriate Marvin -+ * registers -+ */ -+void ci_isp_col_set_color_processing( -+ const struct ci_isp_color_settings *col) -+{ -+ struct isp_register *mrv_reg = -+ (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (col == NULL) { -+ /* disable color processing (bypass) */ -+ mrv_reg->c_proc_ctrl = 0; -+ } else { -+ mrv_reg->c_proc_contrast = col->contrast; -+ mrv_reg->c_proc_brightness = col->brightness; -+ mrv_reg->c_proc_saturation = col->saturation; -+ mrv_reg->c_proc_hue = col->hue; -+ -+ /* modify color processing registers */ -+ -+ if (col->flags & CI_ISP_CPROC_C_OUT_RANGE) { -+ mrv_reg->c_proc_ctrl = -+ mrv_reg->c_proc_ctrl | CI_ISP_CPROC_C_OUT_RANGE; -+ } -+ -+ if (col->flags & CI_ISP_CPROC_Y_IN_RANGE) { -+ mrv_reg->c_proc_ctrl = -+ mrv_reg->c_proc_ctrl | CI_ISP_CPROC_Y_IN_RANGE; -+ } -+ -+ if (col->flags & CI_ISP_CPROC_Y_OUT_RANGE) { -+ mrv_reg->c_proc_ctrl = -+ mrv_reg->c_proc_ctrl | CI_ISP_CPROC_Y_OUT_RANGE; -+ } -+ -+ if (col->flags & CI_ISP_CPROC_ENABLE) { -+ mrv_reg->c_proc_ctrl = -+ mrv_reg->c_proc_ctrl | CI_ISP_CPROC_ENABLE; -+ } -+ } -+} -+ -+/* -+ * Translates a chrominance component value from usual -+ * representation (range 16..240, 128=neutral grey) -+ * to the one used by the ie_tint register -+ * The value is returned as 32 bit unsigned to support shift -+ * operation without explicit cast. -+ * The translation formular implemented here is taken from -+ * the image effects functional specification document, -+ * Doc-ID 30-001-481.130, revision 1.1 from november, 21st. 2005 -+ */ -+static u32 ci_isp_ie_tint_cx2_reg_val(u8 cx) -+{ -+ s32 temp; -+ u32 reg_val; -+ -+ /* -+ * apply scaling as specified in the image effects functional -+ * specification -+ */ -+ temp = 128 - (s32) cx; -+ temp = ((temp * 64) / 110); -+ -+ /* convert from two's complement to sign/value */ -+ if (temp < 0) { -+ reg_val = 0x80; -+ temp *= (-1); -+ } else -+ reg_val = 0; -+ -+ /* saturate at 7 bits */ -+ if (temp > 0x7F) -+ temp = 0x7F; -+ -+ /* combine sign and value to build the regiter value */ -+ reg_val |= (u32) temp; -+ -+ return reg_val; -+} -+ -+/* -+ * Translates usual (decimal) matrix coefficient into the -+ * 4 bit register representation (used in the ie_mat_X registers). -+ * for unsupported decimal numbers, a supported replacement is -+ * selected automatically. -+ * The value is returned as 32 bit unsigned to support shift -+ * operation without explicit cast. -+ * The translation formular implemented here is taken from -+ * the image effects functional specification document, -+ * Doc-ID 30-001-481.130, revision 1.1 from november, 21st. 2005 -+ */ -+static u32 ci_isp_ie_mx_dec2_reg_val(s8 dec) -+{ -+ if (dec <= (-6)) { -+ /* equivlent to -8 */ -+ return 0x0f; -+ } else if (dec <= (-3)) { -+ /* equivlent to -4 */ -+ return 0x0e; -+ } else if (dec == (-2)) { -+ /* equivlent to -2 */ -+ return 0x0d; -+ } else if (dec == (-1)) { -+ /* equivlent to -1 */ -+ return 0x0c; -+ } else if (dec == 0) { -+ /* equivlent to 0 (entry not used) */ -+ return 0x00; -+ } else if (dec == 1) { -+ /* equivlent to 1 */ -+ return 0x08; -+ } else if (dec == 2) { -+ /* equivlent to 2 */ -+ return 0x09; -+ } else if (dec < 6) { -+ /* equivlent to 4 */ -+ return 0x0a; -+ } else { -+ /* equivlent to 8 */ -+ return 0x0b; -+ } -+} -+ -+/* -+ * translates the values of the given configuration -+ * structure into register settings for the image effects -+ * submodule and loads the registers. -+ */ -+int ci_isp_ie_set_config(const struct ci_isp_ie_config *ie_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!ie_config) { -+ /* just disable the module, i.e. put it in bypass mode */ -+ REG_SET_SLICE(mrv_reg->img_eff_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_BYPASS); -+ } else { -+ /* apply the given settings */ -+ u32 ul_ie_ctrl = REG_READ(mrv_reg->img_eff_ctrl); -+ u32 ul_ie_csel = REG_READ(mrv_reg->img_eff_color_sel); -+ u32 ul_ie_tint = REG_READ(mrv_reg->img_eff_tint); -+ u32 ul_ie_mat1 = REG_READ(mrv_reg->img_eff_mat_1); -+ u32 ul_ie_mat2 = REG_READ(mrv_reg->img_eff_mat_2); -+ u32 ul_ie_mat3 = REG_READ(mrv_reg->img_eff_mat_3); -+ u32 ul_ie_mat4 = REG_READ(mrv_reg->img_eff_mat_4); -+ u32 ul_ie_mat5 = REG_READ(mrv_reg->img_eff_mat_5); -+ -+ /* overall operation mode */ -+ switch (ie_config->mode) { -+ case CI_ISP_IE_MODE_OFF: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_BYPASS); -+ break; -+ case CI_ISP_IE_MODE_GRAYSCALE: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE, -+ MRV_IMGEFF_EFFECT_MODE_GRAY); -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_PROCESS); -+ break; -+ case CI_ISP_IE_MODE_NEGATIVE: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE, -+ MRV_IMGEFF_EFFECT_MODE_NEGATIVE); -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_PROCESS); -+ break; -+ case CI_ISP_IE_MODE_SEPIA: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE, -+ MRV_IMGEFF_EFFECT_MODE_SEPIA); -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_PROCESS); -+ break; -+ case CI_ISP_IE_MODE_COLOR_SEL: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE, -+ MRV_IMGEFF_EFFECT_MODE_COLOR_SEL); -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_PROCESS); -+ break; -+ case CI_ISP_IE_MODE_EMBOSS: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE, -+ MRV_IMGEFF_EFFECT_MODE_EMBOSS); -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_PROCESS); -+ break; -+ case CI_ISP_IE_MODE_SKETCH: -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_EFFECT_MODE, -+ MRV_IMGEFF_EFFECT_MODE_SKETCH); -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_BYPASS_MODE, -+ MRV_IMGEFF_BYPASS_MODE_PROCESS); -+ break; -+ default: -+ return CI_STATUS_OUTOFRANGE; -+ } -+ -+ /* use next frame sync update */ -+ REG_SET_SLICE(ul_ie_ctrl, MRV_IMGEFF_CFG_UPD, ON); -+ -+ /* color selection settings */ -+ REG_SET_SLICE(ul_ie_csel, MRV_IMGEFF_COLOR_THRESHOLD, -+ (u32) (ie_config->color_thres)); -+ REG_SET_SLICE(ul_ie_csel, MRV_IMGEFF_COLOR_SELECTION, -+ (u32) (ie_config->color_sel)); -+ -+ /* tint color settings */ -+ REG_SET_SLICE(ul_ie_tint, MRV_IMGEFF_INCR_CB, -+ ci_isp_ie_tint_cx2_reg_val(ie_config->tint_cb)); -+ REG_SET_SLICE(ul_ie_tint, MRV_IMGEFF_INCR_CR, -+ ci_isp_ie_tint_cx2_reg_val(ie_config->tint_cr)); -+ -+ /* matrix coefficients */ -+ REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_11_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_11)); -+ REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_12_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_12)); -+ REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_13_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_13)); -+ REG_SET_SLICE(ul_ie_mat1, MRV_IMGEFF_EMB_COEF_21_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_21)); -+ REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_22_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_22)); -+ REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_23_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_23)); -+ REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_31_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_31)); -+ REG_SET_SLICE(ul_ie_mat2, MRV_IMGEFF_EMB_COEF_32_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_32)); -+ REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_EMB_COEF_33_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_emboss. -+ coeff_33)); -+ REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_SKET_COEF_11_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_11)); -+ REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_SKET_COEF_12_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_12)); -+ REG_SET_SLICE(ul_ie_mat3, MRV_IMGEFF_SKET_COEF_13_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_13)); -+ REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_21_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_21)); -+ REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_22_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_22)); -+ REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_23_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_23)); -+ REG_SET_SLICE(ul_ie_mat4, MRV_IMGEFF_SKET_COEF_31_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_31)); -+ REG_SET_SLICE(ul_ie_mat5, MRV_IMGEFF_SKET_COEF_32_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_32)); -+ REG_SET_SLICE(ul_ie_mat5, MRV_IMGEFF_SKET_COEF_33_4, -+ ci_isp_ie_mx_dec2_reg_val(ie_config->mat_sketch. -+ coeff_33)); -+ -+ /* write changed values back to registers */ -+ REG_WRITE(mrv_reg->img_eff_ctrl, ul_ie_ctrl); -+ REG_WRITE(mrv_reg->img_eff_color_sel, ul_ie_csel); -+ REG_WRITE(mrv_reg->img_eff_tint, ul_ie_tint); -+ REG_WRITE(mrv_reg->img_eff_mat_1, ul_ie_mat1); -+ REG_WRITE(mrv_reg->img_eff_mat_2, ul_ie_mat2); -+ REG_WRITE(mrv_reg->img_eff_mat_3, ul_ie_mat3); -+ REG_WRITE(mrv_reg->img_eff_mat_4, ul_ie_mat4); -+ REG_WRITE(mrv_reg->img_eff_mat_5, ul_ie_mat5); -+ -+ /* frame synchronous update of shadow registers */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON); -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Applies the new image stabilisation settings to the module. -+ */ -+int ci_isp_is_set_config(const struct ci_isp_is_config *is_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!is_config) { -+ eprintk("is_config NULL"); -+ return CI_STATUS_NULL_POINTER; -+ } -+ -+ /* set maximal margin distance for X */ -+ if (is_config->max_dx > MRV_IS_IS_MAX_DX_MAX) { -+ REG_SET_SLICE(mrv_reg->isp_is_max_dx, MRV_IS_IS_MAX_DX, -+ (u32) (MRV_IS_IS_MAX_DX_MAX)); -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_is_max_dx, MRV_IS_IS_MAX_DX, -+ (u32) (is_config->max_dx)); -+ } -+ -+ /* set maximal margin distance for Y */ -+ if (is_config->max_dy > MRV_IS_IS_MAX_DY_MAX) { -+ REG_SET_SLICE(mrv_reg->isp_is_max_dy, MRV_IS_IS_MAX_DY, -+ (u32) (MRV_IS_IS_MAX_DY_MAX)); -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_is_max_dy, MRV_IS_IS_MAX_DY, -+ (u32) (is_config->max_dy)); -+ } -+ -+ /* set H offset */ -+ REG_SET_SLICE(mrv_reg->isp_is_h_offs, MRV_IS_IS_H_OFFS, -+ (u32) (is_config->mrv_is_window.hoffs)); -+ /* set V offset */ -+ REG_SET_SLICE(mrv_reg->isp_is_v_offs, MRV_IS_IS_V_OFFS, -+ (u32) (is_config->mrv_is_window.voffs)); -+ /* set H size */ -+ REG_SET_SLICE(mrv_reg->isp_is_h_size, MRV_IS_IS_H_SIZE, -+ (u32) (is_config->mrv_is_window.hsize)); -+ /* set V size */ -+ REG_SET_SLICE(mrv_reg->isp_is_v_size, MRV_IS_IS_V_SIZE, -+ (u32) (is_config->mrv_is_window.vsize)); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+static int ci_isp_bls_set_fixed_values(const struct ci_isp_bls_subtraction -+ *bls_subtraction) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!bls_subtraction) -+ return CI_STATUS_NULL_POINTER; -+ -+ if ((bls_subtraction->fixed_a > MRV_ISP_BLS_FIX_SUB_MAX) || -+ (bls_subtraction->fixed_b > MRV_ISP_BLS_FIX_SUB_MAX) || -+ (bls_subtraction->fixed_c > MRV_ISP_BLS_FIX_SUB_MAX) || -+ (bls_subtraction->fixed_d > MRV_ISP_BLS_FIX_SUB_MAX) || -+ (bls_subtraction->fixed_a < (s16) MRV_ISP_BLS_FIX_SUB_MIN) || -+ (bls_subtraction->fixed_b < (s16) MRV_ISP_BLS_FIX_SUB_MIN) || -+ (bls_subtraction->fixed_c < (s16) MRV_ISP_BLS_FIX_SUB_MIN) || -+ (bls_subtraction->fixed_d < (s16) MRV_ISP_BLS_FIX_SUB_MIN)) { -+ return CI_STATUS_OUTOFRANGE; -+ } else { -+ /* we are in this path */ -+ REG_SET_SLICE(mrv_reg->isp_bls_a_fixed, MRV_BLS_BLS_A_FIXED, -+ bls_subtraction->fixed_a); -+ REG_SET_SLICE(mrv_reg->isp_bls_b_fixed, MRV_BLS_BLS_B_FIXED, \ -+ bls_subtraction->fixed_b); -+ REG_SET_SLICE(mrv_reg->isp_bls_c_fixed, MRV_BLS_BLS_C_FIXED, -+ bls_subtraction->fixed_c); -+ REG_SET_SLICE(mrv_reg->isp_bls_d_fixed, MRV_BLS_BLS_D_FIXED, -+ bls_subtraction->fixed_d); -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Sets the desired configuration values to the BLS registers, -+ * if possible. In the case the parameter (bls_config == NULL) -+ * the BLS module will be deactivated. -+ */ -+int ci_isp_bls_set_config(const struct ci_isp_bls_config *bls_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_bls_ctrl = 0; -+ -+ int error = CI_STATUS_FAILURE; -+ -+ if (!bls_config) { -+ /* disable the BLS module */ -+ REG_SET_SLICE(mrv_reg->isp_bls_ctrl, -+ MRV_BLS_BLS_ENABLE, DISABLE); -+ return CI_STATUS_SUCCESS; -+ } -+ -+ /* measurement window 2, enable_window =0 */ -+ if (bls_config->isp_bls_window2.enable_window) { -+ if ((bls_config->isp_bls_window2.start_h > -+ MRV_BLS_BLS_H2_START_MAX) -+ || (bls_config->isp_bls_window2.stop_h > -+ MRV_BLS_BLS_H2_STOP_MAX) -+ || (bls_config->isp_bls_window2.start_v > -+ MRV_BLS_BLS_V2_START_MAX) -+ || (bls_config->isp_bls_window2.stop_v > -+ MRV_BLS_BLS_V2_STOP_MAX)) { -+ return CI_STATUS_OUTOFRANGE; -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_bls_h2_start, -+ MRV_BLS_BLS_H2_START, -+ bls_config->isp_bls_window2.start_h); -+ REG_SET_SLICE(mrv_reg->isp_bls_h2_stop, -+ MRV_BLS_BLS_H2_STOP, -+ bls_config->isp_bls_window2.stop_h); -+ REG_SET_SLICE(mrv_reg->isp_bls_v2_start, -+ MRV_BLS_BLS_V2_START, -+ bls_config->isp_bls_window2.start_v); -+ REG_SET_SLICE(mrv_reg->isp_bls_v2_stop, -+ MRV_BLS_BLS_V2_STOP, -+ bls_config->isp_bls_window2.stop_v); -+ } -+ } -+ -+ /* measurement window 1, enable_window=0 */ -+ if (bls_config->isp_bls_window1.enable_window) { -+ if ((bls_config->isp_bls_window1.start_h > -+ MRV_BLS_BLS_H1_START_MAX) -+ || (bls_config->isp_bls_window1.stop_h > -+ MRV_BLS_BLS_H1_STOP_MAX) -+ || (bls_config->isp_bls_window1.start_v > -+ MRV_BLS_BLS_V1_START_MAX) -+ || (bls_config->isp_bls_window1.stop_v > -+ MRV_BLS_BLS_V1_STOP_MAX)) { -+ return CI_STATUS_OUTOFRANGE; -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_bls_h1_start, -+ MRV_BLS_BLS_H1_START, -+ bls_config->isp_bls_window1.start_h); -+ REG_SET_SLICE(mrv_reg->isp_bls_h1_stop, -+ MRV_BLS_BLS_H1_STOP, -+ bls_config->isp_bls_window1.stop_h); -+ REG_SET_SLICE(mrv_reg->isp_bls_v1_start, -+ MRV_BLS_BLS_V1_START, -+ bls_config->isp_bls_window1.start_v); -+ REG_SET_SLICE(mrv_reg->isp_bls_v1_stop, -+ MRV_BLS_BLS_V1_STOP, -+ bls_config->isp_bls_window1.stop_v); -+ } -+ } -+ -+ if (bls_config->bls_samples > MRV_BLS_BLS_SAMPLES_MAX) { -+ return CI_STATUS_OUTOFRANGE; -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_bls_samples, MRV_BLS_BLS_SAMPLES, -+ bls_config->bls_samples); -+ } -+ -+ /* fixed subtraction values, enable_automatic=0 */ -+ if (!bls_config->enable_automatic) { -+ error = ci_isp_bls_set_fixed_values( -+ &(bls_config->bls_subtraction)); -+ if (error != CI_STATUS_SUCCESS) -+ return error; -+ } -+ -+ if ((bls_config->disable_h) || (bls_config->disable_v)) -+ return CI_STATUS_OUTOFRANGE; -+ -+ isp_bls_ctrl = REG_READ(mrv_reg->isp_bls_ctrl); -+ -+ /* enable measurement window(s) */ -+ REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_WINDOW_ENABLE, -+ ((bls_config->isp_bls_window1.enable_window) -+ ? MRV_BLS_WINDOW_ENABLE_WND1 : 0) | -+ ((bls_config->isp_bls_window2.enable_window) -+ ? MRV_BLS_WINDOW_ENABLE_WND2 : 0)); -+ -+ /* set Mode */ -+ REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_BLS_MODE, -+ (bls_config->enable_automatic) ? MRV_BLS_BLS_MODE_MEAS : -+ MRV_BLS_BLS_MODE_FIX); -+ -+ /* enable module */ -+ REG_SET_SLICE(isp_bls_ctrl, MRV_BLS_BLS_ENABLE, ENABLE); -+ -+ /* write into register */ -+ REG_WRITE(mrv_reg->isp_bls_ctrl, isp_bls_ctrl); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+#define RSZ_FLAGS_MASK (RSZ_UPSCALE_ENABLE | RSZ_SCALER_BYPASS) -+ -+/* -+ * writes the scaler values to the appropriate Marvin registers. -+ */ -+void ci_isp_res_set_main_resize(const struct ci_isp_scale *scale, -+ enum ci_isp_conf_update_time update_time, -+ const struct ci_isp_rsz_lut *rsz_lut) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 mrsz_ctrl = REG_READ(mrv_reg->mrsz_ctrl); -+ u32 i; -+ int upscaling = false; -+ -+ /* flags must be "outside" scaler value */ -+ WARN_ON(!((RSZ_FLAGS_MASK & MRV_RSZ_SCALE_MASK) == 0)); -+ WARN_ON(!((scale->scale_hy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_hcb & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_hcr & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_vy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_vc & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ -+ /* horizontal luminance scale factor */ -+ dprintk(1, "scale_hy = %d( %x )", scale->scale_hy, scale->scale_hy); -+ -+ if (scale->scale_hy & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_ENABLE, DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->mrsz_scale_hy, MRV_MRSZ_SCALE_HY, -+ (u32) scale->scale_hy); -+ REG_SET_SLICE(mrv_reg->mrsz_phase_hy, MRV_MRSZ_PHASE_HY, -+ (u32) scale->phase_hy); -+ -+ if (scale->scale_hy & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ dprintk(1, "enable up scale"); -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_UP, -+ MRV_MRSZ_SCALE_HY_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else -+ /* disable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HY_UP, -+ MRV_MRSZ_SCALE_HY_UP_DOWNSCALE); -+ } -+ -+ /* horizontal chrominance scale factors */ -+ WARN_ON(!((scale->scale_hcb & RSZ_FLAGS_MASK) == (scale->scale_hcr & -+ RSZ_FLAGS_MASK))); -+ dprintk(1, "scale_hcb = %d( %x )", scale->scale_hcb, scale->scale_hcb); -+ -+ if (scale->scale_hcb & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_ENABLE, DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->mrsz_scale_hcb, MRV_MRSZ_SCALE_HCB, -+ (u32) scale->scale_hcb); -+ REG_SET_SLICE(mrv_reg->mrsz_scale_hcr, MRV_MRSZ_SCALE_HCB, -+ (u32) scale->scale_hcr); -+ REG_SET_SLICE(mrv_reg->mrsz_phase_hc, MRV_MRSZ_PHASE_HC, -+ (u32) scale->phase_hc); -+ -+ if (scale->scale_hcb & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_UP, -+ MRV_MRSZ_SCALE_HC_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ /* disable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_HC_UP, -+ MRV_MRSZ_SCALE_HC_UP_DOWNSCALE); -+ } -+ } -+ -+ /* vertical luminance scale factor */ -+ dprintk(1, "scale_vy = %d ( %x )", scale->scale_vy, scale->scale_vy); -+ -+ if (scale->scale_vy & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_ENABLE, -+ DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->mrsz_scale_vy, MRV_MRSZ_SCALE_VY, -+ (u32) scale->scale_vy); -+ REG_SET_SLICE(mrv_reg->mrsz_phase_vy, MRV_MRSZ_PHASE_VY, -+ (u32) scale->phase_vy); -+ -+ if (scale->scale_vy & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_UP, -+ MRV_MRSZ_SCALE_VY_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ /* disable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VY_UP, -+ MRV_MRSZ_SCALE_VY_UP_DOWNSCALE); -+ } -+ } -+ -+ /* vertical chrominance scale factor */ -+ dprintk(1, "scale_vc = %d( %x )", scale->scale_vc, scale->scale_vc); -+ -+ if (scale->scale_vc & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_ENABLE, -+ DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->mrsz_scale_vc, MRV_MRSZ_SCALE_VC, -+ (u32) scale->scale_vc); -+ REG_SET_SLICE(mrv_reg->mrsz_phase_vc, MRV_MRSZ_PHASE_VC, -+ (u32) scale->phase_vc); -+ -+ if (scale->scale_vc & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_UP, -+ MRV_MRSZ_SCALE_VC_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ /* disable upscaling mode */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_SCALE_VC_UP, -+ MRV_MRSZ_SCALE_VC_UP_DOWNSCALE); -+ } -+ } -+ -+ /* apply upscaling lookup table */ -+ if (rsz_lut) { -+ for (i = 0; i <= MRV_MRSZ_SCALE_LUT_ADDR_MASK; i++) { -+ REG_SET_SLICE(mrv_reg->mrsz_scale_lut_addr, -+ MRV_MRSZ_SCALE_LUT_ADDR, i); -+ REG_SET_SLICE(mrv_reg->mrsz_scale_lut, -+ MRV_MRSZ_SCALE_LUT, -+ rsz_lut->rsz_lut[i]); -+ } -+ } else if (upscaling) { -+ eprintk("Upscaling requires lookup table!"); -+ WARN_ON(1); -+ } -+ -+ /* handle immediate update flag and write mrsz_ctrl */ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ /* frame synchronous update of shadow registers */ -+ REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl); -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ /* immediate update of shadow registers */ -+ REG_SET_SLICE(mrsz_ctrl, MRV_MRSZ_CFG_UPD, ON); -+ REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ default: -+ /* no update from within this function */ -+ REG_WRITE(mrv_reg->mrsz_ctrl, mrsz_ctrl); -+ break; -+ } -+} -+ -+/* -+ * writes the scaler values to the appropriate Marvin registers. -+ */ -+void ci_isp_res_set_self_resize(const struct ci_isp_scale *scale, -+ enum ci_isp_conf_update_time update_time, -+ const struct ci_isp_rsz_lut *rsz_lut) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 srsz_ctrl = REG_READ(mrv_reg->srsz_ctrl); -+ u32 i; -+ int upscaling = false; -+ -+ /* flags must be "outside" scaler value */ -+ WARN_ON(!((RSZ_FLAGS_MASK & MRV_RSZ_SCALE_MASK) == 0)); -+ WARN_ON(!((scale->scale_hy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_hcb & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_hcr & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_vy & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ WARN_ON(!((scale->scale_vc & ~RSZ_FLAGS_MASK) <= MRV_RSZ_SCALE_MAX)); -+ -+ /* horizontal luminance scale factor */ -+ dprintk(1, "scale_hy = %d,%x", scale->scale_hy, scale->scale_hy); -+ -+ if (scale->scale_hy & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_ENABLE, -+ DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->srsz_scale_hy, MRV_SRSZ_SCALE_HY, -+ (u32) scale->scale_hy); -+ REG_SET_SLICE(mrv_reg->srsz_phase_hy, MRV_SRSZ_PHASE_HY, -+ (u32) scale->phase_hy); -+ -+ if (scale->scale_hy & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_UP, -+ MRV_SRSZ_SCALE_HY_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ /* disable upscaling mode */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HY_UP, -+ MRV_SRSZ_SCALE_HY_UP_DOWNSCALE); -+ } -+ } -+ -+ /* horizontal chrominance scale factors */ -+ WARN_ON(!((scale->scale_hcb & RSZ_FLAGS_MASK) == (scale->scale_hcr & -+ RSZ_FLAGS_MASK))); -+ -+ dprintk(1, "scale_hcb = %d,%x", scale->scale_hcb, scale->scale_hcb); -+ -+ if (scale->scale_hcb & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_ENABLE, -+ DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->srsz_scale_hcb, MRV_SRSZ_SCALE_HCB, -+ (u32) scale->scale_hcb); -+ REG_SET_SLICE(mrv_reg->srsz_scale_hcr, MRV_SRSZ_SCALE_HCB, -+ (u32) scale->scale_hcr); -+ -+ REG_SET_SLICE(mrv_reg->srsz_phase_hc, MRV_SRSZ_PHASE_HC, -+ (u32) scale->phase_hc); -+ -+ if (scale->scale_hcb & RSZ_UPSCALE_ENABLE) { -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_UP, -+ MRV_SRSZ_SCALE_HC_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_HC_UP, -+ MRV_SRSZ_SCALE_HC_UP_DOWNSCALE); -+ } -+ } -+ -+ /* vertical luminance scale factor */ -+ dprintk(1, "scale_vy = %d,%x", scale->scale_vy, scale->scale_vy); -+ -+ if (scale->scale_vy & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_ENABLE, -+ DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->srsz_scale_vy, MRV_SRSZ_SCALE_VY, -+ (u32) scale->scale_vy); -+ REG_SET_SLICE(mrv_reg->srsz_phase_vy, MRV_SRSZ_PHASE_VY, -+ (u32) scale->phase_vy); -+ -+ if (scale->scale_vy & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_UP, -+ MRV_SRSZ_SCALE_VY_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ /* disable upscaling mode */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VY_UP, -+ MRV_SRSZ_SCALE_VY_UP_DOWNSCALE); -+ } -+ } -+ -+ /* vertical chrominance scale factor */ -+ dprintk(1, "scale_vc = %d,%x", scale->scale_vc, scale->scale_vc); -+ -+ if (scale->scale_vc & RSZ_SCALER_BYPASS) { -+ /* disable (bypass) scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_ENABLE, -+ DISABLE); -+ } else { -+ /* enable scaler */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_ENABLE, ENABLE); -+ /* program scale factor and phase */ -+ REG_SET_SLICE(mrv_reg->srsz_scale_vc, MRV_SRSZ_SCALE_VC, -+ (u32) scale->scale_vc); -+ REG_SET_SLICE(mrv_reg->srsz_phase_vc, MRV_SRSZ_PHASE_VC, -+ (u32) scale->phase_vc); -+ -+ if (scale->scale_vc & RSZ_UPSCALE_ENABLE) { -+ /* enable upscaling mode */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_UP, -+ MRV_SRSZ_SCALE_VC_UP_UPSCALE); -+ /* scaler and upscaling enabled */ -+ upscaling = true; -+ } else { -+ /* disable upscaling mode */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_SCALE_VC_UP, -+ MRV_SRSZ_SCALE_VC_UP_DOWNSCALE); -+ } -+ } -+ -+ /* apply upscaling lookup table */ -+ if (rsz_lut) { -+ for (i = 0; i <= MRV_SRSZ_SCALE_LUT_ADDR_MASK; i++) { -+ REG_SET_SLICE(mrv_reg->srsz_scale_lut_addr, -+ MRV_SRSZ_SCALE_LUT_ADDR, i); -+ REG_SET_SLICE(mrv_reg->srsz_scale_lut, -+ MRV_SRSZ_SCALE_LUT, -+ rsz_lut->rsz_lut[i]); -+ } -+ } else if (upscaling) { -+ eprintk("Upscaling requires lookup table!"); -+ WARN_ON(1); -+ } -+ -+ /* handle immediate update flag and write mrsz_ctrl */ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ /* frame synchronous update of shadow registers */ -+ REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl); -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, -+ ON); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ /* immediate update of shadow registers */ -+ REG_SET_SLICE(srsz_ctrl, MRV_SRSZ_CFG_UPD, ON); -+ REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ default: -+ /* no update from within this function */ -+ REG_WRITE(mrv_reg->srsz_ctrl, srsz_ctrl); -+ break; -+ } -+} -+ -+#if MRV_SUPPORT_SL -+ -+/* bad pixel table */ -+static struct ci_sensor_bp_table bp_table = { 0 }; -+ -+/* -+ * Initialization of the Bad Pixel Detection and Correction. -+ */ -+int ci_bp_init(const struct ci_isp_bp_corr_config *bp_corr_config, -+ const struct ci_isp_bp_det_config *bp_det_config) -+{ -+ int error = CI_STATUS_SUCCESS; -+ -+ /* number of table elements */ -+ /* number of table elements */ -+#define MRVSLS_BPINIT_MAX_TABLE 2048 -+ -+ /* check the parameters */ -+ if (!bp_corr_config || !bp_det_config) -+ return CI_STATUS_NULL_POINTER; -+ -+ if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_TABLE) { -+ /* set badpixel correction */ -+ error |= ci_isp_set_bp_correction(bp_corr_config); -+ /* set badpixel detection */ -+ error |= ci_isp_set_bp_detection(bp_det_config); -+ /* zero element inside */ -+ bp_table.bp_number = 0; -+ if (!bp_table.bp_table_elem) { -+ /* allocate mem space for the table */ -+ bp_table.bp_table_elem = -+ (struct ci_sensor_bp_table_elem *) -+ kmalloc((sizeof(struct ci_sensor_bp_table_elem)* -+ MRVSLS_BPINIT_MAX_TABLE), GFP_KERNEL); -+ if (!bp_table.bp_table_elem) -+ error |= CI_STATUS_FAILURE; -+ } -+ /* max count of elements */ -+ bp_table.bp_table_elem_num = MRVSLS_BPINIT_MAX_TABLE; -+ /* Clear Interrupt Status */ -+ error |= ci_isp_clear_bp_int(); -+ } else { -+ if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_DIRECT) { -+ /* set badpixel correction */ -+ error |= ci_isp_set_bp_correction(bp_corr_config); -+ /* set badpixel detection */ -+ error |= ci_isp_set_bp_detection(NULL); -+ } else { -+ return CI_STATUS_NOTSUPP; -+ } -+ } -+ return error; -+} -+ -+/* -+ * Disable the Bad Pixel Detection and Correction. -+ */ -+int ci_bp_end(const struct ci_isp_bp_corr_config *bp_corr_config) -+{ -+ int uiResult = CI_STATUS_SUCCESS; -+ -+ /* check the parameter */ -+ if (!bp_corr_config) -+ return CI_STATUS_NULL_POINTER; -+ -+ /* disable badpixel correction */ -+ uiResult |= ci_isp_set_bp_correction(NULL); -+ -+ /* disable badpixel detection */ -+ uiResult |= ci_isp_set_bp_detection(NULL); -+ -+ if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_TABLE) { -+ /* Clear Interrupt Status */ -+ uiResult |= ci_isp_clear_bp_int(); -+ -+ /* deallocate BP Table */ -+ kfree(bp_table.bp_table_elem); -+ bp_table.bp_table_elem = NULL; -+ } -+ return uiResult; -+} -+#endif -diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c b/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c -new file mode 100644 -index 0000000..7c96bc4 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/mrstisp_isp.c -@@ -0,0 +1,1993 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * Copyright (c) Silicon Image 2008 www.siliconimage.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+ -+int mrst_isp_set_color_conversion_ex(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_0, MRV_ISP_CC_COEFF_0, 0x00001021); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_1, MRV_ISP_CC_COEFF_1, 0x00001040); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_2, MRV_ISP_CC_COEFF_2, 0x0000100D); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_3, MRV_ISP_CC_COEFF_3, 0x00000FED); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_4, MRV_ISP_CC_COEFF_4, 0x00000FDB); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_5, MRV_ISP_CC_COEFF_5, 0x00001038); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_6, MRV_ISP_CC_COEFF_6, 0x00001038); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_7, MRV_ISP_CC_COEFF_7, 0x00000FD1); -+ REG_SET_SLICE(mrv_reg->isp_cc_coeff_8, MRV_ISP_CC_COEFF_8, 0x00000FF7); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Selects the ISP path that will become active while processing -+ * data coming from an image sensor configured by the given ISI -+ * configuration struct. -+ */ -+enum ci_isp_path ci_isp_select_path(const struct ci_sensor_config *isi_cfg, -+ u8 *words_per_pixel) -+{ -+ u8 words; -+ enum ci_isp_path ret_val; -+ -+ switch (isi_cfg->mode) { -+ case SENSOR_MODE_DATA: -+ ret_val = CI_ISP_PATH_RAW; -+ words = 1; -+ break; -+ case SENSOR_MODE_PICT: -+ ret_val = CI_ISP_PATH_RAW; -+ words = 1; -+ break; -+ case SENSOR_MODE_RGB565: -+ ret_val = CI_ISP_PATH_RAW; -+ words = 2; -+ break; -+ case SENSOR_MODE_BT601: -+ ret_val = CI_ISP_PATH_YCBCR; -+ words = 2; -+ break; -+ case SENSOR_MODE_BT656: -+ ret_val = CI_ISP_PATH_YCBCR; -+ words = 2; -+ break; -+ case SENSOR_MODE_BAYER: -+ ret_val = CI_ISP_PATH_BAYER; -+ words = 1; -+ break; -+ -+ case SENSOR_MODE_SMIA: -+ switch (isi_cfg->smia_mode) { -+ case SENSOR_SMIA_MODE_RAW_12: -+ case SENSOR_SMIA_MODE_RAW_10: -+ case SENSOR_SMIA_MODE_RAW_8: -+ case SENSOR_SMIA_MODE_RAW_8_TO_10_DECOMP: -+ ret_val = CI_ISP_PATH_BAYER; -+ words = 1; -+ break; -+ case SENSOR_SMIA_MODE_YUV_422: -+ ret_val = CI_ISP_PATH_YCBCR; -+ words = 2; -+ break; -+ case SENSOR_SMIA_MODE_YUV_420: -+ case SENSOR_SMIA_MODE_RGB_444: -+ case SENSOR_SMIA_MODE_RGB_565: -+ case SENSOR_SMIA_MODE_RGB_888: -+ case SENSOR_SMIA_MODE_COMPRESSED: -+ case SENSOR_SMIA_MODE_RAW_7: -+ case SENSOR_SMIA_MODE_RAW_6: -+ default: -+ ret_val = CI_ISP_PATH_RAW; -+ words = 1; -+ break; -+ } -+ break; -+ -+ case SENSOR_MODE_MIPI: -+ switch (isi_cfg->mipi_mode) { -+ case SENSOR_MIPI_MODE_RAW_12: -+ case SENSOR_MIPI_MODE_RAW_10: -+ case SENSOR_MIPI_MODE_RAW_8: -+ ret_val = CI_ISP_PATH_BAYER; -+ words = 1; -+ break; -+ case SENSOR_MIPI_MODE_YUV422_8: -+ case SENSOR_MIPI_MODE_YUV422_10: -+ ret_val = CI_ISP_PATH_YCBCR; -+ words = 2; -+ break; -+ case SENSOR_MIPI_MODE_YUV420_8: -+ case SENSOR_MIPI_MODE_YUV420_10: -+ case SENSOR_MIPI_MODE_LEGACY_YUV420_8: -+ case SENSOR_MIPI_MODE_YUV420_CSPS_8: -+ case SENSOR_MIPI_MODE_YUV420_CSPS_10: -+ case SENSOR_MIPI_MODE_RGB444: -+ case SENSOR_MIPI_MODE_RGB555: -+ case SENSOR_MIPI_MODE_RGB565: -+ case SENSOR_MIPI_MODE_RGB666: -+ case SENSOR_MIPI_MODE_RGB888: -+ case SENSOR_MIPI_MODE_RAW_7: -+ case SENSOR_MIPI_MODE_RAW_6: -+ default: -+ ret_val = CI_ISP_PATH_RAW; -+ words = 1; -+ break; -+ } -+ break; -+ case SENSOR_MODE_BAY_BT656: -+ ret_val = CI_ISP_PATH_BAYER; -+ words = 1; -+ break; -+ case SENSOR_MODE_RAW_BT656: -+ ret_val = CI_ISP_PATH_RAW; -+ words = 1; -+ break; -+ default: -+ ret_val = CI_ISP_PATH_UNKNOWN; -+ words = 1; -+ } -+ -+ if (words_per_pixel) -+ *words_per_pixel = words ; -+ return ret_val; -+} -+ -+/* -+ * configures the input acquisition according to the -+ * given config structure -+ */ -+int ci_isp_set_input_aquisition(const struct ci_sensor_config *isi_cfg) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_ctrl = REG_READ(mrv_reg->isp_ctrl); -+ u32 isp_acq_prop = REG_READ(mrv_reg->isp_acq_prop); -+ /* factor between pixel count and amount of bytes to sample */ -+ u8 sample_factor; -+ /* number of additional black lines at frame start */ -+ u8 black_lines; -+ -+ if (ci_isp_select_path(isi_cfg, &sample_factor) -+ == CI_ISP_PATH_UNKNOWN) { -+ eprintk("failed to select path"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->mode) { -+ case SENSOR_MODE_DATA: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_DATA); -+ break; -+ case SENSOR_MODE_PICT: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_RAW); -+ break; -+ case SENSOR_MODE_RGB565: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_RAW); -+ break; -+ case SENSOR_MODE_BT601: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_601); -+ break; -+ case SENSOR_MODE_BT656: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_656); -+ break; -+ case SENSOR_MODE_BAYER: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_RGB); -+ break; -+ case SENSOR_MODE_BAY_BT656: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_RGB656); -+ break; -+ case SENSOR_MODE_RAW_BT656: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_RAW656); -+ break; -+ -+ case SENSOR_MODE_SMIA: -+ switch (isi_cfg->smia_mode) { -+ case SENSOR_SMIA_MODE_RAW_12: -+ case SENSOR_SMIA_MODE_RAW_10: -+ case SENSOR_SMIA_MODE_RAW_8: -+ case SENSOR_SMIA_MODE_RAW_8_TO_10_DECOMP: -+ case SENSOR_SMIA_MODE_RAW_7: -+ case SENSOR_SMIA_MODE_RAW_6: -+ case SENSOR_SMIA_MODE_YUV_422: -+ case SENSOR_SMIA_MODE_YUV_420: -+ case SENSOR_SMIA_MODE_RGB_888: -+ case SENSOR_SMIA_MODE_RGB_565: -+ case SENSOR_SMIA_MODE_RGB_444: -+ case SENSOR_SMIA_MODE_COMPRESSED: -+ return CI_STATUS_SUCCESS; -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ break; -+ -+ case SENSOR_MODE_MIPI: -+ REG_SET_SLICE(isp_ctrl, MRV_ISP_ISP_MODE, -+ MRV_ISP_ISP_MODE_RGB); -+ REG_WRITE(mrv_reg->mipi_img_data_sel, 0x02b); -+ break; -+ -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->bus_width) { -+ case SENSOR_BUSWIDTH_12BIT: -+ /* 000- 12Bit external Interface */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION, -+ MRV_ISP_INPUT_SELECTION_12EXT); -+ break; -+ case SENSOR_BUSWIDTH_10BIT_ZZ: -+ /* 001- 10Bit Interface, append 2 zeroes as LSBs */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION, -+ MRV_ISP_INPUT_SELECTION_10ZERO); -+ break; -+ case SENSOR_BUSWIDTH_10BIT_EX: -+ /* 010- 10Bit Interface, append 2 MSBs as LSBs */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION, -+ MRV_ISP_INPUT_SELECTION_10MSB); -+ break; -+ case SENSOR_BUSWIDTH_8BIT_ZZ: -+ /* 011- 8Bit Interface, append 4 zeroes as LSBs */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION, -+ MRV_ISP_INPUT_SELECTION_8ZERO); -+ break; -+ case SENSOR_BUSWIDTH_8BIT_EX: -+ /* 100- 8Bit Interface, append 4 MSBs as LSBs */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_INPUT_SELECTION, -+ MRV_ISP_INPUT_SELECTION_8MSB); -+ break; -+ /* 101...111 reserved */ -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->field_sel) { -+ case SENSOR_FIELDSEL_ODD: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION, -+ MRV_ISP_FIELD_SELECTION_ODD); -+ break; -+ case SENSOR_FIELDSEL_EVEN: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION, -+ MRV_ISP_FIELD_SELECTION_EVEN); -+ break; -+ case SENSOR_FIELDSEL_BOTH: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_FIELD_SELECTION, -+ MRV_ISP_FIELD_SELECTION_BOTH); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->ycseq) { -+ case SENSOR_YCSEQ_CRYCBY: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ, -+ MRV_ISP_CCIR_SEQ_CRYCBY); -+ break; -+ case SENSOR_YCSEQ_CBYCRY: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ, -+ MRV_ISP_CCIR_SEQ_CBYCRY); -+ break; -+ case SENSOR_YCSEQ_YCRYCB: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ, -+ MRV_ISP_CCIR_SEQ_YCRYCB); -+ break; -+ case SENSOR_YCSEQ_YCBYCR: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CCIR_SEQ, -+ MRV_ISP_CCIR_SEQ_YCBYCR); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->conv422) { -+ case SENSOR_CONV422_INTER: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422, -+ MRV_ISP_CONV_422_INTER); -+ break; -+ -+ case SENSOR_CONV422_NOCOSITED: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422, -+ MRV_ISP_CONV_422_NONCO); -+ break; -+ case SENSOR_CONV422_COSITED: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_CONV_422, -+ MRV_ISP_CONV_422_CO); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->bpat) { -+ case SENSOR_BPAT_BGBGGRGR: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT, -+ MRV_ISP_BAYER_PAT_BG); -+ break; -+ case SENSOR_BPAT_GBGBRGRG: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT, -+ MRV_ISP_BAYER_PAT_GB); -+ break; -+ case SENSOR_BPAT_GRGRBGBG: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT, -+ MRV_ISP_BAYER_PAT_GR); -+ break; -+ case SENSOR_BPAT_RGRGGBGB: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_BAYER_PAT, -+ MRV_ISP_BAYER_PAT_RG); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->vpol) { -+ case SENSOR_VPOL_POS: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_VSYNC_POL, 1); -+ break; -+ case SENSOR_VPOL_NEG: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_VSYNC_POL, 0); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->hpol) { -+ /* The trigger edge differs for vsync_pol and hsync_pol. */ -+ /* vsync_pol = 1 triggers on positive edge whereas */ -+ /* hsync_pol = 1 triggers on negative edge and vice versa */ -+ case SENSOR_HPOL_SYNCPOS: -+ /* trigger on negative edge */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 1); -+ break; -+ case SENSOR_HPOL_SYNCNEG: -+ /* trigger on positive edge */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 0); -+ break; -+ case SENSOR_HPOL_REFPOS: -+ /* trigger on positive edge */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 0); -+ break; -+ case SENSOR_HPOL_REFNEG: -+ /* trigger on negative edge */ -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_HSYNC_POL, 1); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ switch (isi_cfg->edge) { -+ case SENSOR_EDGE_RISING: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_SAMPLE_EDGE, 1); -+ break; -+ case SENSOR_EDGE_FALLING: -+ REG_SET_SLICE(isp_acq_prop, MRV_ISP_SAMPLE_EDGE, 0); -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ dprintk(2, "isp_acq_prop = 0x%x", isp_acq_prop); -+ -+ /* now write values to registers */ -+ REG_WRITE(mrv_reg->isp_ctrl, isp_ctrl); -+ REG_WRITE(mrv_reg->isp_acq_prop, isp_acq_prop); -+ -+ /* number of additional black lines at frame start */ -+ switch (isi_cfg->bls) { -+ case SENSOR_BLS_OFF: -+ black_lines = 0; -+ break; -+ case SENSOR_BLS_TWO_LINES: -+ black_lines = 2; -+ break; -+ case SENSOR_BLS_FOUR_LINES: -+ black_lines = 4; -+ break; -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ REG_SET_SLICE(mrv_reg->isp_acq_h_offs, MRV_ISP_ACQ_H_OFFS, -+ 0 * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_offs, MRV_ISP_ACQ_V_OFFS, 0); -+ -+ dprintk(2, "res = %x", isi_cfg->res); -+ switch (isi_cfg->res) { -+ /* 88x72 */ -+ case SENSOR_RES_QQCIF: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QQCIF_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QQCIF_SIZE_V + black_lines); -+ break; -+ /* 160x120 */ -+ case SENSOR_RES_QQVGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QQVGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QQVGA_SIZE_V + black_lines); -+ break; -+ /* 176x144 */ -+ case SENSOR_RES_QCIF: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QCIF_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QCIF_SIZE_V + black_lines); -+ break; -+ /* 320x240 */ -+ case SENSOR_RES_QVGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QVGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QVGA_SIZE_V + black_lines); -+ break; -+ /* 352x288 */ -+ case SENSOR_RES_CIF: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ CIF_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ CIF_SIZE_V + black_lines); -+ break; -+ /* 640x480 */ -+ case SENSOR_RES_VGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ VGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ VGA_SIZE_V + black_lines); -+ break; -+ /* 800x600 */ -+ case SENSOR_RES_SVGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ SVGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ SVGA_SIZE_V + black_lines); -+ break; -+ /* 1024x768 */ -+ case SENSOR_RES_XGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ XGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ XGA_SIZE_V + black_lines); -+ break; -+ case SENSOR_RES_720P: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ RES_720P_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ RES_720P_SIZE_V + black_lines); -+ break; -+ /* 1280x960 */ -+ case SENSOR_RES_XGA_PLUS: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ XGA_PLUS_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ XGA_PLUS_SIZE_V + black_lines); -+ break; -+ /* 1280x1024 */ -+ case SENSOR_RES_SXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ SXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ SXGA_SIZE_V + black_lines); -+ break; -+ /* 1600x1200 */ -+ case SENSOR_RES_UXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QSVGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QSVGA_SIZE_V + black_lines); -+ break; -+ /* 1920x1280 */ -+ case SENSOR_RES_1080P: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ 1920 * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ 1080 + black_lines); -+ break; -+ /* 2048x1536 */ -+ case SENSOR_RES_QXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QXGA_SIZE_V + black_lines); -+ break; -+ /* 2586x2048 */ -+ case SENSOR_RES_QSXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QSXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QSXGA_SIZE_V + black_lines); -+ break; -+ /* 2600x2048 */ -+ case SENSOR_RES_QSXGA_PLUS: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QSXGA_PLUS_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QSXGA_PLUS_SIZE_V + black_lines); -+ break; -+ /* 2600x1950 */ -+ case SENSOR_RES_QSXGA_PLUS2: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QSXGA_PLUS2_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QSXGA_PLUS2_SIZE_V + black_lines); -+ break; -+ /* 2686x2048, 5.30M */ -+ case SENSOR_RES_QSXGA_PLUS3: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QSXGA_PLUS3_SIZE_V * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QSXGA_PLUS3_SIZE_V + black_lines); -+ break; -+ /* 2592*1944 5M */ -+ case SENSOR_RES_QXGA_PLUS: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QXGA_PLUS_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QXGA_PLUS_SIZE_V + black_lines); -+ break; -+ /* 3200x2048, 6.56M */ -+ case SENSOR_RES_WQSXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ WQSXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ WQSXGA_SIZE_V + black_lines); -+ break; -+ /* 3200x2400, 7.68M */ -+ case SENSOR_RES_QUXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ QUXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ QUXGA_SIZE_V + black_lines); -+ break; -+ /* 3840x2400, 9.22M */ -+ case SENSOR_RES_WQUXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ WQUXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ WQUXGA_SIZE_V + black_lines); -+ break; -+ /* 4096x3072, 12.59M */ -+ case SENSOR_RES_HXGA: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ HXGA_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ HXGA_SIZE_V + black_lines); -+ break; -+ /* 4080x1024 */ -+ case SENSOR_RES_YUV_HMAX: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ YUV_HMAX_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ YUV_HMAX_SIZE_V); -+ break; -+ /* 1024x4080 */ -+ case SENSOR_RES_YUV_VMAX: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ YUV_VMAX_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ YUV_VMAX_SIZE_V); -+ break; -+ /* 4096x2048 */ -+ case SENSOR_RES_RAWMAX: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ RAWMAX_SIZE_H); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ RAWMAX_SIZE_V); -+ break; -+ /* 352x240 */ -+ case SENSOR_RES_BP1: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ BP1_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ BP1_SIZE_V); -+ break; -+ /* 720x480 */ -+ case SENSOR_RES_L_AFM: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ L_AFM_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ L_AFM_SIZE_V); -+ break; -+ /* 128x96 */ -+ case SENSOR_RES_M_AFM: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ M_AFM_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ M_AFM_SIZE_V); -+ break; -+ /* 64x32 */ -+ case SENSOR_RES_S_AFM: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ S_AFM_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ S_AFM_SIZE_V); -+ break; -+ /* 1304x980 */ -+ case SENSOR_RES_VGA_PLUS: -+ REG_SET_SLICE(mrv_reg->isp_acq_h_size, MRV_ISP_ACQ_H_SIZE, -+ VGA_PLUS_SIZE_H * sample_factor); -+ REG_SET_SLICE(mrv_reg->isp_acq_v_size, MRV_ISP_ACQ_V_SIZE, -+ VGA_PLUS_SIZE_V); -+ break; -+ -+ default: -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * sets output window -+ */ -+void ci_isp_set_output_formatter(const struct ci_isp_window *window, -+ enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (window) { -+ /* set output window */ -+ REG_SET_SLICE(mrv_reg->isp_out_h_offs, MRV_IS_IS_H_OFFS, -+ window->hoffs); -+ REG_SET_SLICE(mrv_reg->isp_out_v_offs, MRV_IS_IS_V_OFFS, -+ window->voffs); -+ REG_SET_SLICE(mrv_reg->isp_out_h_size, MRV_IS_IS_H_SIZE, -+ window->hsize); -+ REG_SET_SLICE(mrv_reg->isp_out_v_size, MRV_IS_IS_V_SIZE, -+ window->vsize); -+ -+ REG_SET_SLICE(mrv_reg->isp_is_h_offs, MRV_IS_IS_H_OFFS, 0); -+ REG_SET_SLICE(mrv_reg->isp_is_v_offs, MRV_IS_IS_V_OFFS, 0); -+ REG_SET_SLICE(mrv_reg->isp_is_h_size, MRV_IS_IS_H_SIZE, -+ window->hsize); -+ REG_SET_SLICE(mrv_reg->isp_is_v_size, MRV_IS_IS_V_SIZE, -+ window->vsize); -+ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ /* frame synchronous update of shadow registers */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, -+ MRV_ISP_ISP_GEN_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ /* immediate update of shadow registers */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, -+ MRV_ISP_ISP_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ /* no update from within this function */ -+ break; -+ default: -+ break; -+ } -+ } -+} -+ -+/* -+ * programs the given Bayer pattern demosaic parameters -+ */ -+void ci_isp_set_demosaic(enum ci_isp_demosaic_mode demosaic_mode, -+ u8 demosaic_th) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_demosaic = REG_READ(mrv_reg->isp_demosaic); -+ -+ /* set demosaic mode */ -+ switch (demosaic_mode) { -+ case CI_ISP_DEMOSAIC_STANDARD: -+ REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_MODE, -+ MRV_ISP_DEMOSAIC_MODE_STD); -+ break; -+ case CI_ISP_DEMOSAIC_ENHANCED: -+ REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_MODE, -+ MRV_ISP_DEMOSAIC_MODE_ENH); -+ break; -+ default: -+ WARN_ON(!(false)); -+ } -+ -+ /* set demosaic threshold */ -+ REG_SET_SLICE(isp_demosaic, MRV_ISP_DEMOSAIC_TH, demosaic_th); -+ REG_WRITE(mrv_reg->isp_demosaic, isp_demosaic); -+} -+ -+/* -+ * Sets the dedicated AWB block mode. -+ */ -+int ci_isp_set_wb_mode(enum ci_isp_awb_mode wb_mode) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ switch (wb_mode) { -+ case CI_ISP_AWB_COMPLETELY_OFF: -+ /* manual WB, no measurements*/ -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE, -+ MRV_ISP_AWB_MODE_NOMEAS); -+ /* switch ABW block off */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE, -+ DISABLE); -+ break; -+ case CI_ISP_AWB_MAN_MEAS: -+ case CI_ISP_AWB_AUTO: -+ case CI_ISP_AWB_MAN_PUSH_AUTO: -+ case CI_ISP_AWB_ONLY_MEAS: -+ /* manual white balance, measure YCbCr means */ -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE, -+ MRV_ISP_AWB_MODE_MEAS); -+ /* switch ABW block on */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE, -+ ENABLE); -+ break; -+ case CI_ISP_AWB_MAN_NOMEAS: -+ /* manual white balance, no measurements */ -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE, -+ MRV_ISP_AWB_MODE_NOMEAS); -+ /* switch ABW block on */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE, -+ ENABLE); -+ break; -+ default: -+ /* to be sure that a regular value is set: */ -+ /* manual white balance, no measurements */ -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MODE, -+ MRV_ISP_AWB_MODE_NOMEAS); -+ /* switch ABW block off */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE, -+ DISABLE); -+ return CI_STATUS_FAILURE; -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_get_wb_mode(enum ci_isp_awb_mode *wb_mode) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!wb_mode) -+ return CI_STATUS_NULL_POINTER; -+ -+ if (REG_GET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_AWB_ENABLE) == -+ DISABLE) { -+ *wb_mode = CI_ISP_AWB_COMPLETELY_OFF; -+ } else { -+ -+ switch (REG_GET_SLICE(mrv_reg->isp_awb_prop, -+ MRV_ISP_AWB_MODE)) { -+ case MRV_ISP_AWB_MODE_MEAS: -+ *wb_mode = CI_ISP_AWB_MAN_MEAS; -+ break; -+ case MRV_ISP_AWB_MODE_NOMEAS: -+ *wb_mode = CI_ISP_AWB_MAN_NOMEAS; -+ break; -+ default: -+ *wb_mode = CI_ISP_AWB_COMPLETELY_OFF; -+ return CI_STATUS_FAILURE; -+ } -+ } -+ return CI_STATUS_SUCCESS; -+} -+int ci_isp_set_wb_meas_config(const struct ci_isp_wb_meas_config -+ *wb_meas_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_awb_thresh = REG_READ(mrv_reg->isp_awb_thresh); -+ -+ if (!wb_meas_config) -+ return CI_STATUS_NULL_POINTER; -+ -+ /* measurement window */ -+ REG_SET_SLICE(mrv_reg->isp_awb_h_size, MRV_ISP_AWB_H_SIZE, -+ (u32) wb_meas_config->awb_window.hsize); -+ REG_SET_SLICE(mrv_reg->isp_awb_v_size, MRV_ISP_AWB_V_SIZE, -+ (u32) wb_meas_config->awb_window.vsize); -+ REG_SET_SLICE(mrv_reg->isp_awb_h_offs, MRV_ISP_AWB_H_OFFS, -+ (u32) wb_meas_config->awb_window.hoffs); -+ REG_SET_SLICE(mrv_reg->isp_awb_v_offs, MRV_ISP_AWB_V_OFFS, -+ (u32) wb_meas_config->awb_window.voffs); -+ -+ /* adjust awb properties (Y_MAX compare) */ -+ if (wb_meas_config->max_y == 0) { -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN, -+ DISABLE); -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN, -+ ENABLE); -+ } -+ -+ /* measurement thresholds */ -+ REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MAX_Y, -+ (u32) wb_meas_config->max_y); -+ REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MIN_Y__MAX_G, -+ (u32) wb_meas_config->minY_MaxG); -+ REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MAX_CSUM, -+ (u32) wb_meas_config->max_csum); -+ REG_SET_SLICE(isp_awb_thresh, MRV_ISP_AWB_MIN_C, -+ (u32) wb_meas_config->min_c); -+ REG_WRITE(mrv_reg->isp_awb_thresh, isp_awb_thresh); -+ REG_SET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CR__MAX_R, -+ (u32)(wb_meas_config->ref_cr_MaxR)); -+ REG_SET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CB__MAX_B, -+ (u32)(wb_meas_config->ref_cb_MaxB)); -+ -+ /* amount of measurement frames */ -+ REG_SET_SLICE(mrv_reg->isp_awb_frames, MRV_ISP_AWB_FRAMES, -+ (u32) wb_meas_config->frames); -+ -+ /* set measurement mode */ -+ REG_SET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MEAS_MODE, -+ (u32)(wb_meas_config->meas_mode)); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_get_wb_meas_config(struct ci_isp_wb_meas_config *wb_meas_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!wb_meas_config) -+ return CI_STATUS_NULL_POINTER; -+ -+ /* measurement window */ -+ wb_meas_config->awb_window.hsize = -+ (u16) REG_GET_SLICE(mrv_reg->isp_awb_h_size, MRV_ISP_AWB_H_SIZE); -+ wb_meas_config->awb_window.vsize = -+ (u16) REG_GET_SLICE(mrv_reg->isp_awb_v_size, MRV_ISP_AWB_V_SIZE); -+ wb_meas_config->awb_window.hoffs = -+ (u16) REG_GET_SLICE(mrv_reg->isp_awb_h_offs, MRV_ISP_AWB_H_OFFS); -+ wb_meas_config->awb_window.voffs = -+ (u16) REG_GET_SLICE(mrv_reg->isp_awb_v_offs, MRV_ISP_AWB_V_OFFS); -+ -+ /* measurement thresholds */ -+ wb_meas_config->min_c = -+ (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, MRV_ISP_AWB_MIN_C); -+ wb_meas_config->max_csum = -+ (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, MRV_ISP_AWB_MAX_CSUM); -+ wb_meas_config->minY_MaxG = -+ (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, -+ MRV_ISP_AWB_MIN_Y__MAX_G); -+ wb_meas_config->max_y = -+ (u8) REG_GET_SLICE(mrv_reg->isp_awb_thresh, MRV_ISP_AWB_MAX_Y); -+ wb_meas_config->ref_cb_MaxB = -+ (u8)REG_GET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CB__MAX_B); -+ wb_meas_config->ref_cr_MaxR = -+ (u8)REG_GET_SLICE(mrv_reg->isp_awb_ref, MRV_ISP_AWB_REF_CR__MAX_R); -+ -+ /* amount of measurement frames */ -+ wb_meas_config->frames = -+ (u8) REG_GET_SLICE(mrv_reg->isp_awb_frames, MRV_ISP_AWB_FRAMES); -+ -+ /* overwrite max_y if the feature is disabled */ -+ if (REG_GET_SLICE(mrv_reg->isp_awb_prop, MRV_ISP_AWB_MAX_EN) == -+ DISABLE) { -+ wb_meas_config->max_y = 0; -+ } -+ -+ /* get measurement mode */ -+ wb_meas_config->meas_mode = REG_GET_SLICE(mrv_reg->isp_awb_prop, -+ MRV_ISP_AWB_MEAS_MODE); -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_get_wb_meas(struct ci_sensor_awb_mean *awb_mean) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (awb_mean == NULL) -+ return CI_STATUS_NULL_POINTER; -+ -+ awb_mean->white = REG_GET_SLICE(mrv_reg->isp_awb_white_cnt, -+ MRV_ISP_AWB_WHITE_CNT); -+ awb_mean->mean_Y__G = (u8) REG_GET_SLICE(mrv_reg->isp_awb_mean, -+ MRV_ISP_AWB_MEAN_Y__G); -+ awb_mean->mean_cb__B = (u8) REG_GET_SLICE(mrv_reg->isp_awb_mean, -+ MRV_ISP_AWB_MEAN_CB__B); -+ awb_mean->mean_cr__R = (u8) REG_GET_SLICE(mrv_reg->isp_awb_mean, -+ MRV_ISP_AWB_MEAN_CR__R); -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * calculates left-top and right-bottom register values -+ * for a given AF measurement window -+ */ -+static int ci_isp_afm_wnd2_regs(const struct ci_isp_window *wnd, u32 *lt, -+ u32 *rb) -+{ -+ WARN_ON(!((wnd != NULL) && (lt != NULL) && (rb != NULL))); -+ -+ if (wnd->hsize && wnd->vsize) { -+ u32 left = wnd->hoffs; -+ u32 top = wnd->voffs; -+ u32 right = left + wnd->hsize - 1; -+ u32 bottom = top + wnd->vsize - 1; -+ -+ if ((left < MRV_AFM_A_H_L_MIN) -+ || (left > MRV_AFM_A_H_L_MAX) -+ || (top < MRV_AFM_A_V_T_MIN) -+ || (top > MRV_AFM_A_V_T_MAX) -+ || (right < MRV_AFM_A_H_R_MIN) -+ || (right > MRV_AFM_A_H_R_MAX) -+ || (bottom < MRV_AFM_A_V_B_MIN) -+ || (bottom > MRV_AFM_A_V_B_MAX)) { -+ return CI_STATUS_OUTOFRANGE; -+ } -+ -+ /* combine the values and return */ -+ REG_SET_SLICE(*lt, MRV_AFM_A_H_L, left); -+ REG_SET_SLICE(*lt, MRV_AFM_A_V_T, top); -+ REG_SET_SLICE(*rb, MRV_AFM_A_H_R, right); -+ REG_SET_SLICE(*rb, MRV_AFM_A_V_B, bottom); -+ } else { -+ *lt = 0; -+ *rb = 0; -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_set_auto_focus(const struct ci_isp_af_config *af_config) -+{ -+ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 result = CI_STATUS_SUCCESS; -+ -+ /* disable measurement module */ -+ REG_SET_SLICE(mrv_reg->isp_afm_ctrl, MRV_AFM_AFM_EN, DISABLE); -+ -+ if (af_config) { -+ u32 lt; -+ u32 rb; -+ result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_a), -+ <, &rb); -+ /* set measurement window boundaries */ -+ if (result != CI_STATUS_SUCCESS) -+ return result; -+ -+ REG_WRITE(mrv_reg->isp_afm_lt_a, lt); -+ REG_WRITE(mrv_reg->isp_afm_rb_a, rb); -+ -+ result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_b), -+ <, &rb); -+ -+ if (result != CI_STATUS_SUCCESS) -+ return result; -+ -+ REG_WRITE(mrv_reg->isp_afm_lt_b, lt); -+ REG_WRITE(mrv_reg->isp_afm_rb_b, rb); -+ -+ result = ci_isp_afm_wnd2_regs(&(af_config->wnd_pos_c), -+ <, &rb); -+ -+ if (result != CI_STATUS_SUCCESS) -+ return result; -+ -+ REG_WRITE(mrv_reg->isp_afm_lt_c, lt); -+ REG_WRITE(mrv_reg->isp_afm_rb_c, rb); -+ -+ /* set other af measurement paraneters */ -+ REG_SET_SLICE(mrv_reg->isp_afm_thres, MRV_AFM_AFM_THRES, -+ af_config->threshold); -+ REG_SET_SLICE(mrv_reg->isp_afm_var_shift, MRV_AFM_LUM_VAR_SHIFT, -+ (af_config->var_shift >> 16)); -+ REG_SET_SLICE(mrv_reg->isp_afm_var_shift, MRV_AFM_AFM_VAR_SHIFT, -+ (af_config->var_shift >> 0)); -+ -+ /* enable measurement module */ -+ REG_SET_SLICE(mrv_reg->isp_afm_ctrl, MRV_AFM_AFM_EN, ENABLE); -+ } -+ -+ return result; -+} -+ -+ -+void ci_isp_get_auto_focus_meas(struct ci_isp_af_meas *af_meas) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ WARN_ON(!(af_meas != NULL)); -+ -+ af_meas->afm_sum_a = -+ REG_GET_SLICE(mrv_reg->isp_afm_sum_a, MRV_AFM_AFM_SUM_A); -+ af_meas->afm_sum_b = -+ REG_GET_SLICE(mrv_reg->isp_afm_sum_b, MRV_AFM_AFM_SUM_B); -+ af_meas->afm_sum_c = -+ REG_GET_SLICE(mrv_reg->isp_afm_sum_c, MRV_AFM_AFM_SUM_C); -+ af_meas->afm_lum_a = -+ REG_GET_SLICE(mrv_reg->isp_afm_lum_a, MRV_AFM_AFM_LUM_A); -+ af_meas->afm_lum_b = -+ REG_GET_SLICE(mrv_reg->isp_afm_lum_b, MRV_AFM_AFM_LUM_B); -+ af_meas->afm_lum_c = -+ REG_GET_SLICE(mrv_reg->isp_afm_lum_c, MRV_AFM_AFM_LUM_C); -+} -+ -+int ci_isp_set_ls_correction(struct ci_sensor_ls_corr_config *ls_corr_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 i, n; -+ u32 data = 0; -+ int enabled = false; -+ -+ if (!ls_corr_config) { -+ /* disable lens shading module */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, DISABLE); -+ } else { -+ /* test if lens shading correction is enabled */ -+ if (REG_GET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN)) { -+ /* switch off lens shading correction */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, -+ MRV_LSC_LSC_EN, DISABLE); -+ /* wait 1ms to make sure that -+ * the LSC have time enough to switch off */ -+ /* wait over 1 ms */ -+ /*mdelay(1000);*/ -+ msleep(1000); -+ enabled = true; -+ } -+ -+ /* clear address counters */ -+ REG_WRITE(mrv_reg->isp_lsc_r_table_addr, 0); -+ REG_WRITE(mrv_reg->isp_lsc_g_table_addr, 0); -+ REG_WRITE(mrv_reg->isp_lsc_b_table_addr, 0); -+ -+ /* program data tables (table size is 9 * 17 = 153; -+ * see also MRV_LSC_?_RAM_ADDR_MAX) */ -+ WARN_ON(!(((CI_ISP_MAX_LSC_SECTORS + 1) * -+ ((CI_ISP_MAX_LSC_SECTORS + 2) / 2)) == -+ (MRV_LSC_R_RAM_ADDR_MAX + 1))); -+ -+ /* 17 steps */ -+ for (n = 0; -+ n < ((CI_ISP_MAX_LSC_SECTORS + 1) * -+ (CI_ISP_MAX_LSC_SECTORS + 1)); -+ n += CI_ISP_MAX_LSC_SECTORS + 1) { -+ dprintk(2, "set ls correct step n = %d", n); -+ /* 17 sectors with 2 values in one DWORD = 9 -+ * DWORDs (8 steps + 1 outside loop) */ -+ for (i = 0; i < (CI_ISP_MAX_LSC_SECTORS); i += 2) { -+ REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_0, -+ ls_corr_config->ls_rdata_tbl[n + i]); -+ REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_1, -+ ls_corr_config->ls_rdata_tbl -+ [n + i + 1]); -+ REG_WRITE(mrv_reg->isp_lsc_r_table_data, data); -+ REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_0, -+ ls_corr_config->ls_gdata_tbl -+ [n + i]); -+ REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_1, -+ ls_corr_config->ls_gdata_tbl -+ [n + i + 1]); -+ REG_WRITE(mrv_reg->isp_lsc_g_table_data, data); -+ REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_0, -+ ls_corr_config->ls_bdata_tbl[n + i]); -+ REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_1, -+ ls_corr_config->ls_bdata_tbl -+ [n + i + 1]); -+ REG_WRITE(mrv_reg->isp_lsc_b_table_data, data); -+ } -+ REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_0, -+ ls_corr_config->ls_rdata_tbl -+ [n + CI_ISP_MAX_LSC_SECTORS]); -+ REG_SET_SLICE(data, MRV_LSC_R_SAMPLE_1, 0); -+ REG_WRITE(mrv_reg->isp_lsc_r_table_data, data); -+ REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_0, -+ ls_corr_config->ls_gdata_tbl -+ [n + CI_ISP_MAX_LSC_SECTORS]); -+ REG_SET_SLICE(data, MRV_LSC_G_SAMPLE_1, 0); -+ REG_WRITE(mrv_reg->isp_lsc_g_table_data, data); -+ REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_0, -+ ls_corr_config->ls_bdata_tbl -+ [n + CI_ISP_MAX_LSC_SECTORS]); -+ REG_SET_SLICE(data, MRV_LSC_B_SAMPLE_1, 0); -+ REG_WRITE(mrv_reg->isp_lsc_b_table_data, data); -+ } -+ -+ /* program x size tables */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_01, MRV_LSC_X_SECT_SIZE_0, -+ ls_corr_config->ls_xsize_tbl[0]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_01, MRV_LSC_X_SECT_SIZE_1, -+ ls_corr_config->ls_xsize_tbl[1]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_23, MRV_LSC_X_SECT_SIZE_2, -+ ls_corr_config->ls_xsize_tbl[2]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_23, MRV_LSC_X_SECT_SIZE_3, -+ ls_corr_config->ls_xsize_tbl[3]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_45, MRV_LSC_X_SECT_SIZE_4, -+ ls_corr_config->ls_xsize_tbl[4]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_45, MRV_LSC_X_SECT_SIZE_5, -+ ls_corr_config->ls_xsize_tbl[5]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_67, MRV_LSC_X_SECT_SIZE_6, -+ ls_corr_config->ls_xsize_tbl[6]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xsize_67, MRV_LSC_X_SECT_SIZE_7, -+ ls_corr_config->ls_xsize_tbl[7]); -+ -+ /* program y size tables */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_01, MRV_LSC_Y_SECT_SIZE_0, -+ ls_corr_config->ls_ysize_tbl[0]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_01, MRV_LSC_Y_SECT_SIZE_1, -+ ls_corr_config->ls_ysize_tbl[1]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_23, MRV_LSC_Y_SECT_SIZE_2, -+ ls_corr_config->ls_ysize_tbl[2]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_23, MRV_LSC_Y_SECT_SIZE_3, -+ ls_corr_config->ls_ysize_tbl[3]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_45, MRV_LSC_Y_SECT_SIZE_4, -+ ls_corr_config->ls_ysize_tbl[4]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_45, MRV_LSC_Y_SECT_SIZE_5, -+ ls_corr_config->ls_ysize_tbl[5]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_67, MRV_LSC_Y_SECT_SIZE_6, -+ ls_corr_config->ls_ysize_tbl[6]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ysize_67, MRV_LSC_Y_SECT_SIZE_7, -+ ls_corr_config->ls_ysize_tbl[7]); -+ -+ /* program x grad tables */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_01, MRV_LSC_XGRAD_0, -+ ls_corr_config->ls_xgrad_tbl[0]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_01, MRV_LSC_XGRAD_1, -+ ls_corr_config->ls_xgrad_tbl[1]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_23, MRV_LSC_XGRAD_2, -+ ls_corr_config->ls_xgrad_tbl[2]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_23, MRV_LSC_XGRAD_3, -+ ls_corr_config->ls_xgrad_tbl[3]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_45, MRV_LSC_XGRAD_4, -+ ls_corr_config->ls_xgrad_tbl[4]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_45, MRV_LSC_XGRAD_5, -+ ls_corr_config->ls_xgrad_tbl[5]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_67, MRV_LSC_XGRAD_6, -+ ls_corr_config->ls_xgrad_tbl[6]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_xgrad_67, MRV_LSC_XGRAD_7, -+ ls_corr_config->ls_xgrad_tbl[7]); -+ -+ /* program y grad tables */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_01, MRV_LSC_YGRAD_0, -+ ls_corr_config->ls_ygrad_tbl[0]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_01, MRV_LSC_YGRAD_1, -+ ls_corr_config->ls_ygrad_tbl[1]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_23, MRV_LSC_YGRAD_2, -+ ls_corr_config->ls_ygrad_tbl[2]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_23, MRV_LSC_YGRAD_3, -+ ls_corr_config->ls_ygrad_tbl[3]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_45, MRV_LSC_YGRAD_4, -+ ls_corr_config->ls_ygrad_tbl[4]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_45, MRV_LSC_YGRAD_5, -+ ls_corr_config->ls_ygrad_tbl[5]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_67, MRV_LSC_YGRAD_6, -+ ls_corr_config->ls_ygrad_tbl[6]); -+ REG_SET_SLICE(mrv_reg->isp_lsc_ygrad_67, MRV_LSC_YGRAD_7, -+ ls_corr_config->ls_ygrad_tbl[7]); -+ -+ if (enabled) { -+ /* switch on lens chading correction */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, -+ MRV_LSC_LSC_EN, ENABLE); -+ } -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_ls_correction_on_off(int ls_corr_on_off) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (ls_corr_on_off) { -+ /* switch on lens chading correction */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, ENABLE); -+ } else { -+ /* switch off lens chading correction */ -+ REG_SET_SLICE(mrv_reg->isp_lsc_ctrl, MRV_LSC_LSC_EN, DISABLE); -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Sets the Bad Pixel Correction configuration -+ */ -+int ci_isp_set_bp_correction(const struct ci_isp_bp_corr_config -+ *bp_corr_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_bp_ctrl = REG_READ(mrv_reg->isp_bp_ctrl); -+ -+ if (!bp_corr_config) { -+ /* disable correction module */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, DISABLE); -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, DISABLE); -+ } else { -+ /* set bad pixel configuration */ -+ if (bp_corr_config->bp_corr_type == CI_ISP_BP_CORR_DIRECT) { -+ /* direct detection */ -+ u32 isp_bp_cfg1 = REG_READ(mrv_reg->isp_bp_cfg1); -+ u32 isp_bp_cfg2 = REG_READ(mrv_reg->isp_bp_cfg2); -+ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_COR_TYPE, -+ MRV_BP_COR_TYPE_DIRECT); -+ -+ WARN_ON(!(!REG_GET_SLICE(mrv_reg->isp_bp_ctrl, -+ MRV_BP_BP_DET_EN))); -+ -+ /* threshold register only used for direct mode */ -+ REG_SET_SLICE(isp_bp_cfg1, MRV_BP_HOT_THRES, -+ bp_corr_config->bp_abs_hot_thres); -+ REG_SET_SLICE(isp_bp_cfg1, MRV_BP_DEAD_THRES, -+ bp_corr_config->bp_abs_dead_thres); -+ REG_WRITE(mrv_reg->isp_bp_cfg1, isp_bp_cfg1); -+ REG_SET_SLICE(isp_bp_cfg2, MRV_BP_DEV_HOT_THRES, -+ bp_corr_config->bp_dev_hot_thres); -+ REG_SET_SLICE(isp_bp_cfg2, MRV_BP_DEV_DEAD_THRES, -+ bp_corr_config->bp_dev_dead_thres); -+ REG_WRITE(mrv_reg->isp_bp_cfg2, isp_bp_cfg2); -+ } else { -+ /* use bad pixel table */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_COR_TYPE, -+ MRV_BP_COR_TYPE_TABLE); -+ } -+ -+ if (bp_corr_config->bp_corr_rep == CI_ISP_BP_CORR_REP_LIN) { -+ /* use linear approch */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_REP_APPR, -+ MRV_BP_REP_APPR_INTERPOL); -+ } else { -+ /* use best neighbour */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_REP_APPR, -+ MRV_BP_REP_APPR_NEAREST); -+ } -+ -+ switch (bp_corr_config->bp_corr_mode) { -+ case CI_ISP_BP_CORR_HOT_EN: -+ /* enable Hot */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, ENABLE); -+ /* disable Dead */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, DISABLE); -+ break; -+ case CI_ISP_BP_CORR_DEAD_EN: -+ /* disable Hot */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, DISABLE); -+ /* enable Dead */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, ENABLE); -+ break; -+ case CI_ISP_BP_CORR_HOT_DEAD_EN: -+ default: -+ /* enable Hot */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_HOT_COR_EN, ENABLE); -+ /* enable Dead */ -+ REG_SET_SLICE(isp_bp_ctrl, MRV_BP_DEAD_COR_EN, ENABLE); -+ break; -+ } -+ } -+ -+ REG_WRITE(mrv_reg->isp_bp_ctrl, isp_bp_ctrl); -+ -+ return CI_STATUS_SUCCESS; -+ -+} -+ -+/* -+ * Sets the Bad Pixel configuration for detection -+ */ -+int ci_isp_set_bp_detection(const struct ci_isp_bp_det_config *bp_det_config) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!bp_det_config) { -+ /* disable measurement module */ -+ REG_SET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_BP_DET_EN, DISABLE); -+ } else { -+ WARN_ON(!(REG_GET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_COR_TYPE) -+ == MRV_BP_COR_TYPE_TABLE)); -+ -+ /* set dead threshold for bad pixel detection */ -+ REG_SET_SLICE(mrv_reg->isp_bp_cfg1, MRV_BP_DEAD_THRES, -+ bp_det_config->bp_dead_thres); -+ -+ /* enable measurement module */ -+ REG_SET_SLICE(mrv_reg->isp_bp_ctrl, MRV_BP_BP_DET_EN, ENABLE); -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_clear_bp_int(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* clear bp_det irq (only if it is signalled to prevent loss of irqs) */ -+ if (REG_GET_SLICE(mrv_reg->isp_ris, MRV_ISP_RIS_BP_DET)) -+ REG_SET_SLICE(mrv_reg->isp_icr, MRV_ISP_ICR_BP_DET, 1); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Initializes Isp filter registers with default reset values. -+ */ -+static int ci_isp_initialize_filter_registers(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ mrv_reg->isp_filt_mode = 0x00000000; -+ mrv_reg->isp_filt_fac_sh1 = 0x00000010; -+ mrv_reg->isp_filt_fac_sh0 = 0x0000000C; -+ mrv_reg->isp_filt_fac_mid = 0x0000000A; -+ mrv_reg->isp_filt_fac_bl0 = 0x00000006; -+ mrv_reg->isp_filt_fac_bl1 = 0x00000002; -+ mrv_reg->isp_filt_thresh_bl0 = 0x0000000D; -+ mrv_reg->isp_filt_thresh_bl1 = 0x00000005; -+ mrv_reg->isp_filt_thresh_sh0 = 0x0000001A; -+ mrv_reg->isp_filt_thresh_sh1 = 0x0000002C; -+ mrv_reg->isp_filt_lum_weight = 0x00032040; -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_isp_activate_filter(int activate_filter) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ int retval = CI_STATUS_SUCCESS; -+ -+ /* Initialize ISP filter control registers first */ -+ retval = ci_isp_initialize_filter_registers(); -+ if (retval != CI_STATUS_SUCCESS) -+ return retval; -+ -+ /* Activate or deactivate filter algorythm */ -+ REG_SET_SLICE(mrv_reg->isp_filt_mode, MRV_FILT_FILT_ENABLE, -+ (activate_filter) ? ENABLE : DISABLE); -+ -+ return retval; -+} -+ -+/* -+ * Write coefficient and threshold values into Isp filter -+ * registers for noise, sharpness and blurring filtering. -+ */ -+int ci_isp_set_filter_params(u8 noise_reduc_level, u8 sharp_level) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 isp_filt_mode = 0; -+ -+ if (!REG_GET_SLICE(mrv_reg->isp_filt_mode, MRV_FILT_FILT_ENABLE)) -+ return CI_STATUS_CANCELED; -+ -+ REG_WRITE(mrv_reg->isp_filt_mode, isp_filt_mode); -+ -+ if (((noise_reduc_level <= 10) || (noise_reduc_level == 99)) -+ && (sharp_level <= 10)) { -+ switch (noise_reduc_level) { -+ /* Test Mode */ -+ case 99: -+ /* 10 bit max value */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 0x000003FF); -+ /* 10 bit max value */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 0x000003FF); -+ /* 10 bit max value */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 0x000003FF); -+ /* 10 bit max value */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 0x000003FF); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 0 -+ /* MRV_FILT_STAGE1_SELECT_MAX_BLUR */); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_BYPASS); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_BYPASS); -+ break; -+ -+ case 0: -+ /* NoiseReductionLevel = 0 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 0x000000); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 0x000000); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 0x000000); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 0x000000); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 6); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC8); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_BYPASS); -+ break; -+ -+ case 1: -+ /* NoiseReductionLevel = 1; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 33); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 18); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 8); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 2); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 6); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 2: -+ /* NoiseReductionLevel = 2; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 44); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 26); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 13); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 5); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 4 -+ /* MRV_FILT_STAGE1_SELECT_DEFAULT */); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 3: -+ /* NoiseReductionLevel = 3; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 51); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 36); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 23); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 10); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 4 -+ /* MRV_FILT_STAGE1_SELECT_DEFAULT */); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 4: -+ /* NoiseReductionLevel = 4; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 67); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 41); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 26); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 15); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 3); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 5: -+ /* NoiseReductionLevel = 5; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 100); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 75); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 50); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 20); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 3); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 6: -+ /* NoiseReductionLevel = 6; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 120); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 90); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 60); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 26); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 2); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 7: -+ /* NoiseReductionLevel = 7; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 150); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 120); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 80); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 51); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 2); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 8: -+ /* NoiseReductionLevel = 8; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 200); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 170); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 140); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 100); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, 2); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 9: -+ /* NoiseReductionLevel = 9; */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 300); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 250); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 180); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 150); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, -+ (sharp_level > 3) ? 2 : 1); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ case 10: -+ /* NoiseReductionLevel = 10; extrem noise */ -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, 1023); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 1023); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl0, -+ MRV_FILT_FILT_THRESH_BL0, 1023); -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_bl1, -+ MRV_FILT_FILT_THRESH_BL1, 1023); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_STAGE1_SELECT, -+ (sharp_level > 5) ? 2 : -+ ((sharp_level > 3) ? 1 : 0)); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_V_MODE, -+ MRV_FILT_FILT_CHR_V_MODE_STATIC12); -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_CHR_H_MODE, -+ MRV_FILT_FILT_CHR_H_MODE_DYN_2); -+ break; -+ -+ default: -+ return CI_STATUS_OUTOFRANGE; -+ } -+ -+ switch (sharp_level) { -+ /* SharpLevel = 0; no sharp enhancement */ -+ case 0: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000004); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x00000004); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000004); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000002); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000000); -+ break; -+ -+ /* SharpLevel = 1; */ -+ case 1: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000008); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x00000007); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000006); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000002); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000000); -+ break; -+ -+ /* SharpLevel = 2; */ -+ case 2: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x0000000C); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x0000000A); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000008); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000004); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000000); -+ break; -+ -+ /* SharpLevel = 3; */ -+ case 3: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000010); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x0000000C); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x0000000A); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000006); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000002); -+ break; -+ -+ /* SharpLevel = 4; */ -+ case 4: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000016); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x00000010); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x0000000C); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000008); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000004); -+ break; -+ -+ /* SharpLevel = 5; */ -+ case 5: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x0000001B); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x00000014); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000010); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x0000000A); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000004); -+ break; -+ -+ /* SharpLevel = 6; */ -+ case 6: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000020); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x0000001A); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000013); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x0000000C); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000006); -+ break; -+ -+ /* SharpLevel = 7; */ -+ case 7: -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000026); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x0000001E); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000017); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000010); -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000008); -+ break; -+ -+ /* SharpLevel = 8; */ -+ case 8: -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 0x00000013); -+ if (REG_GET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1) > 0x0000008A) { -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, -+ 0x0000008A); -+ } -+ /* 43 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x0000002C); -+ /* 36 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x00000024); -+ /* 29 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x0000001D); -+ /* 21 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000015); -+ /* 14 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x0000000D); -+ break; -+ -+ /* SharpLevel = 9; */ -+ case 9: -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ MRV_FILT_FILT_THRESH_SH0, 0x00000013); -+ if (REG_GET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1) > 0x0000008A) { -+ REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ MRV_FILT_FILT_THRESH_SH1, -+ 0x0000008A); -+ } -+ /* 48 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x00000030); -+ /* 42 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x0000002A); -+ /* 34 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000022); -+ /* 26 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x0000001A); -+ /* 20 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000014); -+ break; -+ -+ /* SharpLevel = 10; */ -+ case 10: -+ /* REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh0, -+ * MRV_FILT_FILT_THRESH_SH0, 0x00000013); */ -+ /* if (REG_GET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ * MRV_FILT_FILT_THRESH_SH1) > 0x0000008A) */ -+ /* { */ -+ /* REG_SET_SLICE(mrv_reg->isp_filt_thresh_sh1, -+ * MRV_FILT_FILT_THRESH_SH1, 0x0000008A); */ -+ /* } */ -+ -+ /* 63 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh1, -+ MRV_FILT_FILT_FAC_SH1, 0x0000003F); -+ /* 48 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_sh0, -+ MRV_FILT_FILT_FAC_SH0, 0x00000030); -+ /* 40 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_mid, -+ MRV_FILT_FILT_FAC_MID, 0x00000028); -+ /* 36 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, 0x00000024); -+ /* 32 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, 0x00000020); -+ break; -+ -+ default: -+ return CI_STATUS_OUTOFRANGE; -+ } -+ -+ if (noise_reduc_level > 7) { -+ if (sharp_level > 7) { -+ u32 filt_fac_bl0 = REG_GET_SLICE -+ (mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0); -+ u32 filt_fac_bl1 = -+ REG_GET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1); -+ /* * 0.50 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, -+ (filt_fac_bl0) >> 1); -+ /* * 0.25 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, -+ (filt_fac_bl1) >> 2); -+ } else if (sharp_level > 4) { -+ u32 filt_fac_bl0 = -+ REG_GET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0); -+ u32 filt_fac_bl1 = -+ REG_GET_SLICE(mrv_reg-> -+ isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1); -+ /* * 0.75 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl0, -+ MRV_FILT_FILT_FAC_BL0, -+ (filt_fac_bl0 * 3) >> 2); -+ /* * 0.50 */ -+ REG_SET_SLICE(mrv_reg->isp_filt_fac_bl1, -+ MRV_FILT_FILT_FAC_BL1, -+ (filt_fac_bl1) >> 1); -+ } -+ } -+ -+ /* Set ISP filter mode register values */ -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_MODE, -+ MRV_FILT_FILT_MODE_DYNAMIC); -+ -+ /* enable filter */ -+ REG_SET_SLICE(isp_filt_mode, MRV_FILT_FILT_ENABLE, ENABLE); -+ REG_WRITE(mrv_reg->isp_filt_mode, isp_filt_mode); -+ -+ return CI_STATUS_SUCCESS; -+ } else { -+ /* At least one function parameter is out of range */ -+ return CI_STATUS_OUTOFRANGE; -+ } -+} -+ -+int ci_isp_meas_exposure_initialize_module(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ REG_SET_SLICE(mrv_reg->isp_exp_h_size, MRV_AE_ISP_EXP_H_SIZE, 0); -+ REG_SET_SLICE(mrv_reg->isp_exp_v_size, MRV_AE_ISP_EXP_V_SIZE, 0); -+ REG_SET_SLICE(mrv_reg->isp_exp_h_offset, MRV_AE_ISP_EXP_H_OFFSET, 0); -+ REG_SET_SLICE(mrv_reg->isp_exp_v_offset, MRV_AE_ISP_EXP_V_OFFSET, 0); -+ -+ return CI_STATUS_SUCCESS; -+ -+} -+ -+/* -+ * Configures the exposure measurement module. -+ */ -+int ci_isp_meas_exposure_set_config(const struct ci_isp_window *wnd, -+ const struct ci_isp_exp_ctrl *isp_exp_ctrl) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ if (!wnd) { -+ /* stop loop if running */ -+ REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_AUTOSTOP, ON); -+ /* required? */ -+ REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_START, OFF); -+ return CI_STATUS_SUCCESS; -+ } -+ -+ /* range check */ -+ if ((wnd->hoffs > MRV_AE_ISP_EXP_H_OFFSET_MAX) -+ || (wnd->hsize > MRV_AE_ISP_EXP_H_SIZE_MAX) -+ || (wnd->voffs > MRV_AE_ISP_EXP_V_OFFSET_MAX) -+ || (wnd->vsize > MRV_AE_ISP_EXP_V_SIZE_MAX) -+ || (wnd->vsize & ~MRV_AE_ISP_EXP_V_SIZE_VALID_MASK)) -+ return CI_STATUS_OUTOFRANGE; -+ -+ /* configure measurement windows */ -+ REG_SET_SLICE(mrv_reg->isp_exp_h_size, MRV_AE_ISP_EXP_H_SIZE, -+ wnd->hsize); -+ REG_SET_SLICE(mrv_reg->isp_exp_v_size, MRV_AE_ISP_EXP_V_SIZE, -+ wnd->vsize); -+ REG_SET_SLICE(mrv_reg->isp_exp_h_offset, MRV_AE_ISP_EXP_H_OFFSET, -+ wnd->hoffs); -+ REG_SET_SLICE(mrv_reg->isp_exp_v_offset, MRV_AE_ISP_EXP_V_OFFSET, -+ wnd->voffs); -+ -+ /* set exposure measurement mode */ -+ REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_MEAS_MODE, -+ (isp_exp_ctrl->exp_meas_mode) ? ON : OFF); -+ -+ /* set or clear AE autostop bit */ -+ REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_AUTOSTOP, -+ (isp_exp_ctrl->auto_stop) ? ON : OFF); -+ REG_SET_SLICE(mrv_reg->isp_exp_ctrl, MRV_AE_EXP_START, -+ (isp_exp_ctrl->exp_start) ? ON : OFF); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Programs the given gamma curve for the input gamma -+ * block. Enables or disables gamma processing for the -+ * input gamma block. -+ */ -+void ci_isp_set_gamma(const struct ci_sensor_gamma_curve *r, -+ const struct ci_sensor_gamma_curve *g, -+ const struct ci_sensor_gamma_curve *b) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *)MEM_MRV_REG_BASE; -+ /* values stored as 16bit - use MSBs if cambuswidth is smaller */ -+ const u8 shift_val = 16 - MARVIN_FEATURE_CAMBUSWIDTH; -+ /* used to round up values */ -+ const u16 round_ofs = 0 << (shift_val - 1); -+ s32 i; -+ -+ if (r) { -+ -+ /* -+ * Note: gamma curve increments are already register conform, -+ * so REG_WRITE is used instead of REG_SET_SLICE -+ */ -+ -+ /* -+ * better would be split into 16 separate values to be -+ * register independant -+ */ -+ -+ /* gamma curve dx1..dx16 increments (each nibble of */ -+ REG_WRITE(mrv_reg->isp_gamma_dx_lo, r->gamma_dx0); -+ /* the 32bit-values hold 3 valid bits, see register) */ -+ REG_WRITE(mrv_reg->isp_gamma_dx_hi, r->gamma_dx1); -+ -+ for (i = 0; i < MRV_ISP_GAMMA_R_Y_ARR_SIZE; i++) { -+ REG_SET_SLICE(mrv_reg->isp_gamma_r_y[i], -+ MRV_ISP_GAMMA_R_Y, -+ (r->isp_gamma_y[i] + round_ofs) >> shift_val); -+ REG_SET_SLICE(mrv_reg->isp_gamma_g_y[i], -+ MRV_ISP_GAMMA_G_Y, -+ (g->isp_gamma_y[i] + round_ofs) >> shift_val); -+ REG_SET_SLICE(mrv_reg->isp_gamma_b_y[i], -+ MRV_ISP_GAMMA_B_Y, -+ (b->isp_gamma_y[i] + round_ofs) >> shift_val); -+ } -+ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, -+ MRV_ISP_ISP_GAMMA_IN_ENABLE, ENABLE); -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_ctrl, -+ MRV_ISP_ISP_GAMMA_IN_ENABLE, DISABLE); -+ } -+} -+ -+/* -+ * Programs the given gamma curve for the output gamma -+ * block. Enables or disables gamma processing for the -+ * output gamma block. -+ */ -+void ci_isp_set_gamma2(const struct ci_isp_gamma_out_curve *gamma) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ s32 i; -+ -+ if (gamma) { -+ WARN_ON(!(MRV_ISP_GAMMA_OUT_Y_ARR_SIZE == -+ CI_ISP_GAMMA_OUT_CURVE_ARR_SIZE)); -+ -+ for (i = 0; i < MRV_ISP_GAMMA_OUT_Y_ARR_SIZE; i++) { -+ REG_SET_SLICE(mrv_reg->isp_gamma_out_y[i], -+ MRV_ISP_ISP_GAMMA_OUT_Y, -+ gamma->isp_gamma_y[i]); -+ } -+ -+ /* gamma curve linear or log */ -+ REG_SET_SLICE(mrv_reg->isp_gamma_out_mode, MRV_ISP_EQU_SEGM, -+ gamma->gamma_segmentation); -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GAMMA_OUT_ENABLE, -+ ENABLE); -+ } else { -+ REG_SET_SLICE(mrv_reg->isp_ctrl, -+ MRV_ISP_ISP_GAMMA_OUT_ENABLE, DISABLE); -+ } -+ -+} -diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c b/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c -new file mode 100644 -index 0000000..c042e06 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/mrstisp_jpe.c -@@ -0,0 +1,569 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * Copyright (c) Silicon Image 2008 www.siliconimage.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+ -+int ci_isp_jpe_init_ex(u16 hsize, u16 vsize, u8 compression_ratio, u8 jpe_scale) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* -+ * Reset JPEG-Encoder. In contrast to other software resets -+ * this triggers the modules asynchronous reset resulting -+ * in loss of all data. -+ */ -+ -+ REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_JPEG_SOFT_RST, ON); -+ REG_SET_SLICE(mrv_reg->vi_ircl, MRV_VI_JPEG_SOFT_RST, OFF); -+ -+ /* set configuration for the Jpeg capturing */ -+ ci_isp_jpe_set_config(hsize, vsize, jpe_scale); -+ -+ /* -+ * Sleep a while before setting up tables because of the 400 -+ * clock cycles required to initialize the table RAM after a -+ * reset was issued. On FPGA we are running with only 30MHz, -+ * so at least 13us are required. -+ */ -+ -+ -+ /* -+ * Note: this func is called when holding spin lock, -+ * so can not change to msleep. -+ */ -+ mdelay(15); -+ -+ /* program tables */ -+ ci_isp_jpe_set_tables(compression_ratio); -+ -+ /* choose tables */ -+ ci_isp_jpe_select_tables(); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * initialization of JPEG encoder -+ */ -+int ci_isp_jpe_init(u32 resolution, u8 compression_ratio, int jpe_scale) -+{ -+ u16 hsize = 0; -+ u16 vsize = 0; -+ -+ switch (resolution) { -+ case SENSOR_RES_BP1: -+ /* 352; */ -+ hsize = BP1_SIZE_H; -+ /* 240; */ -+ vsize = BP1_SIZE_V; -+ break; -+ case SENSOR_RES_S_AFM: -+ /* 64; */ -+ hsize = S_AFM_SIZE_H; -+ /* 32; */ -+ vsize = S_AFM_SIZE_V; -+ break; -+ case SENSOR_RES_M_AFM: -+ /* 128; */ -+ hsize = M_AFM_SIZE_H; -+ /* 96; */ -+ vsize = M_AFM_SIZE_V; -+ break; -+ case SENSOR_RES_L_AFM: -+ /* 720; */ -+ hsize = L_AFM_SIZE_H; -+ /* 480; */ -+ vsize = L_AFM_SIZE_V; -+ break; -+ case SENSOR_RES_QQCIF: -+ /* 88; */ -+ hsize = QQCIF_SIZE_H; -+ /* 72; */ -+ vsize = QQCIF_SIZE_V; -+ break; -+ case SENSOR_RES_QQVGA: -+ /* 160; */ -+ hsize = QQVGA_SIZE_H; -+ /* 120; */ -+ vsize = QQVGA_SIZE_V; -+ break; -+ case SENSOR_RES_QCIF: -+ /* 176; */ -+ hsize = QCIF_SIZE_H; -+ /* 144; */ -+ vsize = QCIF_SIZE_V; -+ break; -+ case SENSOR_RES_QVGA: -+ /* 320; */ -+ hsize = QVGA_SIZE_H; -+ /* 240; */ -+ vsize = QVGA_SIZE_V; -+ break; -+ case SENSOR_RES_CIF: -+ /* 352; */ -+ hsize = CIF_SIZE_H; -+ /* 288; */ -+ vsize = CIF_SIZE_V; -+ break; -+ case SENSOR_RES_VGA: -+ /* 640; */ -+ hsize = VGA_SIZE_H; -+ /* 480; */ -+ vsize = VGA_SIZE_V; -+ break; -+ case SENSOR_RES_SVGA: -+ /* 800; */ -+ hsize = SVGA_SIZE_H; -+ /* 600; */ -+ vsize = SVGA_SIZE_V; -+ break; -+ case SENSOR_RES_XGA: -+ /* 1024; */ -+ hsize = XGA_SIZE_H; -+ /* 768; */ -+ vsize = XGA_SIZE_V; -+ break; -+ case SENSOR_RES_XGA_PLUS: -+ /* 1280; */ -+ hsize = XGA_PLUS_SIZE_H; -+ /* 960; */ -+ vsize = XGA_PLUS_SIZE_V; -+ break; -+ case SENSOR_RES_SXGA: -+ /* 1280; */ -+ hsize = SXGA_SIZE_H; -+ /* 1024; */ -+ vsize = SXGA_SIZE_V; -+ break; -+ case SENSOR_RES_UXGA: -+ /* 1600; */ -+ hsize = UXGA_SIZE_H; -+ /* 1200; */ -+ vsize = UXGA_SIZE_V; -+ break; -+ case SENSOR_RES_QXGA: -+ /* 2048; */ -+ hsize = QXGA_SIZE_H; -+ /* 1536; */ -+ vsize = QXGA_SIZE_V; -+ break; -+ case SENSOR_RES_QSXGA: -+ /* 2586; */ -+ hsize = QSXGA_SIZE_H; -+ /* 2048; */ -+ vsize = QSXGA_SIZE_V; -+ break; -+ case SENSOR_RES_QSXGA_PLUS: -+ /* 2600; */ -+ hsize = QSXGA_PLUS_SIZE_H; -+ /* 2048; */ -+ vsize = QSXGA_PLUS_SIZE_V; -+ break; -+ case SENSOR_RES_QSXGA_PLUS2: -+ /* 2600; */ -+ hsize = QSXGA_PLUS2_SIZE_H; -+ /* 1950; */ -+ vsize = QSXGA_PLUS2_SIZE_V; -+ break; -+ case SENSOR_RES_QSXGA_PLUS3: -+ /* 2686; */ -+ hsize = QSXGA_PLUS3_SIZE_H; -+ /* 2048; */ -+ vsize = QSXGA_PLUS3_SIZE_V; -+ break; -+ case SENSOR_RES_WQSXGA: -+ /* 3200 */ -+ hsize = WQSXGA_SIZE_H; -+ /* 2048 */ -+ vsize = WQSXGA_SIZE_V; -+ break; -+ case SENSOR_RES_QUXGA: -+ /* 3200 */ -+ hsize = QUXGA_SIZE_H; -+ /* 2400 */ -+ vsize = QUXGA_SIZE_V; -+ break; -+ case SENSOR_RES_WQUXGA: -+ /* 3840 */ -+ hsize = WQUXGA_SIZE_H; -+ /* 2400 */ -+ vsize = WQUXGA_SIZE_V; -+ break; -+ case SENSOR_RES_HXGA: -+ /* 4096 */ -+ hsize = HXGA_SIZE_H; -+ /* 3072 */ -+ vsize = HXGA_SIZE_V; -+ break; -+ default: -+ eprintk("resolution not supported"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ return ci_isp_jpe_init_ex(hsize, vsize, compression_ratio, jpe_scale); -+} -+ -+void ci_isp_jpe_set_tables(u8 compression_ratio) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ /* required because auto-increment register */ -+ u32 jpe_table_data = 0; -+ -+ u8 idx, size; -+ const u8 *yqtable = NULL; -+ const u8 *uvqtable = NULL; -+ -+ switch (compression_ratio) { -+ case CI_ISP_JPEG_LOW_COMPRESSION: -+ yqtable = ci_isp_yq_table_low_comp1; -+ uvqtable = ci_isp_uv_qtable_low_comp1; -+ break; -+ case CI_ISP_JPEG_01_PERCENT: -+ yqtable = ci_isp_yq_table01_per_cent; -+ uvqtable = ci_isp_uv_qtable01_per_cent; -+ break; -+ case CI_ISP_JPEG_20_PERCENT: -+ yqtable = ci_isp_yq_table20_per_cent; -+ uvqtable = ci_isp_uv_qtable20_per_cent; -+ break; -+ case CI_ISP_JPEG_30_PERCENT: -+ yqtable = ci_isp_yq_table30_per_cent; -+ uvqtable = ci_isp_uv_qtable30_per_cent; -+ break; -+ case CI_ISP_JPEG_40_PERCENT: -+ yqtable = ci_isp_yq_table40_per_cent; -+ uvqtable = ci_isp_uv_qtable40_per_cent; -+ break; -+ case CI_ISP_JPEG_50_PERCENT: -+ yqtable = ci_isp_yq_table50_per_cent; -+ uvqtable = ci_isp_uv_qtable50_per_cent; -+ break; -+ case CI_ISP_JPEG_60_PERCENT: -+ yqtable = ci_isp_yq_table60_per_cent; -+ uvqtable = ci_isp_uv_qtable60_per_cent; -+ break; -+ case CI_ISP_JPEG_70_PERCENT: -+ yqtable = ci_isp_yq_table70_per_cent; -+ uvqtable = ci_isp_uv_qtable70_per_cent; -+ break; -+ case CI_ISP_JPEG_80_PERCENT: -+ yqtable = ci_isp_yq_table80_per_cent; -+ uvqtable = ci_isp_uv_qtable80_per_cent; -+ break; -+ case CI_ISP_JPEG_90_PERCENT: -+ yqtable = ci_isp_yq_table90_per_cent; -+ uvqtable = ci_isp_uv_qtable90_per_cent; -+ break; -+ case CI_ISP_JPEG_99_PERCENT: -+ yqtable = ci_isp_yq_table99_per_cent; -+ uvqtable = ci_isp_uv_qtable99_per_cent; -+ break; -+ case CI_ISP_JPEG_HIGH_COMPRESSION: -+ default: -+ /* -+ * in the case an unknown value is set, -+ * use CI_JPEG_HIGH_COMPRESSION -+ */ -+ yqtable = ci_isp_yq_table75_per_cent; -+ uvqtable = ci_isp_uv_qtable75_per_cent; -+ break; -+ } -+ -+ /* Y q-table 0 programming */ -+ -+ /* all possible assigned tables have same size */ -+ size = sizeof(ci_isp_yq_table75_per_cent)/ -+ sizeof(ci_isp_yq_table75_per_cent[0]); -+ REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID, -+ MRV_JPE_TABLE_ID_QUANT0); -+ for (idx = 0; idx < (size - 1); idx += 2) { -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H, -+ yqtable[idx]); -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L, -+ yqtable[idx + 1]); -+ /* auto-increment register! */ -+ REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data); -+ } -+ -+ /* U/V q-table 0 programming */ -+ -+ /* all possible assigned tables have same size */ -+ size = sizeof(ci_isp_uv_qtable75_per_cent) / -+ sizeof(ci_isp_uv_qtable75_per_cent[0]); -+ REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID, -+ MRV_JPE_TABLE_ID_QUANT1); -+ for (idx = 0; idx < (size - 1); idx += 2) { -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H, -+ uvqtable[idx]); -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L, -+ uvqtable[idx + 1]); -+ /* auto-increment register! */ -+ REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data); -+ } -+ -+ /* Y AC-table 0 programming */ -+ -+ size = sizeof(ci_isp_ac_luma_table_annex_k) / -+ sizeof(ci_isp_ac_luma_table_annex_k[0]); -+ REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID, -+ MRV_JPE_TABLE_ID_VLC_AC0); -+ REG_SET_SLICE(mrv_reg->jpe_tac0_len, MRV_JPE_TAC0_LEN, size); -+ for (idx = 0; idx < (size - 1); idx += 2) { -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H, -+ ci_isp_ac_luma_table_annex_k[idx]); -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L, -+ ci_isp_ac_luma_table_annex_k[idx + 1]); -+ /* auto-increment register! */ -+ REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data); -+ } -+ -+ /* U/V AC-table 1 programming */ -+ -+ size = sizeof(ci_isp_ac_chroma_table_annex_k) / -+ sizeof(ci_isp_ac_chroma_table_annex_k[0]); -+ REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID, -+ MRV_JPE_TABLE_ID_VLC_AC1); -+ REG_SET_SLICE(mrv_reg->jpe_tac1_len, MRV_JPE_TAC1_LEN, size); -+ for (idx = 0; idx < (size - 1); idx += 2) { -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H, -+ ci_isp_ac_chroma_table_annex_k[idx]); -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L, -+ ci_isp_ac_chroma_table_annex_k[idx + 1]); -+ /* auto-increment register! */ -+ REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data); -+ } -+ -+ /* Y DC-table 0 programming */ -+ -+ size = sizeof(ci_isp_dc_luma_table_annex_k) / -+ sizeof(ci_isp_dc_luma_table_annex_k[0]); -+ REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID, -+ MRV_JPE_TABLE_ID_VLC_DC0); -+ REG_SET_SLICE(mrv_reg->jpe_tdc0_len, MRV_JPE_TDC0_LEN, size); -+ for (idx = 0; idx < (size - 1); idx += 2) { -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H, -+ ci_isp_dc_luma_table_annex_k[idx]); -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L, -+ ci_isp_dc_luma_table_annex_k[idx + 1]); -+ /* auto-increment register! */ -+ REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data); -+ } -+ -+ /* U/V DC-table 1 programming */ -+ -+ size = sizeof(ci_isp_dc_chroma_table_annex_k) / -+ sizeof(ci_isp_dc_chroma_table_annex_k[0]); -+ REG_SET_SLICE(mrv_reg->jpe_table_id, MRV_JPE_TABLE_ID, -+ MRV_JPE_TABLE_ID_VLC_DC1); -+ REG_SET_SLICE(mrv_reg->jpe_tdc1_len, MRV_JPE_TDC1_LEN, size); -+ for (idx = 0; idx < (size - 1); idx += 2) { -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_H, -+ ci_isp_dc_chroma_table_annex_k[idx]); -+ REG_SET_SLICE(jpe_table_data, MRV_JPE_TABLE_WDATA_L, -+ ci_isp_dc_chroma_table_annex_k[idx + 1]); -+ /* auto-increment register! */ -+ REG_WRITE(mrv_reg->jpe_table_data, jpe_table_data); -+ } -+} -+ -+/* -+ * selects tables to be used by encoder -+ */ -+void ci_isp_jpe_select_tables(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* selects quantization table for Y */ -+ REG_SET_SLICE(mrv_reg->jpe_tq_y_select, MRV_JPE_TQ0_SELECT, -+ MRV_JPE_TQ_SELECT_TAB0); -+ /* selects quantization table for U */ -+ REG_SET_SLICE(mrv_reg->jpe_tq_u_select, MRV_JPE_TQ1_SELECT, -+ MRV_JPE_TQ_SELECT_TAB1); -+ /* selects quantization table for V */ -+ REG_SET_SLICE(mrv_reg->jpe_tq_v_select, MRV_JPE_TQ2_SELECT, -+ MRV_JPE_TQ_SELECT_TAB1); -+ /* selects Huffman DC table */ -+ REG_SET_SLICE(mrv_reg->jpe_dc_table_select, -+ MRV_JPE_DC_TABLE_SELECT_Y, 0); -+ REG_SET_SLICE(mrv_reg->jpe_dc_table_select, -+ MRV_JPE_DC_TABLE_SELECT_U, 1); -+ REG_SET_SLICE(mrv_reg->jpe_dc_table_select, -+ MRV_JPE_DC_TABLE_SELECT_V, 1); -+ /* selects Huffman AC table */ -+ REG_SET_SLICE(mrv_reg->jpe_ac_table_select, -+ MRV_JPE_AC_TABLE_SELECT_Y, 0); -+ REG_SET_SLICE(mrv_reg->jpe_ac_table_select, -+ MRV_JPE_AC_TABLE_SELECT_U, 1); -+ REG_SET_SLICE(mrv_reg->jpe_ac_table_select, -+ MRV_JPE_AC_TABLE_SELECT_V, 1); -+} -+ -+/* -+ * configure JPEG encoder -+ */ -+void ci_isp_jpe_set_config(u16 hsize, u16 vsize, int jpe_scale) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ /* JPEG image size */ -+ -+ REG_SET_SLICE(mrv_reg->jpe_enc_hsize, MRV_JPE_ENC_HSIZE, hsize); -+ REG_SET_SLICE(mrv_reg->jpe_enc_vsize, MRV_JPE_ENC_VSIZE, vsize); -+ -+ if (jpe_scale) { -+ /* upscaling of BT601 color space to full range 0..255 */ -+ REG_SET_SLICE(mrv_reg->jpe_y_scale_en, MRV_JPE_Y_SCALE_EN, -+ ENABLE); -+ REG_SET_SLICE(mrv_reg->jpe_cbcr_scale_en, -+ MRV_JPE_CBCR_SCALE_EN, ENABLE); -+ } else { -+ /* bypass scaler */ -+ REG_SET_SLICE(mrv_reg->jpe_y_scale_en, -+ MRV_JPE_Y_SCALE_EN, DISABLE); -+ REG_SET_SLICE(mrv_reg->jpe_cbcr_scale_en, -+ MRV_JPE_CBCR_SCALE_EN, DISABLE); -+ } -+ -+ /* picture format YUV 422 */ -+ REG_SET_SLICE(mrv_reg->jpe_pic_format, MRV_JPE_ENC_PIC_FORMAT, -+ MRV_JPE_ENC_PIC_FORMAT_422); -+ REG_SET_SLICE(mrv_reg->jpe_table_flush, MRV_JPE_TABLE_FLUSH, 0); -+} -+ -+int ci_isp_jpe_generate_header(struct mrst_isp_device *intel, u8 header_mode) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ WARN_ON(!((header_mode == MRV_JPE_HEADER_MODE_JFIF) -+ || (header_mode == MRV_JPE_HEADER_MODE_NO))); -+ -+ /* clear jpeg gen_header_done interrupt */ -+ /* since we poll them later to detect command completion */ -+ -+ REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_GEN_HEADER_DONE, 1); -+ REG_SET_SLICE(mrv_reg->jpe_header_mode, MRV_JPE_HEADER_MODE, -+ header_mode); -+ -+ /* start header generation */ -+ REG_SET_SLICE(mrv_reg->jpe_gen_header, MRV_JPE_GEN_HEADER, ON); -+ -+ return ci_isp_jpe_wait_for_header_gen_done(intel); -+} -+ -+void ci_isp_jpe_prep_enc(enum ci_isp_jpe_enc_mode jpe_enc_mode) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 jpe_encode = REG_READ(mrv_reg->jpe_encode); -+ -+ /* clear jpeg encode_done interrupt */ -+ /* since we poll them later to detect command completion */ -+ -+ REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ENCODE_DONE, 1); -+ REG_SET_SLICE(jpe_encode, MRV_JPE_ENCODE, ON); -+ -+ switch (jpe_enc_mode) { -+ case CI_ISP_JPE_LARGE_CONT_MODE: -+ /* motion JPEG with header generation */ -+ REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE, -+ MRV_JPE_CONT_MODE_HEADER); -+ break; -+ case CI_ISP_JPE_SHORT_CONT_MODE: -+ /* motion JPEG only first frame with header */ -+ REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE, -+ MRV_JPE_CONT_MODE_NEXT); -+ break; -+ default: -+ /* single shot JPEG */ -+ REG_SET_SLICE(jpe_encode, MRV_JPE_CONT_MODE, -+ MRV_JPE_CONT_MODE_STOP); -+ break; -+ } -+ -+ REG_WRITE(mrv_reg->jpe_encode, jpe_encode); -+ REG_SET_SLICE(mrv_reg->jpe_init, MRV_JPE_JP_INIT, 1); -+} -+ -+/* -+ * wait until JPG Header is generated (MRV_JPGINT_GEN_HEADER_DONE -+ * interrupt occurs) -+ * waiting for JPG Header to be generated -+ */ -+int ci_isp_jpe_wait_for_header_gen_done(struct mrst_isp_device *intel) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ mrst_timer_start(); -+ -+ while (!REG_GET_SLICE(mrv_reg->jpe_status_ris, -+ MRV_JPE_GEN_HEADER_DONE)) { -+ if (mrst_get_micro_sec() > 2000000) { -+ mrst_timer_stop(); -+ eprintk("timeout"); -+ return CI_STATUS_FAILURE; -+ } -+ } -+ -+ mrst_timer_stop(); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * wait until JPG Encoder is done (MRV_JPGINT_ENCODE_DONE -+ * interrupt occurs) waiting for the JPG Encoder to be done -+ */ -+int ci_isp_jpe_wait_for_encode_done(struct mrst_isp_device *intel) -+{ -+#if 0 -+ int ret = 0; -+ INIT_COMPLETION(intel->jpe_complete); -+ ret = wait_for_completion_interruptible_timeout(&intel->jpe_complete, -+ 100 * HZ); -+ if ((ret == 0) | (intel->irq_stat == IRQ_JPE_ERROR)) { -+ eprintk("timeout"); -+ return CI_STATUS_FAILURE; -+ } -+ -+ return CI_STATUS_SUCCESS; -+#endif -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ mrst_timer_start(); -+ -+ while (!REG_GET_SLICE(mrv_reg->jpe_status_ris, -+ MRV_JPE_ENCODE_DONE)) { -+ if (mrst_get_micro_sec() > 200000) { -+ mrst_timer_stop(); -+ eprintk("timeout"); -+ return CI_STATUS_FAILURE; -+ } -+ } -+ -+ mrst_timer_stop(); -+ -+ /* clear jpeg encode_done interrupt */ -+ REG_SET_SLICE(mrv_reg->jpe_status_icr, MRV_JPE_ENCODE_DONE, 1); -+ -+ return CI_STATUS_SUCCESS; -+} -diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_main.c b/drivers/media/video/mrstci/mrstisp/mrstisp_main.c -new file mode 100644 -index 0000000..e37b3d1 ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/mrstisp_main.c -@@ -0,0 +1,2977 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+#include "ci_isp_fmts_common.h" -+ -+#define GPIO_SCLK_25 44 -+#define GPIO_STDBY1_PIN 48 -+#define GPIO_STDBY2_PIN 49 -+#define GPIO_RESET_PIN 50 -+ -+int mrstisp_debug; -+module_param(mrstisp_debug, int, 0644); -+ -+/*XXX*/ -+static int frame_cnt; -+static long mipi_error_num; -+static u32 mipi_error_flag; -+static long isp_error_num; -+static u32 isp_error_flag; -+static unsigned long jiffies_start; -+static int mipi_flag; -+ -+void intel_timer_start(void) -+{ -+ jiffies_start = jiffies; -+} -+void intel_timer_stop(void) -+{ -+ jiffies_start = 0; -+} -+unsigned long intel_get_micro_sec(void) -+{ -+ unsigned long time_diff = 0; -+ -+ time_diff = jiffies - jiffies_start; -+ -+ return jiffies_to_msecs(time_diff); -+} -+ -+ -+static inline struct mrst_isp_device *to_isp(struct v4l2_device *dev) -+{ -+ return container_of(dev, struct mrst_isp_device, v4l2_dev); -+} -+ -+static struct mrst_camera mrst_camera_table[] = { -+ { -+ .type = MRST_CAMERA_SOC, -+ .name = "ov2650", -+ .sensor_addr = 0x30, -+ }, -+ { -+ .type = MRST_CAMERA_SOC, -+ .name = "ov9665", -+ .sensor_addr = 0x30, -+ }, -+ { -+ .type = MRST_CAMERA_RAW, -+ .name = "ov5630", -+ .sensor_addr = 0x36, -+ .motor_name = "ov5630_motor", -+ .motor_addr = (0x18 >> 1), -+ }, -+ { -+ .type = MRST_CAMERA_RAW, -+ .name = "s5k4e1", -+ .sensor_addr = 0x36, -+ .motor_name = "s5k4e1_motor", -+ .motor_addr = (0x18 >> 1), -+ }, -+}; -+ -+#define N_CAMERA (ARRAY_SIZE(mrst_camera_table)) -+ -+struct videobuf_dma_contig_memory { -+ u32 magic; -+ void *vaddr; -+ dma_addr_t dma_handle; -+ unsigned long size; -+ int is_userptr; -+}; -+#define MAGIC_DC_MEM 0x0733ac61 -+#define MAGIC_CHECK(is, should) \ -+ if (unlikely((is) != (should))) { \ -+ pr_err("magic mismatch: %x expected %x\n", (is), (should)); \ -+ BUG(); \ -+ } -+/* flag to determine whether to do the handler of mblk_line irq */ -+int mrst_isp_to_do_mblk_line; -+unsigned char *mrst_isp_regs; -+ -+static inline struct ci_sensor_config *to_sensor_config(struct v4l2_subdev *sd) -+{ -+ return container_of(sd, struct ci_sensor_config, sd); -+} -+ -+/* g45-th20-b5 gamma out curve with enhanced black level */ -+static struct ci_isp_gamma_out_curve g45_th20_b5 = { -+ { -+ 0x0000, 0x0014, 0x003C, 0x0064, -+ 0x00A0, 0x0118, 0x0171, 0x01A7, -+ 0x01D8, 0x0230, 0x027A, 0x02BB, -+ 0x0323, 0x0371, 0x03AD, 0x03DB, -+ 0x03FF} -+ , -+ 0 -+}; -+ -+static void print_snr_cfg(struct ci_sensor_config *cfg) -+{ -+ dprintk(2, "bus width = %x", cfg->bus_width); -+ dprintk(2, "mode = %x", cfg->mode); -+ dprintk(2, "field_inv = %x", cfg->field_inv); -+ dprintk(2, "field_sel = %x", cfg->field_sel); -+ dprintk(2, "ycseq = %x", cfg->ycseq); -+ dprintk(2, "conv422 = %x", cfg->conv422); -+ dprintk(2, "bpat = %x", cfg->bpat); -+ dprintk(2, "hpol = %x", cfg->hpol); -+ dprintk(2, "vpol = %x", cfg->vpol); -+ dprintk(2, "edge = %x", cfg->edge); -+ dprintk(2, "bls = %x", cfg->bls); -+ dprintk(2, "gamma = %x", cfg->gamma); -+ dprintk(2, "cconv = %x", cfg->cconv); -+ dprintk(2, "res = %x", cfg->res); -+ dprintk(2, "blc = %x", cfg->blc); -+ dprintk(2, "agc = %x", cfg->agc); -+ dprintk(2, "awb = %x", cfg->awb); -+ dprintk(2, "aec = %x", cfg->aec); -+ dprintk(2, "cie_profile = %x", cfg->cie_profile); -+ dprintk(2, "flicker_freq = %x", cfg->flicker_freq); -+ dprintk(2, "smia_mode = %x", cfg->smia_mode); -+ dprintk(2, "mipi_mode = %x", cfg->mipi_mode); -+ dprintk(2, "type = %x", cfg->type); -+ dprintk(2, "name = %s", cfg->name); -+} -+ -+static int mrst_isp_defcfg_all_load(struct ci_isp_config *isp_config) -+{ -+ -+ DBG_entering; -+ -+ /* demosaic mode */ -+ isp_config->demosaic_mode = CI_ISP_DEMOSAIC_ENHANCED; -+ -+ /* bpc */ -+ isp_config->bpc_cfg.bp_corr_type = CI_ISP_BP_CORR_DIRECT; -+ isp_config->bpc_cfg.bp_corr_rep = CI_ISP_BP_CORR_REP_NB; -+ isp_config->bpc_cfg.bp_corr_mode = CI_ISP_BP_CORR_HOT_DEAD_EN; -+ isp_config->bpc_cfg.bp_abs_hot_thres = 496; -+ isp_config->bpc_cfg.bp_abs_dead_thres = 20; -+ isp_config->bpc_cfg.bp_dev_hot_thres = 328; -+ isp_config->bpc_cfg.bp_dev_dead_thres = 328; -+ isp_config->bpd_cfg.bp_dead_thres = 1; -+ -+ /* WB */ -+ isp_config->wb_config.mrv_wb_mode = CI_ISP_AWB_AUTO; -+ isp_config->wb_config.mrv_wb_sub_mode = CI_ISP_AWB_AUTO_ON; -+ isp_config->wb_config.awb_pca_damping = 16; -+ isp_config->wb_config.awb_prior_exp_damping = 12; -+ isp_config->wb_config.awb_pca_push_damping = 16; -+ isp_config->wb_config.awb_prior_exp_push_damping = 12; -+ isp_config->wb_config.awb_auto_max_y = 254; -+ isp_config->wb_config.awb_push_max_y = 250; -+ isp_config->wb_config.awb_measure_max_y = 200; -+ isp_config->wb_config.awb_underexp_det = 10; -+ isp_config->wb_config.awb_push_underexp_det = 170; -+ -+ /* CAC */ -+ isp_config->cac_config.hsize = 2048; -+ isp_config->cac_config.vsize = 1536; -+ isp_config->cac_config.hcenter_offset = 0; -+ isp_config->cac_config.vcenter_offset = 0; -+ isp_config->cac_config.hclip_mode = 1; -+ isp_config->cac_config.vclip_mode = 2; -+ isp_config->cac_config.ablue = 24; -+ isp_config->cac_config.ared = 489; -+ isp_config->cac_config.bblue = 450; -+ isp_config->cac_config.bred = 53; -+ isp_config->cac_config.cblue = 40; -+ isp_config->cac_config.cred = 479; -+ isp_config->cac_config.aspect_ratio = 0.000000; -+ -+ /* BLS */ -+ isp_config->bls_cfg.enable_automatic = 0; -+ isp_config->bls_cfg.disable_h = 0; -+ isp_config->bls_cfg.disable_v = 0; -+ isp_config->bls_cfg.isp_bls_window1.enable_window = 0; -+ isp_config->bls_cfg.isp_bls_window1.start_h = 0; -+ isp_config->bls_cfg.isp_bls_window1.stop_h = 0; -+ isp_config->bls_cfg.isp_bls_window1.start_v = 0; -+ isp_config->bls_cfg.isp_bls_window1.stop_v = 0; -+ isp_config->bls_cfg.isp_bls_window2.enable_window = 0; -+ isp_config->bls_cfg.isp_bls_window2.start_h = 0; -+ isp_config->bls_cfg.isp_bls_window2.stop_h = 0; -+ isp_config->bls_cfg.isp_bls_window2.start_v = 0; -+ isp_config->bls_cfg.isp_bls_window2.stop_v = 0; -+ isp_config->bls_cfg.bls_samples = 5; -+ isp_config->bls_cfg.bls_subtraction.fixed_a = 0x100; -+ isp_config->bls_cfg.bls_subtraction.fixed_b = 0x100; -+ isp_config->bls_cfg.bls_subtraction.fixed_c = 0x100; -+ isp_config->bls_cfg.bls_subtraction.fixed_d = 0x100; -+ -+ /* AF */ -+ isp_config->af_cfg.wnd_pos_a.hoffs = 874; -+ isp_config->af_cfg.wnd_pos_a.voffs = 618; -+ isp_config->af_cfg.wnd_pos_a.hsize = 300; -+ isp_config->af_cfg.wnd_pos_a.vsize = 300; -+ isp_config->af_cfg.wnd_pos_b.hoffs = 0; -+ isp_config->af_cfg.wnd_pos_b.voffs = 0; -+ isp_config->af_cfg.wnd_pos_b.hsize = 0; -+ isp_config->af_cfg.wnd_pos_b.vsize = 0; -+ isp_config->af_cfg.wnd_pos_c.hoffs = 0; -+ isp_config->af_cfg.wnd_pos_c.voffs = 0; -+ isp_config->af_cfg.wnd_pos_c.hsize = 0; -+ isp_config->af_cfg.wnd_pos_c.vsize = 0; -+ isp_config->af_cfg.threshold = 0x00000000; -+ -+ /* color */ -+ isp_config->color.contrast = 128; -+ isp_config->color.brightness = 0; -+ isp_config->color.saturation = 128; -+ isp_config->color.hue = 0; -+ -+ /* Img Effect */ -+ isp_config->img_eff_cfg.mode = CI_ISP_IE_MODE_OFF; -+ isp_config->img_eff_cfg.color_sel = 4; -+ isp_config->img_eff_cfg.color_thres = 128; -+ isp_config->img_eff_cfg.tint_cb = 108; -+ isp_config->img_eff_cfg.tint_cr = 141; -+ isp_config->img_eff_cfg.mat_emboss.coeff_11 = 2; -+ isp_config->img_eff_cfg.mat_emboss.coeff_12 = 1; -+ isp_config->img_eff_cfg.mat_emboss.coeff_13 = 0; -+ isp_config->img_eff_cfg.mat_emboss.coeff_21 = 1; -+ isp_config->img_eff_cfg.mat_emboss.coeff_22 = 0; -+ isp_config->img_eff_cfg.mat_emboss.coeff_23 = -1; -+ isp_config->img_eff_cfg.mat_emboss.coeff_31 = 0; -+ isp_config->img_eff_cfg.mat_emboss.coeff_32 = -1; -+ isp_config->img_eff_cfg.mat_emboss.coeff_33 = -2; -+ isp_config->img_eff_cfg.mat_sketch.coeff_11 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_12 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_13 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_21 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_22 = 8; -+ isp_config->img_eff_cfg.mat_sketch.coeff_23 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_31 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_32 = -1; -+ isp_config->img_eff_cfg.mat_sketch.coeff_33 = -1; -+ -+ /* Framefun */ -+ isp_config->flags.bls = 0; -+ isp_config->flags.lsc = 0; -+ isp_config->flags.bpc = 0; -+ isp_config->flags.awb = 0; -+ isp_config->flags.aec = 0; -+ isp_config->flags.af = 0; -+ isp_config->flags.cp = 0; -+ isp_config->flags.gamma = 0; -+ isp_config->flags.cconv = 0; -+ isp_config->flags.demosaic = 0; -+ isp_config->flags.gamma2 = 0; -+ isp_config->flags.isp_filters = 0; -+ isp_config->flags.cac = 0; -+ isp_config->flags.cconv_basic = 0; -+ isp_config->demosaic_th = 4; -+ -+ isp_config->view_finder.flags = VFFLAG_HWRGB; -+ -+ isp_config->afm_mode = 1; -+ isp_config->filter_level_noise_reduc = 4; -+ isp_config->filter_level_sharp = 4; -+ -+ isp_config->jpeg_enc_ratio = 1; -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static void mrst_isp_update_marvinvfaddr(struct mrst_isp_device *isp, -+ u32 buffer_base, -+ enum ci_isp_conf_update_time update_time) -+{ -+ struct ci_isp_mi_path_conf isp_mi_path_conf; -+ struct ci_isp_mi_path_conf isp_sf_mi_path_conf; -+ static struct v4l2_jpg_review_buffer *jpg_review; -+ u32 bufsize = 0; -+ u32 w; -+ u32 h; -+ -+ jpg_review = &isp->sys_conf.jpg_review; -+ memset(&isp_mi_path_conf, 0, sizeof(struct ci_isp_mi_path_conf)); -+ memset(&isp_sf_mi_path_conf, 0, sizeof(struct ci_isp_mi_path_conf)); -+ -+ w = isp_mi_path_conf.llength = isp->bufwidth; -+ h = isp_mi_path_conf.ypic_height = isp->bufheight; -+ isp_mi_path_conf.ypic_width = isp->bufwidth; -+ -+ /*XXX Zheng: disable jpg review for MIPI sensor */ -+ /*if ((isp->sys_conf.isi_config)->mipi_mode == SENSOR_MIPI_MODE_RAW_10) -+ isp->sys_conf.jpg_review_enable = 0; -+ */ -+ -+ if (isp->sys_conf.jpg_review_enable) { -+ -+ /* for self path, JPEG review */ -+ isp_sf_mi_path_conf.ypic_width = jpg_review->width; -+ isp_sf_mi_path_conf.llength = jpg_review->width; -+ isp_sf_mi_path_conf.ypic_height = jpg_review->height; -+ -+ bufsize = jpg_review->width * jpg_review->height; -+ -+ /* buffer size in bytes */ -+ if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV420 -+ || jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420) { -+ -+ dprintk(3, "VF yuv420 fmt"); -+ isp_sf_mi_path_conf.ybuffer.size = bufsize; -+ isp_sf_mi_path_conf.cb_buffer.size = bufsize/4; -+ isp_sf_mi_path_conf.cr_buffer.size = bufsize/4; -+ -+ } else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV422P) { -+ -+ dprintk(3, "VF yuv422 fmt"); -+ isp_sf_mi_path_conf.ybuffer.size = bufsize; -+ isp_sf_mi_path_conf.cb_buffer.size = bufsize/2; -+ isp_sf_mi_path_conf.cr_buffer.size = bufsize/2; -+ -+ } else if (jpg_review->pix_fmt == V4L2_PIX_FMT_NV12) { -+ -+ dprintk(3, "VF nv12 fmt"); -+ isp_sf_mi_path_conf.ybuffer.size = bufsize; -+ isp_sf_mi_path_conf.cb_buffer.size = bufsize/2; -+ isp_sf_mi_path_conf.cr_buffer.size = 0; -+ -+ } else { -+ printk(KERN_ERR "mrstisp: no support jpg review fmt\n"); -+ } -+ -+ /* buffer address */ -+ if (isp_sf_mi_path_conf.ybuffer.size != 0) { -+ isp_sf_mi_path_conf.ybuffer.pucbuffer = -+ (u8 *)(unsigned long) -+ isp->mb1 + isp->mb1_size - 640*480*2; -+ } -+ -+ if (isp_sf_mi_path_conf.cb_buffer.size != 0) { -+ isp_sf_mi_path_conf.cb_buffer.pucbuffer = -+ isp_sf_mi_path_conf.ybuffer.pucbuffer + -+ isp_sf_mi_path_conf.ybuffer.size; -+ } -+ -+ if (isp_sf_mi_path_conf.cr_buffer.size != 0) { -+ isp_sf_mi_path_conf.cr_buffer.pucbuffer = -+ isp_sf_mi_path_conf.cb_buffer.pucbuffer + -+ isp_sf_mi_path_conf.cb_buffer.size; -+ } -+ -+ if (jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420) { -+ isp_sf_mi_path_conf.cr_buffer.pucbuffer = -+ isp_sf_mi_path_conf.ybuffer.pucbuffer + -+ isp_sf_mi_path_conf.ybuffer.size; -+ isp_sf_mi_path_conf.cb_buffer.pucbuffer = -+ isp_sf_mi_path_conf.cr_buffer.pucbuffer + -+ isp_sf_mi_path_conf.cr_buffer.size; -+ } -+ -+ } -+ -+ if (isp->pixelformat == V4L2_PIX_FMT_YUV420 || -+ isp->pixelformat == V4L2_PIX_FMT_YVU420 || -+ isp->pixelformat == V4L2_PIX_FMT_YUV422P || -+ isp->pixelformat == V4L2_PIX_FMT_NV12) { -+ bufsize = w*h; -+ } else -+ bufsize = isp->frame_size; -+ -+ /* buffer size in bytes */ -+ if (isp->pixelformat == V4L2_PIX_FMT_YUV420 -+ || isp->pixelformat == V4L2_PIX_FMT_YVU420) { -+ -+ dprintk(3, "yuv420 fmt"); -+ isp_mi_path_conf.ybuffer.size = bufsize; -+ isp_mi_path_conf.cb_buffer.size = bufsize/4; -+ isp_mi_path_conf.cr_buffer.size = bufsize/4; -+ } else if (isp->pixelformat == V4L2_PIX_FMT_YUV422P) { -+ -+ dprintk(3, "yuv422 fmt"); -+ isp_mi_path_conf.ybuffer.size = bufsize; -+ isp_mi_path_conf.cb_buffer.size = bufsize/2; -+ isp_mi_path_conf.cr_buffer.size = bufsize/2; -+ } else if (isp->pixelformat == V4L2_PIX_FMT_NV12) { -+ -+ dprintk(3, "nv12 fmt"); -+ isp_mi_path_conf.ybuffer.size = bufsize; -+ isp_mi_path_conf.cb_buffer.size = bufsize/2; -+ isp_mi_path_conf.cr_buffer.size = 0; -+ } else { -+ -+ dprintk(3, "jpeg and rgb fmt"); -+ isp_mi_path_conf.ybuffer.size = bufsize; -+ isp_mi_path_conf.cb_buffer.size = 0; -+ isp_mi_path_conf.cr_buffer.size = 0; -+ } -+ -+ /* buffer address */ -+ if (isp_mi_path_conf.ybuffer.size != 0) { -+ isp_mi_path_conf.ybuffer.pucbuffer = -+ (u8 *)(unsigned long) buffer_base; -+ } -+ -+ if (isp_mi_path_conf.cb_buffer.size != 0) { -+ isp_mi_path_conf.cb_buffer.pucbuffer = -+ isp_mi_path_conf.ybuffer.pucbuffer + -+ isp_mi_path_conf.ybuffer.size; -+ } -+ -+ if (isp_mi_path_conf.cr_buffer.size != 0) { -+ isp_mi_path_conf.cr_buffer.pucbuffer = -+ isp_mi_path_conf.cb_buffer.pucbuffer + -+ isp_mi_path_conf.cb_buffer.size; -+ } -+ -+ if (isp->pixelformat == V4L2_PIX_FMT_YVU420) { -+ isp_mi_path_conf.cr_buffer.pucbuffer = -+ isp_mi_path_conf.ybuffer.pucbuffer + -+ isp_mi_path_conf.ybuffer.size; -+ isp_mi_path_conf.cb_buffer.pucbuffer = -+ isp_mi_path_conf.cr_buffer.pucbuffer + -+ isp_mi_path_conf.cr_buffer.size; -+ } -+ -+ if (isp->sys_conf.isp_cfg.view_finder.flags & VFFLAG_USE_MAINPATH) { -+ ci_isp_mif_set_main_buffer(&isp_mi_path_conf, update_time); -+ if (isp->pixelformat == V4L2_PIX_FMT_JPEG) -+ if (isp->sys_conf.jpg_review_enable) -+ ci_isp_mif_set_self_buffer( -+ &isp_sf_mi_path_conf, update_time); -+ } else { -+ ci_isp_mif_set_self_buffer(&isp_mi_path_conf, update_time); -+ } -+} -+ -+static int mrst_isp_setup_viewfinder_path(struct mrst_isp_device *isp, -+ struct ci_sensor_config *isi_config, -+ int zoom) -+{ -+ int error = CI_STATUS_SUCCESS; -+ struct ci_isp_datapath_desc dp_main; -+ struct ci_isp_datapath_desc dp_self; -+ struct ci_isp_rect self_rect; -+ u16 isi_hsize; -+ u16 isi_vsize; -+ int jpe_scale; -+ struct ci_pl_system_config *sys_conf = &isp->sys_conf; -+ struct ci_isp_config *config = &sys_conf->isp_cfg; -+ struct v4l2_jpg_review_buffer *jpg_review = &sys_conf->jpg_review; -+ u32 dp_mode; -+ -+ DBG_entering; -+ -+ if (sys_conf->isp_cfg.flags.ycbcr_full_range) -+ jpe_scale = false; -+ else -+ jpe_scale = true; -+ -+ memset(&dp_main, 0, sizeof(struct ci_isp_datapath_desc)); -+ memset(&dp_self, 0, sizeof(struct ci_isp_datapath_desc)); -+ -+ self_rect.x = 0; -+ self_rect.y = 0; -+ self_rect.w = isp->bufwidth; /* 640 */ -+ self_rect.h = isp->bufheight; /* 480 */ -+ -+ if (isp->pixelformat == V4L2_PIX_FMT_JPEG) { -+ -+ dprintk(1, "jpeg fmt"); -+ -+ dp_main.flags = CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPJPEG; -+ config->view_finder.flags |= VFFLAG_USE_MAINPATH; -+ -+ dp_main.out_w = (u16) isp->bufwidth; -+ dp_main.out_h = (u16) isp->bufheight; -+ -+ if (isp->sys_conf.jpg_review_enable) { -+ -+ dprintk(1, "jpg_review enabled in VF"); -+ -+ self_rect.w = jpg_review->width; -+ self_rect.h = jpg_review->height; -+ -+ dp_self.flags = (CI_ISP_DPD_ENABLE -+ | CI_ISP_DPD_MODE_ISPYC); -+ if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV420 || -+ jpg_review->pix_fmt == V4L2_PIX_FMT_YVU420) -+ dp_self.flags |= CI_ISP_DPD_YUV_420 -+ | CI_ISP_DPD_CSS_V2; -+ else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUV422P) -+ dp_self.flags |= CI_ISP_DPD_YUV_422; -+ else if (jpg_review->pix_fmt == V4L2_PIX_FMT_NV12) -+ dp_self.flags |= CI_ISP_DPD_YUV_NV12 -+ | CI_ISP_DPD_CSS_V2; -+ else if (jpg_review->pix_fmt == V4L2_PIX_FMT_YUYV) -+ dp_self.flags |= CI_ISP_DPD_YUV_YUYV; -+ -+ dprintk(1, "dp_self.flags is 0x%x", dp_self.flags); -+ } -+ -+ } else if (isp->pixelformat == INTEL_PIX_FMT_RAW08) { -+ -+ dp_main.flags = CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPRAW; -+ config->view_finder.flags |= VFFLAG_USE_MAINPATH; -+ -+ /*just take the output of the sensor without any resizing*/ -+ dp_main.flags |= CI_ISP_DPD_NORESIZE; -+ (void)ci_sensor_res2size(isi_config->res, -+ &(dp_main.out_w), &(dp_main.out_h)); -+ -+ dprintk(1, "RAW08 dp_main.flags is 0x%x", dp_main.flags); -+ -+ } else if (isp->pixelformat == INTEL_PIX_FMT_RAW10 -+ || isp->pixelformat == INTEL_PIX_FMT_RAW12) { -+ -+ dp_main.flags = (CI_ISP_DPD_ENABLE -+ | CI_ISP_DPD_MODE_ISPRAW_16B); -+ config->view_finder.flags |= VFFLAG_USE_MAINPATH; -+ -+ /*just take the output of the sensor without any resizing*/ -+ dp_main.flags |= CI_ISP_DPD_NORESIZE; -+ (void)ci_sensor_res2size(isi_config->res, -+ &(dp_main.out_w), &(dp_main.out_h)); -+ -+ dprintk(1, "RAW10 dp_main.flags is 0x%x", dp_main.flags); -+ -+ } /*else if (isp->bufwidth >= 640 && isp->bufheight >= 480) {*/ -+ else if (isp->bufwidth >= 32 && isp->bufheight >= 16) { -+ -+ dp_main.flags = (CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPYC); -+ dp_main.out_w = (u16) isp->bufwidth; -+ dp_main.out_h = (u16) isp->bufheight; -+ config->view_finder.flags |= VFFLAG_USE_MAINPATH; -+ -+ if (isp->pixelformat == V4L2_PIX_FMT_YUV420 || -+ isp->pixelformat == V4L2_PIX_FMT_YVU420) -+ dp_main.flags |= CI_ISP_DPD_YUV_420 | CI_ISP_DPD_CSS_V2; -+ else if (isp->pixelformat == V4L2_PIX_FMT_YUV422P) -+ dp_main.flags |= CI_ISP_DPD_YUV_422; -+ else if (isp->pixelformat == V4L2_PIX_FMT_NV12) { -+ /* to use crop set crop_flag first */ -+ dp_main.flags |= CI_ISP_DPD_YUV_NV12; -+ if (!crop_flag) -+ dp_main.flags |= CI_ISP_DPD_CSS_V2; -+ } else if (isp->pixelformat == V4L2_PIX_FMT_YUYV) -+ dp_main.flags |= CI_ISP_DPD_YUV_YUYV; -+ -+ dprintk(1, "YUV dp_main.flags is 0x%x", dp_main.flags); -+ -+ } /* else if (isp->bufwidth <= 640 && isp->bufheight <= 480) { -+ -+ dp_self.flags = (CI_ISP_DPD_ENABLE | CI_ISP_DPD_MODE_ISPYC); -+ -+ if (isp->pixelformat == V4L2_PIX_FMT_YUV420 || -+ isp->pixelformat == V4L2_PIX_FMT_YVU420) -+ dp_self.flags |= CI_ISP_DPD_YUV_420 | CI_ISP_DPD_CSS_V2; -+ else if (isp->pixelformat == V4L2_PIX_FMT_YUV422P) -+ dp_self.flags |= CI_ISP_DPD_YUV_422; -+ else if (isp->pixelformat == V4L2_PIX_FMT_NV12) -+ dp_self.flags |= CI_ISP_DPD_YUV_NV12 -+ | CI_ISP_DPD_CSS_V2; -+ else if (isp->pixelformat == V4L2_PIX_FMT_YUYV) -+ dp_self.flags |= CI_ISP_DPD_YUV_YUYV; -+ else if (isp->pixelformat == V4L2_PIX_FMT_RGB565) -+ dp_self.flags |= CI_ISP_DPD_HWRGB_565; -+ else if (isp->pixelformat == V4L2_PIX_FMT_BGR32) -+ dp_self.flags |= CI_ISP_DPD_HWRGB_888; -+ -+ dprintk(1, "YUV dp_self.flags is 0x%x", dp_self.flags); -+ } -+ */ -+ -+ dprintk(1, "sensor_res = %x", isi_config->res); -+ -+ (void)ci_sensor_res2size(isi_config->res, &isi_hsize, &isi_vsize); -+ dprintk(1, "self path: w:%d, h:%d; sensor: w:%d, h:%d", -+ self_rect.w, self_rect.h, isi_hsize, isi_vsize); -+ dprintk(1, "main path: out_w:%d, out_h:%d ", -+ dp_main.out_w, dp_main.out_h); -+ -+ /* no stretching/squeezing */ -+ if (dp_self.flags && CI_ISP_DPD_ENABLE) -+ dp_self.flags |= CI_ISP_DPD_KEEPRATIO; -+ else -+ dp_main.flags |= CI_ISP_DPD_KEEPRATIO; -+ -+ /* prepare datapath, 640x480, can changed to the bufsize */ -+ dp_self.out_w = (u16) self_rect.w; -+ dp_self.out_h = (u16) self_rect.h; -+ -+ if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_HWRGB) { -+ /* YCbCr to RGB conversion in hardware */ -+ if (isp->pixelformat == V4L2_PIX_FMT_RGB565) -+ dp_self.flags |= CI_ISP_DPD_HWRGB_565; -+ if (isp->pixelformat == V4L2_PIX_FMT_BGR32) -+ dp_self.flags |= CI_ISP_DPD_HWRGB_888; -+ } -+ -+ if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_MIRROR) -+ dp_self.flags |= CI_ISP_DPD_H_FLIP; -+ -+ -+ if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_V_FLIP) -+ dp_self.flags |= CI_ISP_DPD_V_FLIP; -+ -+ -+ if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_ROT90_CCW) -+ dp_self.flags |= CI_ISP_DPD_90DEG_CCW; -+ -+ /* setup self & main path with zoom */ -+ if (zoom < 0) -+ zoom = sys_conf->isp_cfg.view_finder.zoom; -+ -+ if (sys_conf->isp_cfg.view_finder.flags & VFFLAG_USE_MAINPATH) { -+ /* For RAW snapshots, we have to bypass the ISP too */ -+ dp_mode = dp_main.flags & CI_ISP_DPD_MODE_MASK; -+ if ((dp_mode == CI_ISP_DPD_MODE_ISPRAW) || -+ (dp_mode == CI_ISP_DPD_MODE_ISPRAW_16B)) { -+ struct ci_sensor_config isi_conf; -+ /* isi_conf = *sys_conf->isi_config; */ -+ isi_conf = *isi_config; -+ isi_conf.mode = SENSOR_MODE_PICT; -+ error = ci_isp_set_input_aquisition(&isi_conf); -+ if (error != CI_STATUS_SUCCESS) -+ eprintk("33"); -+ } -+ } -+ /* to use crop mode, set crop_flag */ -+ if (crop_flag) -+ dp_main.flags |= CI_ISP_DPD_NORESIZE; -+ -+ error = ci_datapath_isp(sys_conf, isi_config, &dp_main, &dp_self, zoom); -+ if (error != CI_STATUS_SUCCESS) { -+ printk(KERN_ERR "mrstisp: failed to setup marvins datapath\n"); -+ return error; -+ } -+ -+ DBG_leaving; -+ return error; -+} -+ -+static int mrst_isp_init_mrv_image_effects(struct ci_pl_system_config *sys_conf, -+ int enable) -+{ -+ int res; -+ -+ DBG_entering; -+ -+ if (enable && sys_conf->isp_cfg.img_eff_cfg.mode -+ != CI_ISP_IE_MODE_OFF) { -+ res = ci_isp_ie_set_config(&(sys_conf->isp_cfg.img_eff_cfg)); -+ if (res != CI_STATUS_SUCCESS) -+ printk(KERN_ERR "mrstisp: error setting ie config\n"); -+ } else { -+ (void)ci_isp_ie_set_config(NULL); -+ res = CI_STATUS_SUCCESS; -+ } -+ -+ DBG_leaving; -+ return res; -+} -+ -+static int mrst_isp_init_mrvisp_lensshade(struct ci_pl_system_config *sys_conf, -+ int enable) -+{ -+ if (enable) { -+ ci_isp_set_ls_correction(&sys_conf->isp_cfg.lsc_cfg); -+ ci_isp_ls_correction_on_off(1); -+ } else { -+ ci_isp_ls_correction_on_off(0); -+ } -+ return CI_STATUS_SUCCESS; -+} -+ -+static int mrst_isp_init_mrvisp_badpixel(const struct ci_pl_system_config -+ *sys_conf, int enable) -+{ -+ if ((enable) && (sys_conf->isp_cfg.flags.bpc)) { -+ (void)ci_bp_init(&sys_conf->isp_cfg.bpc_cfg, -+ &sys_conf->isp_cfg.bpd_cfg); -+ } else { -+ (void)ci_bp_end(&sys_conf->isp_cfg.bpc_cfg); -+ (void)ci_isp_set_bp_correction(NULL); -+ (void)ci_isp_set_bp_detection(NULL); -+ } -+ return CI_STATUS_SUCCESS; -+} -+ -+static int mrst_isp_init_mrv_ispfilter(const struct ci_pl_system_config -+ *sys_conf, int enable) -+{ -+ int res; -+ -+ DBG_entering; -+ -+ if ((enable) && (sys_conf->isp_cfg.flags.isp_filters)) { -+ ci_isp_activate_filter(true); -+ res = ci_isp_set_filter_params(sys_conf->isp_cfg. -+ filter_level_noise_reduc, -+ sys_conf->isp_cfg. -+ filter_level_sharp); -+ if (res != CI_STATUS_SUCCESS) -+ printk(KERN_ERR "mrstisp: error set filter param\n"); -+ } else { -+ ci_isp_activate_filter(false); -+ res = CI_STATUS_SUCCESS; -+ } -+ -+ DBG_leaving; -+ return res; -+} -+ -+static int mrst_isp_init_mrvisp_cac(const struct ci_pl_system_config *sys_conf, -+ int enable) -+{ -+ return 0; -+} -+ -+static int mrst_isp_initbls(const struct ci_pl_system_config *sys_conf) -+{ -+ struct ci_isp_bls_config *bls_config = -+ (struct ci_isp_bls_config *)&sys_conf->isp_cfg.bls_cfg; -+ return ci_isp_bls_set_config(bls_config); -+} -+ -+static int mrst_isp_dp_init(struct ci_pl_system_config *sys_conf, -+ struct ci_sensor_config *isi_config) -+{ -+ int error; -+ u8 words_per_pixel; -+ -+ DBG_entering; -+ -+ /* base initialisation of Marvin */ -+ ci_isp_init(); -+ -+ /* setup input acquisition according to image sensor settings */ -+ print_snr_cfg(isi_config); -+ error = ci_isp_set_input_aquisition(isi_config); -+ if (error) { -+ printk(KERN_ERR "mrstisp: error setting input acquisition\n"); -+ return error; -+ } -+ -+ /* setup functional blocks for Bayer pattern processing */ -+ if (ci_isp_select_path(isi_config, &words_per_pixel) -+ == CI_ISP_PATH_BAYER) { -+ -+ /* black level */ -+ if (sys_conf->isp_cfg.flags.bls) { -+ error = mrst_isp_initbls(sys_conf); -+ if (error != CI_STATUS_SUCCESS) { -+ printk(KERN_ERR "mrstisp: error set bls\n"); -+ return error; -+ } -+ } else { -+ ci_isp_bls_set_config(NULL); -+ } -+ -+ /* gamma */ -+ if (sys_conf->isp_cfg.flags.gamma2) { -+ dprintk(1, "setting gamma 2 "); -+ ci_isp_set_gamma2(&g45_th20_b5); -+ } else { -+ dprintk(1, "no setting gamma 2 "); -+ ci_isp_set_gamma2(NULL); -+ } -+ -+ /* demosaic */ -+ ci_isp_set_demosaic(sys_conf->isp_cfg.demosaic_mode, -+ sys_conf->isp_cfg.demosaic_th); -+ -+ /* color convertion */ -+ if (sys_conf->isp_cfg.flags.cconv) { -+ if (!sys_conf->isp_cfg.flags.cconv_basic) { -+ mrst_isp_set_color_conversion_ex(); -+ /* set color converstion skipped by xiaolin, -+ * to be done in libci */ -+ if (error != CI_STATUS_SUCCESS) { -+ printk(KERN_ERR "mrstisp: error set" -+ " color conversion\n"); -+ return error; -+ } -+ } -+ } -+ -+ /* af setting */ -+ if (sys_conf->isp_cfg.flags.af) -+ ci_isp_set_auto_focus(&sys_conf->isp_cfg.af_cfg); -+ else -+ ci_isp_set_auto_focus(NULL); -+ -+ /* filter */ -+ mrst_isp_init_mrv_ispfilter(sys_conf, true); -+ -+ /* cac */ -+ mrst_isp_init_mrvisp_cac(sys_conf, true); -+ } -+ -+ /* -+ * disable color processing for now (will be set under user control -+ * in the main loop) -+ */ -+ ci_isp_col_set_color_processing(NULL); -+ -+ /* configure image effects */ -+ mrst_isp_init_mrv_image_effects(sys_conf, true); -+ -+ /* configure lens shading correction */ -+ if (strcmp(isi_config->name, "s5k4e1") == 0 -+ && (isi_config->res == SENSOR_RES_720P -+ || isi_config->res == SENSOR_RES_QXGA_PLUS)) { -+ dprintk(1, "enabling lsc for kmot 720p and qsxga\n"); -+ mrst_isp_init_mrvisp_lensshade(sys_conf, true); -+ } else -+ mrst_isp_init_mrvisp_lensshade(sys_conf, -+ sys_conf->isp_cfg.flags.lsc); -+ -+ /* configure bad pixel detection/correction */ -+ mrst_isp_init_mrvisp_badpixel(sys_conf, true); -+ -+ DBG_leaving; -+ return CI_STATUS_SUCCESS; -+} -+ -+int ci_jpe_encode(struct mrst_isp_device *intel, -+ enum ci_isp_conf_update_time update_time, -+ enum ci_isp_jpe_enc_mode mrv_jpe_encMode) -+{ -+ u32 mipi_data_id = 1; -+ struct isp_register *mrv_reg = -+ (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ ci_isp_jpe_prep_enc(mrv_jpe_encMode); -+ -+ if (to_sensor_config(intel->sensor_curr)->mipi_mode) { -+ ci_isp_start(1, update_time); -+ v4l2_subdev_call(intel->sensor_curr, video, s_stream, 1); -+ if (mipi_flag) -+ while (mipi_data_id) -+ mipi_data_id = -+ REG_READ_EX(mrv_reg->mipi_cur_data_id); -+ mipi_flag = 0; -+ -+ } else -+ ci_isp_start(1, update_time); -+ -+ return ci_isp_jpe_wait_for_encode_done(intel); -+} -+ -+/* capture one frame */ -+u32 ci_jpe_capture(struct mrst_isp_device *isp, -+ enum ci_isp_conf_update_time update_time) -+{ -+ int retval = CI_STATUS_SUCCESS; -+ -+ /* generate header */ -+ retval = ci_isp_jpe_generate_header(isp, MRV_JPE_HEADER_MODE_JFIF); -+ if (retval != CI_STATUS_SUCCESS) -+ return 0; -+ -+ /* now encode JPEG */ -+ retval = ci_jpe_encode(isp, update_time, CI_ISP_JPE_SINGLE_SHOT); -+ if (retval != CI_STATUS_SUCCESS) -+ return 0; -+ -+ /* return ci_isp_mif_get_byte_cnt(); */ -+ return 0; -+} -+ -+static int mrst_ci_capture(struct mrst_isp_device *isp) -+{ -+ u32 bufbase; -+ u32 mipi_data_id = 1; -+ struct videobuf_buffer *vb; -+ struct isp_register *mrv_reg = -+ (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ bufbase = videobuf_to_dma_contig(isp->active); -+ mrst_isp_update_marvinvfaddr(isp, bufbase, CI_ISP_CFG_UPDATE_IMMEDIATE); -+ ci_isp_mif_reset_offsets(CI_ISP_CFG_UPDATE_IMMEDIATE); -+ -+ ci_isp_reset_interrupt_status(); -+ mrst_isp_enable_interrupt(isp); -+ -+ if (isp->pixelformat == V4L2_PIX_FMT_JPEG) { -+ mrst_isp_disable_interrupt(isp); -+ ci_isp_jpe_init_ex(isp->bufwidth, isp->bufheight, -+ isp->sys_conf.isp_cfg.jpeg_enc_ratio, -+ true); -+ ci_jpe_capture(isp, CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ -+ vb = isp->active; -+ vb->size = ci_isp_mif_get_byte_cnt(); -+ vb->state = VIDEOBUF_DONE; -+ do_gettimeofday(&vb->ts); -+ vb->field_count++; -+ wake_up(&vb->done); -+ isp->active = NULL; -+ -+ dprintk(2, "countcount = %lx", vb->size); -+ } else if (isp->pixelformat == INTEL_PIX_FMT_RAW08 -+ || isp->pixelformat == INTEL_PIX_FMT_RAW10 -+ || isp->pixelformat == INTEL_PIX_FMT_RAW12) { -+ mrst_isp_disable_interrupt(isp); -+ ci_isp_start(1, CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ ci_isp_wait_for_frame_end(isp); -+ -+ /* update captured frame status */ -+ vb = isp->active; -+ /* vb->size = ci_isp_mif_get_byte_cnt(); */ -+ vb->state = VIDEOBUF_DONE; -+ do_gettimeofday(&vb->ts); -+ vb->field_count++; -+ wake_up(&vb->done); -+ isp->active = NULL; -+ /* ci_isp_reg_dump_all(); */ -+ dprintk(3, "captured index = %d", vb->i); -+ } else if (to_sensor_config(isp->sensor_curr)->mipi_mode) { -+ ci_isp_start(0, CI_ISP_CFG_UPDATE_IMMEDIATE); -+ -+ if (mipi_flag) { -+ v4l2_subdev_call(isp->sensor_curr, video, s_stream, 1); -+ -+ while (mipi_data_id) { -+ mipi_data_id = -+ REG_READ_EX(mrv_reg->mipi_cur_data_id); -+ dprintk(5, "mipi_cur_data_id = %x", -+ mipi_data_id); -+ } -+ mipi_flag = 0; -+ } -+ } else -+ ci_isp_start(0, CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ -+ return 0; -+} -+ -+static int buffer_setup(struct videobuf_queue *vq, unsigned int *count, -+ unsigned int *size) -+{ -+ struct mrst_isp_fh *fh = vq->priv_data; -+ struct mrst_isp_device *isp = fh->dev; -+ -+ u32 w = isp->bufwidth; -+ u32 h = isp->bufheight; -+ u32 depth = isp->depth; -+ u32 fourcc = isp->pixelformat; -+ -+ if (fourcc == V4L2_PIX_FMT_JPEG) { -+ *size = PAGE_ALIGN((isp->mb1_size -+ - 640*480*2)/(*count)) - PAGE_SIZE; -+ /* *size = PAGE_ALIGN(2 * 1024 * 1024); */ -+ } else if (fourcc == INTEL_PIX_FMT_RAW08 -+ || fourcc == INTEL_PIX_FMT_RAW10 -+ || fourcc == INTEL_PIX_FMT_RAW12) { -+ *size = (w * h * depth)/8; -+ } else { -+ *size = (w * h * depth)/8; -+ } -+ -+ isp->frame_size = *size; -+ isp->num_frames = *count; -+ -+ if (0 == *count) -+ *count = 3; -+ -+ while (*size * *count > isp->mb1_size) -+ (*count)--; -+ -+ dprintk(1, "count=%d, size=%d", *count, *size); -+ return 0; -+} -+ -+static void free_buffer(struct videobuf_queue *vq, struct mrst_isp_buffer *buf) -+{ -+ struct videobuf_buffer *vb = &buf->vb; -+ -+ dprintk(1, "(vb=0x%p) baddr = 0x%08lx bsize = %d", vb, -+ vb->baddr, vb->bsize); -+ -+ videobuf_dma_contig_free(vq, vb); -+ -+ buf->vb.state = VIDEOBUF_NEEDS_INIT; -+ dprintk(1, "free_buffer: freed"); -+} -+ -+static int buffer_prepare(struct videobuf_queue *vq, -+ struct videobuf_buffer *vb, enum v4l2_field field) -+{ -+ struct mrst_isp_fh *fh = vq->priv_data; -+ struct mrst_isp_device *isp = fh->dev; -+ struct mrst_isp_buffer *buf = container_of(vb, struct mrst_isp_buffer, -+ vb); -+ int ret; -+ -+ if (vb->width != isp->bufwidth || vb->height != isp->bufheight -+ || vb->field != field) { -+ /* buf->fmt = isp->pixelformat; */ -+ vb->width = isp->bufwidth; -+ vb->height = isp->bufheight; -+ vb->field = field; -+ vb->state = VIDEOBUF_NEEDS_INIT; -+ } -+ -+ vb->size = isp->frame_size; -+ -+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { -+ ret = videobuf_iolock(vq, vb, NULL); -+ if (ret) -+ goto fail; -+ vb->state = VIDEOBUF_PREPARED; -+ } -+ -+ return 0; -+ -+fail: -+ printk(KERN_ERR "mrstisp: error calling videobuf_iolock"); -+ free_buffer(vq, buf); -+ return ret; -+} -+ -+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -+{ -+ struct mrst_isp_fh *fh = vq->priv_data; -+ struct mrst_isp_device *isp = fh->dev; -+ u32 bufbase; -+ -+ vb->state = VIDEOBUF_QUEUED; -+ dprintk(1, "buffer %d in buffer querue", vb->i); -+ if (isp->stopflag) { -+ list_add_tail(&vb->queue, &isp->capture); -+ if (isp->active) { -+ /* dprintk(1, "AAAAAAAAAA in flag condition"); */ -+ /* isp->active->state = VIDEOBUF_ACTIVE; */ -+ /* mrst_isp_to_do_mblk_line = 1; */ -+ bufbase = videobuf_to_dma_contig(vb); -+ mrst_isp_update_marvinvfaddr(isp, bufbase, 0); -+ /* mrst_isp_enable_interrupt(isp); */ -+ } else { -+ isp->active = vb; -+ mrst_isp_enable_interrupt(isp); -+ /* -+ dprintk(1, "xxxxxxxxx in flag condition"); -+ isp->active->state = VIDEOBUF_ACTIVE; -+ mrst_isp_to_do_mblk_line = 1; -+ bufbase = videobuf_to_dma_contig(isp->active); -+ mrst_isp_update_marvinvfaddr(isp, bufbase, -+ CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ */ -+ } -+ isp->stopflag = 0; -+ } else if (!isp->active) { -+ dprintk(1, "no active queue"); -+ isp->active = vb; -+ isp->active->state = VIDEOBUF_ACTIVE; -+ mrst_isp_to_do_mblk_line = 1; -+ mrst_ci_capture(isp); -+ } else { -+ dprintk(1, "capture to active queue"); -+ list_add_tail(&vb->queue, &isp->capture); -+ } -+ -+ return; -+} -+ -+static void buffer_release(struct videobuf_queue *vq, -+ struct videobuf_buffer *vb) -+{ -+ struct mrst_isp_buffer *buf = container_of(vb, -+ struct mrst_isp_buffer, vb); -+ DBG_entering; -+ free_buffer(vq, buf); -+ DBG_leaving; -+} -+ -+static struct videobuf_queue_ops mrst_isp_videobuf_qops = { -+ .buf_setup = buffer_setup, -+ .buf_prepare = buffer_prepare, -+ .buf_queue = buffer_queue, -+ .buf_release = buffer_release, -+}; -+ -+static int mrst_isp_open(struct file *file) -+{ -+ struct video_device *vdev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(vdev); -+ struct mrst_isp_fh *fh = NULL; -+ struct v4l2_format sensor_format; -+ int ret; -+ -+ DBG_entering; -+ -+ if (!isp) { -+ printk(KERN_ERR "null in mrst_isp_open\n"); -+ return -ENODEV; -+ } -+ -+ dprintk(2, "open = %d", isp->open); -+ mutex_lock(&isp->mutex); -+ if (isp->open == 0) { -+ if (isp->sensor_soc) { -+ dprintk(0, "cur senfor soc"); -+ isp->sensor_curr = isp->sensor_soc; -+ } else { -+ dprintk(0, "cur sensor raw"); -+ isp->sensor_curr = isp->sensor_raw; -+ } -+ } -+ ++isp->open; -+ -+ ret = v4l2_subdev_call(isp->sensor_curr, video, g_fmt, -+ &sensor_format); -+ if (ret) { -+ printk(KERN_ERR "can't get current pix from sensor!\n"); -+ ret = -EINVAL; -+ goto exit_unlock; -+ } -+ -+ dprintk(1, "current sensor format: %d x %d", -+ sensor_format.fmt.pix.width, -+ sensor_format.fmt.pix.height); -+ -+ fh = kzalloc(sizeof(*fh), GFP_KERNEL); -+ if (NULL == fh) { -+ printk(KERN_ERR "no mem for fh \n"); -+ ret = -ENOMEM; -+ goto exit_unlock; -+ } -+ -+ file->private_data = fh; -+ fh->dev = isp; -+ -+ videobuf_queue_dma_contig_init(&fh->vb_q, &mrst_isp_videobuf_qops, -+ vdev->parent, &isp->lock, -+ V4L2_BUF_TYPE_VIDEO_CAPTURE, -+ V4L2_FIELD_NONE, -+ sizeof(struct mrst_isp_buffer), fh); -+ -+exit_unlock: -+ mutex_unlock(&isp->mutex); -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_close(struct file *file) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ struct mrst_isp_fh *fh = file->private_data; -+ unsigned long flags; -+ -+ DBG_entering; -+ mutex_lock(&isp->mutex); -+ --isp->open; -+ dprintk(2, "close = %d", isp->open); -+ if (isp->open == 0) { -+ if (isp->streaming == 1) { -+ videobuf_streamoff(&fh->vb_q); -+ isp->streaming = 0; -+ isp->buffer_required = 0; -+ isp->stopflag = 0; -+ -+ spin_lock_irqsave(&isp->lock, flags); -+ INIT_LIST_HEAD(&isp->capture); -+ isp->active = NULL; -+ isp->next = NULL; -+ isp->sys_conf.isp_hal_enable = 0; -+ isp->sys_conf.jpg_review_enable = 0; -+ spin_unlock_irqrestore(&isp->lock, flags); -+ -+ ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ v4l2_subdev_call(isp->sensor_curr, video, s_stream, 0); -+ isp->sensor_curr = NULL; -+ } -+ if (isp->sensor_soc) -+ v4l2_subdev_call(isp->sensor_soc, core, s_gpio, 1); -+ if (isp->sensor_raw) -+ v4l2_subdev_call(isp->sensor_raw, core, s_gpio, 1); -+ } -+ -+ kfree(file->private_data); -+ -+ mutex_unlock(&isp->mutex); -+ -+ /*XXX zheng*/ -+ if (isp->open == 0) -+ frame_cnt = 0; -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static ssize_t mrst_isp_read(struct file *file, char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ return 0; -+} -+ -+static void mrst_isp_videobuf_vm_open(struct vm_area_struct *vma) -+{ -+ struct videobuf_mapping *map = vma->vm_private_data; -+ -+ dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", -+ map, map->count, vma->vm_start, vma->vm_end); -+ -+ map->count++; -+} -+ -+static void mrst_isp_videobuf_vm_close(struct vm_area_struct *vma) -+{ -+ struct videobuf_mapping *map = vma->vm_private_data; -+ struct videobuf_queue *q = map->q; -+ int i; -+ -+ dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", -+ map, map->count, vma->vm_start, vma->vm_end); -+ -+ map->count--; -+ if (0 == map->count) { -+ struct videobuf_dma_contig_memory *mem; -+ -+ dprintk(2, "munmap %p q=%p\n", map, q); -+ mutex_lock(&q->vb_lock); -+ -+ /* We need first to cancel streams, before unmapping */ -+ if (q->streaming) -+ videobuf_queue_cancel(q); -+ -+ for (i = 0; i < VIDEO_MAX_FRAME; i++) { -+ if (NULL == q->bufs[i]) -+ continue; -+ -+ if (q->bufs[i]->map != map) -+ continue; -+ -+ mem = q->bufs[i]->priv; -+ if (mem) { -+ /* This callback is called only if kernel has -+ allocated memory and this memory is mmapped. -+ In this case, memory should be freed, -+ in order to do memory unmap. -+ */ -+ -+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); -+ -+ /* vfree is not atomic - can't be -+ called with IRQ's disabled -+ */ -+ dprintk(2, "buf[%d] freeing %p\n", -+ i, mem->vaddr); -+ -+ /* -+ dma_free_coherent(q->dev, mem->size, -+ mem->vaddr, mem->dma_handle); -+ */ -+ mem->vaddr = NULL; -+ } -+ -+ q->bufs[i]->map = NULL; -+ q->bufs[i]->baddr = 0; -+ } -+ -+ kfree(map); -+ -+ mutex_unlock(&q->vb_lock); -+ } -+} -+ -+static struct vm_operations_struct mrst_isp_videobuf_vm_ops = { -+ .open = mrst_isp_videobuf_vm_open, -+ .close = mrst_isp_videobuf_vm_close, -+}; -+ -+static int mrst_isp_mmap_mapper(struct videobuf_queue *q, -+ struct vm_area_struct *vma) -+{ -+ struct videobuf_dma_contig_memory *mem; -+ struct videobuf_mapping *map; -+ unsigned int first; -+ int retval; -+ unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT; -+ -+ struct mrst_isp_fh *fh = q->priv_data; -+ struct mrst_isp_device *isp = fh->dev; -+ -+ DBG_entering; -+ -+ if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) -+ return -EINVAL; -+ -+ /* look for first buffer to map */ -+ for (first = 0; first < VIDEO_MAX_FRAME; first++) { -+ if (!q->bufs[first]) -+ continue; -+ -+ if (V4L2_MEMORY_MMAP != q->bufs[first]->memory) -+ continue; -+ if (q->bufs[first]->boff == offset) { -+ dprintk(1, "buff id %d is mapped", first); -+ break; -+ } -+ } -+ if (VIDEO_MAX_FRAME == first) { -+ eprintk("invalid user space offset [offset=0x%lx]", offset); -+ return -EINVAL; -+ } -+ -+ /* create mapping + update buffer list */ -+ map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); -+ if (!map) -+ return -ENOMEM; -+ -+ q->bufs[first]->map = map; -+ map->start = vma->vm_start; -+ map->end = vma->vm_end; -+ map->q = q; -+ -+ q->bufs[first]->baddr = vma->vm_start; -+ -+ mem = q->bufs[first]->priv; -+ BUG_ON(!mem); -+ MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); -+ -+ mem->size = PAGE_ALIGN(q->bufs[first]->bsize); -+ mem->dma_handle = isp->mb1 + (mem->size * first); -+ mem->vaddr = (void *)0x1; -+ /* -+ mem->vaddr = dma_alloc_coherent(q->dev, mem->size, -+ &mem->dma_handle, GFP_KERNEL); -+ */ -+ if (mem->size > isp->mb1_size) { -+ eprintk("to big size, can not be mmapped"); -+ return -EINVAL; -+ } -+ -+ /* Try to remap memory */ -+ -+ size = vma->vm_end - vma->vm_start; -+ size = (size < mem->size) ? size : mem->size; -+ -+ dprintk(1, "vm_end - vm_start = %ld, mem-size = %ld", size, mem->size); -+ -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ retval = remap_pfn_range(vma, vma->vm_start, -+ mem->dma_handle >> PAGE_SHIFT, -+ size, vma->vm_page_prot); -+ if (retval) { -+ eprintk("mmap: remap failed with error %d. ", retval); -+ goto error; -+ } -+ -+ vma->vm_ops = &mrst_isp_videobuf_vm_ops; -+ vma->vm_flags |= VM_DONTEXPAND; -+ vma->vm_private_data = map; -+ -+ dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", -+ map, q, vma->vm_start, vma->vm_end, -+ (long int) q->bufs[first]->bsize, -+ vma->vm_pgoff, first); -+ -+ mrst_isp_videobuf_vm_open(vma); -+ -+ return 0; -+ -+error: -+ kfree(map); -+ return -ENOMEM; -+} -+int mrst_isp_videobuf_mmap_mapper(struct videobuf_queue *q, -+ struct vm_area_struct *vma) -+{ -+ MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); -+ -+ mutex_lock(&q->vb_lock); -+ mrst_isp_mmap_mapper(q, vma); -+ /* retval = CALL(q, mmap_mapper, q, vma); */ -+ q->is_mmapped = 1; -+ mutex_unlock(&q->vb_lock); -+ -+ return 0; -+} -+static int mrst_isp_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int ret; -+ int map_by_myself; -+ struct mrst_isp_fh *fh; -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; -+ unsigned long size = vma->vm_end-vma->vm_start; -+ unsigned long page; -+ -+ DBG_entering; -+ -+ /* temporarily put here */ -+ if (isp->open > 1) { -+ printk(KERN_ERR "ISP already opened..."); -+ return -EINVAL; -+ } -+ -+ fh = file->private_data; -+ -+ if (!(vma->vm_flags & (VM_WRITE | VM_READ)) -+ || !(vma->vm_flags & VM_SHARED)) { -+ printk(KERN_ERR "mrstisp: wrong vma flag"); -+ return -EINVAL; -+ } -+ -+ /* to check whether if it is ISP bar 0 map */ -+ if (offset == isp->mb0_size + isp->mb1_size) { -+ dprintk(1, "---- map bar0 ----"); -+ page = isp->mb0; -+ map_by_myself = 1; -+ } else if (offset == 0 && size == isp->mb1_size) { -+ dprintk(1, "---- map bar1 ----"); -+ page = isp->mb1; -+ map_by_myself = 1; -+ } else if (isp->pixelformat == V4L2_PIX_FMT_JPEG -+ && isp->sys_conf.jpg_review_enable == 1 -+ && offset == isp->sys_conf.jpg_review.offset) { -+ dprintk(1, "---- map jpeg review buffer----"); -+ page = isp->mb1 + isp->sys_conf.jpg_review.offset; -+ map_by_myself = 1; -+ } else { -+ dprintk(1, "----map one certain buffer----"); -+ map_by_myself = 0; -+ } -+ -+ if (map_by_myself) { -+ vma->vm_flags |= VM_IO; -+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ -+ -+ page = page >> PAGE_SHIFT; -+ -+ if (remap_pfn_range(vma, vma->vm_start, page, size, -+ PAGE_SHARED)) { -+ printk(KERN_ERR "fail to put MMAP buffer to user space\n"); -+ return -EAGAIN; -+ } -+ -+ return 0; -+ } -+ -+ if (size > isp->num_frames * PAGE_ALIGN(isp->frame_size)) { -+ eprintk("length is larger than num * size"); -+ return -EINVAL; -+ } -+ -+ ret = mrst_isp_videobuf_mmap_mapper(&fh->vb_q, vma); -+ -+ dprintk(1, "vma start=0x%08lx, size=%ld, offset=%ld ret=%d", -+ (unsigned long)vma->vm_start, -+ (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, -+ (unsigned long)offset, ret); -+ -+ return ret; -+} -+ -+static int mrst_isp_g_fmt_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ int ret; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ f->fmt.pix.width = isp->bufwidth; -+ f->fmt.pix.height = isp->bufheight; -+ f->fmt.pix.pixelformat = isp->pixelformat; -+ f->fmt.pix.bytesperline = (f->fmt.pix.width * isp->depth) >> 3; -+ f->fmt.pix.sizeimage = f->fmt.pix.height -+ * f->fmt.pix.bytesperline; -+ ret = 0; -+ } else { -+ ret = -EINVAL; -+ } -+ -+ dprintk(1, "get fmt %d x %d ", f->fmt.pix.width, f->fmt.pix.height); -+ DBG_leaving; -+ return ret; -+} -+ -+static struct intel_fmt *fmt_by_fourcc(unsigned int fourcc) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < NUM_FORMATS; i++) -+ if (fmts[i].fourcc == fourcc) -+ return fmts+i; -+ return NULL; -+} -+ -+static int mrst_isp_try_fmt_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ struct intel_fmt *fmt; -+ int w, h; -+ int ret; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ mutex_lock(&isp->mutex); -+ -+ fmt = fmt_by_fourcc(f->fmt.pix.pixelformat); -+ if (NULL == fmt && f->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) { -+ printk(KERN_ERR "mrstisp: fmt not found\n"); -+ ret = -EINVAL; -+ goto exit_unlock; -+ } -+ -+ w = f->fmt.pix.width; -+ h = f->fmt.pix.height; -+ -+ dprintk(1, "sensor name %s: before w = %d, h = %d", -+ isp->sensor_curr->name, w, h); -+ -+ ret = v4l2_subdev_call(isp->sensor_curr, video, try_fmt, f); -+ if (ret) -+ goto exit_unlock; -+ -+ -+ w = f->fmt.pix.width; -+ h = f->fmt.pix.height; -+ -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 || -+ f->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) { -+ if (w < INTEL_MIN_WIDTH) -+ w = INTEL_MIN_WIDTH; -+ if (w > INTEL_MAX_WIDTH) -+ w = INTEL_MAX_WIDTH; -+ if (h < INTEL_MIN_HEIGHT) -+ h = INTEL_MIN_HEIGHT; -+ if (h > INTEL_MAX_HEIGHT) -+ h = INTEL_MAX_HEIGHT; -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; -+ } else { -+ if (w < INTEL_MIN_WIDTH) -+ w = INTEL_MIN_WIDTH; -+ if (w > INTEL_MAX_WIDTH_MP) -+ w = INTEL_MAX_WIDTH_MP; -+ if (h < INTEL_MIN_HEIGHT) -+ h = INTEL_MIN_HEIGHT; -+ if (h > INTEL_MAX_HEIGHT_MP) -+ h = INTEL_MAX_HEIGHT_MP; -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; -+ } -+ -+ f->fmt.pix.width = w; -+ f->fmt.pix.height = h; -+ -+ f->fmt.pix.field = V4L2_FIELD_NONE; -+ f->fmt.pix.bytesperline = (w * h)/8; -+ if (fmt) -+ f->fmt.pix.sizeimage = (w * h * fmt->depth)/8; -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; -+ f->fmt.pix.priv = 0; -+ -+ dprintk(3, "after w = %d, h = %d", w, h); -+ ret = 0; -+ -+exit_unlock: -+ mutex_unlock(&isp->mutex); -+ -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_s_fmt_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ struct intel_fmt *fmt; -+ int ret; -+ unsigned int width_o, height_o; -+ unsigned short width_sensor, height_sensor; -+ unsigned int w, h; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ mipi_flag = 1; -+ -+ w = f->fmt.pix.width; -+ h = f->fmt.pix.height; -+ -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 || -+ f->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) { -+ if (w < INTEL_MIN_WIDTH) -+ w = INTEL_MIN_WIDTH; -+ if (w > INTEL_MAX_WIDTH) -+ w = INTEL_MAX_WIDTH; -+ if (h < INTEL_MIN_HEIGHT) -+ h = INTEL_MIN_HEIGHT; -+ if (h > INTEL_MAX_HEIGHT) -+ h = INTEL_MAX_HEIGHT; -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; -+ } else { -+ if (w < INTEL_MIN_WIDTH) -+ w = INTEL_MIN_WIDTH; -+ if (w > INTEL_MAX_WIDTH_MP) -+ w = INTEL_MAX_WIDTH_MP; -+ if (h < INTEL_MIN_HEIGHT) -+ h = INTEL_MIN_HEIGHT; -+ if (h > INTEL_MAX_HEIGHT_MP) -+ h = INTEL_MAX_HEIGHT_MP; -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; -+ } -+ -+ f->fmt.pix.width = w; -+ f->fmt.pix.height = h; -+ -+ width_o = f->fmt.pix.width; -+ height_o = f->fmt.pix.height; -+ -+ (void)ci_sensor_res2size(to_sensor_config(isp->sensor_curr)->res, -+ &width_sensor, &height_sensor); -+ -+ ret = mrst_isp_try_fmt_cap(file, priv, f); -+ if (0 != ret) { -+ printk(KERN_ERR "mrstisp: set format failed\n"); -+ return ret; -+ } -+ -+ /* set fmt for only sensor */ -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_MPEG) { -+ ret = v4l2_subdev_call(isp->sensor_curr, video, s_fmt, f); -+ dprintk(1, "------------set fmt only for sensor (%d x %d)", -+ f->fmt.pix.width, f->fmt.pix.height); -+ return ret; -+ } -+ -+ if (isp->sys_conf.isp_hal_enable) { -+ /* set fmt for isp */ -+ mutex_lock(&isp->mutex); -+ fmt = fmt_by_fourcc(f->fmt.pix.pixelformat); -+ -+ isp->pixelformat = fmt->fourcc; -+ isp->depth = fmt->depth; -+ -+ dprintk(1, "sensor (%d x %d)", width_sensor, height_sensor); -+ if (width_o < f->fmt.pix.width && -+ height_o < f->fmt.pix.height) { -+ isp->bufwidth = width_o; -+ isp->bufheight = height_o; -+ } else if (width_sensor < f->fmt.pix.width && -+ height_sensor < f->fmt.pix.height) { -+ isp->bufwidth = width_sensor; -+ isp->bufheight = height_sensor; -+ f->fmt.pix.width = width_sensor; -+ f->fmt.pix.height = height_sensor; -+ } else { -+ isp->bufwidth = f->fmt.pix.width; -+ isp->bufheight = f->fmt.pix.height; -+ } -+ -+ /* FIXME -+ * check if buf res is larger than -+ * sensor real res(1304x980) -+ * if yes, down buf res to VGA -+ */ -+ if (to_sensor_config(isp->sensor_curr)->res == -+ SENSOR_RES_VGA_PLUS) -+ if (isp->bufwidth >= VGA_SIZE_H && -+ isp->bufheight >= VGA_SIZE_V) { -+ isp->bufwidth = VGA_SIZE_H; -+ isp->bufheight = VGA_SIZE_V; -+ } -+ -+ mutex_unlock(&isp->mutex); -+ -+ dprintk(1, "----------set fmt only to isp: w %d, h%d, " -+ "fourcc: %lx", isp->bufwidth, -+ isp->bufheight, fmt->fourcc); -+ } else { -+ -+ /* set fmt for both isp and sensor */ -+ mutex_lock(&isp->mutex); -+ fmt = fmt_by_fourcc(f->fmt.pix.pixelformat); -+ -+ isp->pixelformat = fmt->fourcc; -+ isp->depth = fmt->depth; -+ isp->bufwidth = width_o; -+ isp->bufheight = height_o; -+ -+ mutex_unlock(&isp->mutex); -+ -+ dprintk(1, "--------set fmt for isp : w%d, h%d, fourcc: %lx", -+ isp->bufwidth, isp->bufheight, fmt->fourcc); -+ dprintk(1, "--------set fmt for sesnro : w%d, h%d, fourcc: %lx", -+ f->fmt.pix.width, f->fmt.pix.height, fmt->fourcc); -+ -+ ret = v4l2_subdev_call(isp->sensor_curr, video, s_fmt, f); -+ } -+ -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_enum_framesizes(struct file *file, void *priv, -+ struct v4l2_frmsizeenum *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ int ret; -+ -+ DBG_entering; -+ -+ WARN_ON(priv != file->private_data); -+ -+ ret = v4l2_subdev_call(isp->sensor_curr, video, enum_framesizes, arg); -+ -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_enum_frameintervals(struct file *file, void *priv, -+ struct v4l2_frmivalenum *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ int ret; -+ -+ DBG_entering; -+ -+ WARN_ON(priv != file->private_data); -+ -+ ret = v4l2_subdev_call(isp->sensor_curr, video, enum_frameintervals, -+ arg); -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_queryctrl(struct file *file, void *priv, -+ struct v4l2_queryctrl *c) -+{ -+ struct video_device *vdev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(vdev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ if (!v4l2_subdev_call(isp->sensor_curr, core, queryctrl, c)) -+ return 0; -+ else if (!v4l2_subdev_call(isp->motor, core, queryctrl, c)) -+ return 0; -+ -+ /* No controls supported */ -+ return -EINVAL; -+} -+ -+static int mrst_isp_g_ctrl(struct file *file, void *priv, -+ struct v4l2_control *c) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ int ret; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ if (c->id == V4L2_CID_FOCUS_ABSOLUTE) { -+ ret = v4l2_subdev_call(isp->motor, core, g_ctrl, c); -+ dprintk(2, "get focus from motor : %d", c->value); -+ return ret; -+ } else { -+ ret = v4l2_subdev_call(isp->sensor_curr, core, g_ctrl, c); -+ dprintk(2, "get other cotrol from senrsor : %d", c->value); -+ return ret; -+ } -+} -+ -+static int mrst_isp_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ DBG_entering; -+ -+ if (c->id == V4L2_CID_FOCUS_ABSOLUTE) { -+ dprintk(2, "setting focus %d to motor", c->value); -+ return v4l2_subdev_call(isp->motor, core, s_ctrl, c); -+ } else { -+ dprintk(2, "setting other ctrls, value = %d", c->value); -+ return v4l2_subdev_call(isp->sensor_curr, core, s_ctrl, c); -+ } -+} -+ -+static int mrst_isp_index_to_camera(struct mrst_isp_device *isp, u32 index) -+{ -+ int camera = MRST_CAMERA_NONE; -+ -+ if (isp->sensor_soc && isp->sensor_raw) { -+ switch (index) { -+ case 0: -+ camera = isp->sensor_soc_index; -+ break; -+ case 1: -+ camera = isp->sensor_raw_index; -+ break; -+ } -+ } else if (isp->sensor_soc) { -+ switch (index) { -+ case 0: -+ camera = isp->sensor_soc_index; -+ break; -+ } -+ } else if (isp->sensor_raw) { -+ switch (index) { -+ case 0: -+ camera = isp->sensor_raw_index; -+ break; -+ } -+ } -+ -+ return camera; -+} -+ -+static int mrst_isp_enum_input(struct file *file, void *priv, -+ struct v4l2_input *i) -+{ -+ struct video_device *vdev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(vdev); -+ int camera; -+ -+ DBG_entering; -+ -+ WARN_ON(priv != file->private_data); -+ -+ camera = mrst_isp_index_to_camera(isp, i->index); -+ if (MRST_CAMERA_NONE == camera) -+ return -EINVAL; -+ -+ i->type = V4L2_INPUT_TYPE_CAMERA; -+ i->std = V4L2_STD_UNKNOWN; -+ strcpy(i->name, mrst_camera_table[camera].name); -+ -+ DBG_leaving; -+ return 0; -+} -+static int mrst_isp_g_input(struct file *file, void *priv, unsigned int *i) -+{ -+ struct video_device *vdev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(vdev); -+ -+ DBG_entering; -+ -+ WARN_ON(priv != file->private_data); -+ -+ if (isp->sensor_soc && isp->sensor_raw) -+ if (isp->sensor_curr == isp->sensor_soc) -+ *i = 0; -+ else -+ *i = 1; -+ else -+ *i = 0; -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_s_input(struct file *file, void *priv, unsigned int i) -+{ -+ struct video_device *vdev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(vdev); -+ -+ int camera; -+ -+ DBG_entering; -+ -+ if (isp->streaming) { -+ printk(KERN_WARNING "VIDIOC_S_INPUT error: ISP is streaming\n"); -+ return -EBUSY; -+ } -+ -+ camera = mrst_isp_index_to_camera(isp, i); -+ if (MRST_CAMERA_NONE == camera) -+ return -EINVAL; -+ -+ if (mrst_camera_table[camera].type == MRST_CAMERA_SOC) -+ isp->sensor_curr = isp->sensor_soc; -+ else -+ isp->sensor_curr = isp->sensor_raw; -+ -+ dprintk(1, "set sensor %s as input", isp->sensor_curr->name); -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_g_ext_ctrls(struct file *file, -+ void *fh, -+ struct v4l2_ext_controls *c) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ int ret = -EINVAL; -+ -+ DBG_entering; -+ -+ if (c->ctrl_class != V4L2_CTRL_CLASS_CAMERA) { -+ printk(KERN_ERR "Invalid control class\n"); -+ return ret; -+ } -+ -+ c->error_idx = 0; -+ if (isp->motor) { -+ ret = v4l2_subdev_call(isp->motor, core, g_ext_ctrls, c); -+ if (c->error_idx) { -+ printk(KERN_ERR "mrst: error call g_ext_ctrls\n"); -+ return ret; -+ } -+ } -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_s_ext_ctrls(struct file *file, void *fh, -+ struct v4l2_ext_controls *c) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ int ret = -EINVAL; -+ -+ DBG_entering; -+ -+ if (c->ctrl_class != V4L2_CTRL_CLASS_CAMERA) { -+ printk(KERN_INFO "Invalid control class\n"); -+ return ret; -+ } -+ -+ c->error_idx = 0; -+ if (isp->motor) { -+ ret = v4l2_subdev_call(isp->motor, core, s_ext_ctrls, c); -+ if (c->error_idx) { -+ printk(KERN_ERR "mrst: error call s_ext_ctrls\n"); -+ return ret; -+ } -+ } -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_s_std(struct file *filp, void *priv, v4l2_std_id *a) -+{ -+ DBG_entering; -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_querycap(struct file *file, void *priv, -+ struct v4l2_capability *cap) -+{ -+ struct video_device *dev = video_devdata(file); -+ -+ DBG_entering; -+ -+ strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); -+ strlcpy(cap->card, dev->name, sizeof(cap->card)); -+ -+ cap->version = INTEL_VERSION(0, 5, 0); -+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; -+ -+ DBG_leaving; -+ -+ return 0; -+} -+ -+static int mrst_isp_cropcap(struct file *file, void *priv, -+ struct v4l2_cropcap *cap) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ -+ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ cap->bounds.left = 0; -+ cap->bounds.top = 0; -+ cap->bounds.width = isp->bufwidth; -+ cap->bounds.height = isp->bufheight; -+ cap->defrect = cap->bounds; -+ cap->pixelaspect.numerator = 1; -+ cap->pixelaspect.denominator = 1; -+ -+ DBG_leaving; -+ -+ return 0; -+} -+ -+static int mrst_isp_enum_fmt_cap(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ unsigned int index; -+ -+ DBG_entering; -+ -+ index = f->index; -+ -+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ else { -+ if (isp->sensor_curr == isp->sensor_soc) -+ if (index >= 8) -+ return -EINVAL; -+ if (index >= sizeof(fmts) / sizeof(*fmts)) -+ return -EINVAL; -+ -+ f->index = index; -+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ strlcpy(f->description, fmts[index].name, -+ sizeof(f->description)); -+ f->pixelformat = fmts[index].fourcc; -+ if (fmts[index].fourcc == V4L2_PIX_FMT_JPEG) -+ f->flags = V4L2_FMT_FLAG_COMPRESSED; -+ } -+ -+ DBG_leaving; -+ -+ return 0; -+ -+} -+ -+#define ALIGN4(x) ((((long)(x)) & 0x3) == 0) -+ -+static int mrst_isp_reqbufs(struct file *file, void *priv, -+ struct v4l2_requestbuffers *req) -+{ -+ int ret; -+ struct mrst_isp_fh *fh = file->private_data; -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ if (req->count == 0) -+ return 0; -+ -+ /* -+ * if (req->count > 3) -+ req->count = 3; -+ */ -+ -+ if (req->memory != V4L2_MEMORY_MMAP) { -+ eprintk("wrong memory type"); -+ return -EINVAL; -+ } -+ ret = videobuf_reqbufs(&fh->vb_q, req); -+ if (ret) -+ eprintk("err calling videobuf_reqbufs ret = %d", ret); -+ -+ if (!ret) -+ isp->buffer_required = 1; -+ -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_querybuf(struct file *file, void *priv, -+ struct v4l2_buffer *buf) -+{ -+ int ret; -+ struct mrst_isp_fh *fh = file->private_data; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ ret = videobuf_querybuf(&fh->vb_q, buf); -+ -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -+{ -+ int ret; -+ struct mrst_isp_fh *fh = file->private_data; -+ -+ WARN_ON(priv != file->private_data); -+ -+ DBG_entering; -+ ret = videobuf_qbuf(&fh->vb_q, buf); -+ /* identify which video buffer was q-ed */ -+ if (ret == 0) -+ fh->qbuf_flag |= (1<<buf->index); -+ dprintk(1, "q-ed index = %d", buf->index); -+ -+ DBG_leaving; -+ -+ return ret; -+} -+ -+static int mrst_isp_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -+{ -+ int ret; -+ struct mrst_isp_fh *fh = file->private_data; -+ -+ WARN_ON(priv != file->private_data); -+ -+ /*XXX zheng*/ -+ /* -+ if (frame_cnt == 0) { -+ printk(KERN_WARNING "timer start\n"); -+ intel_timer_start(); -+ } -+ */ -+ -+ DBG_entering; -+ -+ if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ if (b->memory != V4L2_MEMORY_MMAP) -+ return -EINVAL; -+ if (fh->qbuf_flag == 0) { -+ dprintk(1, "no buffer can be dq-ed\n"); -+ return -EINVAL; -+ } -+ -+ /*dprintk(3, "entering");*/ -+ /* ret = videobuf_dqbuf(&fh->vb_q, b, file->f_flags & O_NONBLOCK); */ -+ ret = videobuf_dqbuf(&fh->vb_q, b, 0); -+ /* identify which video buffer was dq-ed */ -+ if (ret == 0) -+ fh->qbuf_flag &= ~(1<<b->index); -+ -+ /*XXX zheng*/ -+ ++frame_cnt; -+ /* -+ if (frame_cnt % 10 == 0) -+ printk(KERN_WARNING "%d frames takes %dms to go, fps = %d\n", -+ frame_cnt, intel_get_micro_sec(), -+ frame_cnt * 1000 / intel_get_micro_sec()); -+ */ -+ -+ dprintk(1, "dq-ed index = %d", b->index); -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_streamon(struct file *file, void *priv, -+ enum v4l2_buf_type type) -+{ -+ struct mrst_isp_fh *fh = file->private_data; -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ int ret; -+ -+ DBG_entering; -+ -+ if (!isp->buffer_required) { -+ eprintk("buffer is not required, can not stream on "); -+ return -EINVAL; -+ } -+ -+ dprintk(2, "gamma2 = %d", isp->sys_conf.isp_cfg.flags.gamma2); -+ WARN_ON(priv != file->private_data); -+ -+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ mutex_lock(&isp->mutex); -+ -+ if (!to_sensor_config(isp->sensor_curr)->mipi_mode) -+ v4l2_subdev_call(isp->sensor_curr, video, s_stream, 1); -+ -+ mrst_isp_dp_init(&isp->sys_conf, to_sensor_config(isp->sensor_curr)); -+ mrst_isp_setup_viewfinder_path(isp, -+ to_sensor_config(isp->sensor_curr), -1); -+ -+ ret = videobuf_streamon(&fh->vb_q); -+ isp->streaming = 1; -+ -+ mutex_unlock(&isp->mutex); -+ -+ dprintk(1, "isp->active = %p", isp->active); -+ DBG_leaving; -+ return ret; -+} -+ -+static int mrst_isp_streamoff(struct file *file, void *priv, -+ enum v4l2_buf_type type) -+{ -+ struct mrst_isp_fh *fh = file->private_data; -+ struct video_device *dev = video_devdata(file); -+ struct mrst_isp_device *isp = video_get_drvdata(dev); -+ -+ unsigned long flags; -+ int ret; -+ -+ DBG_entering; -+ -+ WARN_ON(priv != file->private_data); -+ -+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ mutex_lock(&isp->mutex); -+ -+ ret = videobuf_streamoff(&fh->vb_q); -+ dprintk(1, "ret of videobuf_streamoff = %d", ret); -+ isp->streaming = 0; -+ -+ spin_lock_irqsave(&isp->lock, flags); -+ INIT_LIST_HEAD(&isp->capture); -+ isp->active = NULL; -+ isp->next = NULL; -+ isp->stopflag = 0; -+ isp->sys_conf.isp_hal_enable = 0; -+ isp->sys_conf.jpg_review_enable = 0; -+ isp->sys_conf.isp_cfg.img_eff_cfg.mode = CI_ISP_IE_MODE_OFF; -+ isp->sys_conf.isp_cfg.jpeg_enc_ratio = 1; -+ -+ spin_unlock_irqrestore(&isp->lock, flags); -+ -+ v4l2_subdev_call(isp->sensor_curr, video, s_stream, 0); -+ ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ -+ mutex_unlock(&isp->mutex); -+ -+ DBG_leaving; -+ return ret; -+} -+ -+static const struct v4l2_file_operations mrst_isp_fops = { -+ .owner = THIS_MODULE, -+ .open = mrst_isp_open, -+ .release = mrst_isp_close, -+ .read = mrst_isp_read, -+ .mmap = mrst_isp_mmap, -+ .ioctl = video_ioctl2, -+}; -+ -+static const struct v4l2_ioctl_ops mrst_isp_ioctl_ops = { -+ .vidioc_querycap = mrst_isp_querycap, -+ .vidioc_enum_fmt_vid_cap = mrst_isp_enum_fmt_cap, -+ .vidioc_g_fmt_vid_cap = mrst_isp_g_fmt_cap, -+ /* .vidioc_g_fmt_vid_out = -+ * mrst_isp_g_fmt_cap_for_sensor_hal, */ -+ .vidioc_try_fmt_vid_cap = mrst_isp_try_fmt_cap, -+ .vidioc_s_fmt_vid_cap = mrst_isp_s_fmt_cap, -+ .vidioc_cropcap = mrst_isp_cropcap, -+ .vidioc_reqbufs = mrst_isp_reqbufs, -+ .vidioc_querybuf = mrst_isp_querybuf, -+ .vidioc_qbuf = mrst_isp_qbuf, -+ .vidioc_dqbuf = mrst_isp_dqbuf, -+ .vidioc_enum_input = mrst_isp_enum_input, -+ .vidioc_g_input = mrst_isp_g_input, -+ .vidioc_s_input = mrst_isp_s_input, -+ .vidioc_s_std = mrst_isp_s_std, -+ .vidioc_queryctrl = mrst_isp_queryctrl, -+ .vidioc_streamon = mrst_isp_streamon, -+ .vidioc_streamoff = mrst_isp_streamoff, -+ .vidioc_g_ctrl = mrst_isp_g_ctrl, -+ .vidioc_s_ctrl = mrst_isp_s_ctrl, -+ .vidioc_enum_framesizes = mrst_isp_enum_framesizes, -+ .vidioc_enum_frameintervals = mrst_isp_enum_frameintervals, -+ .vidioc_g_ext_ctrls = mrst_isp_g_ext_ctrls, -+ .vidioc_s_ext_ctrls = mrst_isp_s_ext_ctrls, -+ /* FIXME private ioctls */ -+ .vidioc_default = mrst_isp_vidioc_default, -+}; -+ -+static struct video_device mrst_isp_vdev = { -+ .name = "mrst_isp", -+ .minor = -1, -+ .fops = &mrst_isp_fops, -+ .ioctl_ops = &mrst_isp_ioctl_ops, -+ .release = video_device_release_empty, -+}; -+ -+static int mrst_ci_sensor_probe(struct mrst_isp_device *isp) -+{ -+ struct v4l2_subdev *sensor = NULL, *motor = NULL; -+ int i; -+ char *name; -+ u8 addr; -+ -+ isp->adapter_sensor = i2c_get_adapter(MRST_I2C_BUS_SENSOR); -+ if (NULL == isp->adapter_sensor) { -+ printk(KERN_ERR "mrstisp: no sensor i2c adapter\n"); -+ return -ENODEV; -+ } -+ -+ dprintk(1, "got sensor i2c adapter: %s", isp->adapter_sensor->name); -+ -+ gpio_request(GPIO_STDBY1_PIN, "Sensor Standby1"); -+ gpio_request(GPIO_STDBY2_PIN, "Sensor Standby2"); -+ gpio_request(GPIO_RESET_PIN, "Sensor Reset"); -+ gpio_request(GPIO_SCLK_25, "Sensor clock"); -+ gpio_request(95, "Camera Motor"); -+ -+ /* Enable sensor related GPIO in system */ -+ gpio_direction_output(GPIO_STDBY1_PIN, 0); -+ gpio_direction_output(GPIO_STDBY2_PIN, 0); -+ gpio_direction_output(GPIO_RESET_PIN, 1); -+ gpio_direction_output(GPIO_SCLK_25, 0); -+ /* gpio_direction_output(GPIO_AF_PD, 1); */ -+ -+ /* -+ gpio_alt_func(GPIO_STDBY1_PIN, 0); -+ gpio_alt_func(GPIO_STDBY2_PIN, 0); -+ gpio_alt_func(GPIO_RESET_PIN, 0); -+ gpio_alt_func(GPIO_SCLK_25, 1); -+ */ -+ -+ for (i = 0; i < N_CAMERA; i++) { -+ name = mrst_camera_table[i].name; -+ addr = mrst_camera_table[i].sensor_addr; -+ if (mrst_camera_table[i].type == MRST_CAMERA_SOC) { -+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) -+ sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_sensor, -+ name, name, addr); -+#else -+ sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_sensor, -+ name, name, addr, NULL); -+#endif -+ -+ if (sensor == NULL) { -+ dprintk(2, "sensor %s not found", name); -+ continue; -+ } -+ isp->sensor_soc = sensor; -+ isp->sensor_soc_index = i; -+ dprintk(0, "soc camera sensor %s-%s successfully found", -+ name, sensor->name); -+ } -+ -+ if (mrst_camera_table[i].type == MRST_CAMERA_RAW) { -+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) -+ sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_sensor, -+ name, name, addr); -+#else -+ sensor = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_sensor, -+ name, name, addr, NULL); -+#endif -+ -+ if (sensor == NULL) { -+ dprintk(2, "sensor %s not found", name); -+ continue; -+ } -+ isp->sensor_raw = sensor; -+ isp->sensor_raw_index = i; -+ dprintk(0, "raw camera sensor %s successfully found", -+ name); -+ name = mrst_camera_table[i].motor_name; -+ addr = mrst_camera_table[i].motor_addr; -+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) -+ motor = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_sensor, -+ name, name, addr); -+#else -+ motor = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_sensor, -+ name, name, addr, NULL); -+#endif -+ -+ if (motor == NULL) -+ dprintk(2, "motor %s not found", name); -+ else { -+ isp->motor = motor; -+ dprintk(0, "motor %s successfully found", name); -+ } -+ } -+ } -+ -+ if (!isp->sensor_soc && !isp->sensor_raw) { -+ dprintk(0, "no camera sensor device attached"); -+ return -ENODEV; -+ } else { -+ if (isp->sensor_soc) -+ isp->sensor_curr = isp->sensor_soc; -+ else -+ isp->sensor_curr = isp->sensor_raw; -+ return 0; -+ } -+} -+ -+static int mrst_ci_flash_probe(struct mrst_isp_device *isp) -+{ -+ struct v4l2_subdev *flash = NULL; -+ char *name = "mrst_camera_flash"; -+ -+ gpio_request(45, "Camera Flash"); -+ gpio_direction_output(45, 0); -+ -+ isp->adapter_flash = i2c_get_adapter(MRST_I2C_BUS_FLASH); -+ if (NULL == isp->adapter_flash) { -+ dprintk(0, "no flash i2c adapter\n"); -+ return -ENODEV; -+ } -+ -+ dprintk(1, "got flash i2c adapter: %s", isp->adapter_flash->name); -+ -+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) -+ flash = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_flash, -+ name, name, 0x53); -+#else -+ flash = v4l2_i2c_new_subdev(&isp->v4l2_dev, -+ isp->adapter_flash, -+ name, name, 0x53, NULL); -+#endif -+ -+ if (flash == NULL) { -+ dprintk(0, "no flash IC found\n"); -+ return -ENODEV; -+ } -+ -+ dprintk(0, "flash IC found"); -+ return 0; -+} -+ -+#if IRQ -+static irqreturn_t mrst_isp_irq_handler(int this_irq, void *dev_id) -+{ -+ struct isp_register *mrv_reg = -+ (struct isp_register *) MEM_MRV_REG_BASE; -+ struct mrst_isp_device *isp = dev_id; -+ struct videobuf_buffer *vb; -+ unsigned long flags; -+ -+ u32 mi_mask = ci_isp_get_frame_end_irq_mask_isp(); -+ u32 isp_mask = MRV_ISP_RIS_DATA_LOSS_MASK -+ | MRV_ISP_RIS_PIC_SIZE_ERR_MASK; -+ u32 jpe_status_mask = MRV_JPE_ALL_STAT_MASK; -+ u32 jpe_error_mask = MRV_JPE_ALL_ERR_MASK; -+ u32 mblk_line_mask = MRV_MI_MBLK_LINE_MASK; -+ -+ u32 isp_irq; -+ u32 mi_irq; -+ u32 jpe_status_irq; -+ u32 jpe_error_irq; -+ u32 mipi_irq; -+ u32 mblk_line; -+ u32 bufbase; -+ -+ isp_irq = REG_READ_EX(mrv_reg->isp_ris) & isp_mask; -+ mi_irq = REG_READ_EX(mrv_reg->mi_ris) & mi_mask; -+ -+ mblk_line = REG_READ_EX(mrv_reg->mi_ris) & mblk_line_mask; -+ -+ jpe_status_irq = REG_READ_EX(mrv_reg->jpe_status_ris) & jpe_status_mask; -+ jpe_error_irq = REG_READ_EX(mrv_reg->jpe_error_ris) & jpe_error_mask; -+ -+ mipi_irq = REG_READ_EX(mrv_reg->mipi_ris) & 0x00f00000; -+ -+ dprintk(3, "IRQ: mblk_line = %x, mi_irq = %x, jpe_status_irq = %x," -+ " jpe_error_irq = %x, isp_irq = %x", mblk_line, mi_irq, -+ jpe_status_irq, jpe_error_irq, isp_irq); -+ -+ if (!(isp_irq | mi_irq | jpe_status_irq | jpe_error_irq | mblk_line -+ | mipi_irq)) { -+ dprintk(2, "unknown interrupt"); -+ return IRQ_HANDLED; -+ } -+ -+ REG_SET_SLICE_EX(mrv_reg->isp_icr, MRV_ISP_ICR_ALL, ON); -+ REG_SET_SLICE_EX(mrv_reg->mi_icr, MRV_MI_ALLIRQS, ON); -+ REG_SET_SLICE_EX(mrv_reg->jpe_error_icr, MRV_JPE_ALL_ERR, ON); -+ REG_SET_SLICE_EX(mrv_reg->jpe_status_icr, MRV_JPE_ALL_STAT, ON); -+ REG_WRITE_EX(mrv_reg->mipi_icr, 0xffffffff); -+ -+ if (isp_irq) { -+ /* Currently we don't reset hardware even error detect */ -+ dprintk(3, "ISP error IRQ received %x", isp_irq); -+ isp_error_num++; -+ isp_error_flag |= isp_irq; -+ return IRQ_HANDLED; -+ } -+ -+ if (mipi_irq) { -+ dprintk(3, "error in mipi_irq %x", mipi_irq); -+ mipi_error_num++; -+ mipi_error_flag |= mipi_irq; -+ return IRQ_HANDLED; -+ } -+ -+ if (mblk_line && mrst_isp_to_do_mblk_line) { -+ REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, OFF); -+ dprintk(3, "enter mblk_line irq"); -+ -+ if (!(isp->active && !isp->next)) { -+ dprintk(3, "wrong isq status"); -+ if (isp->active) -+ dprintk(2, "actie->i = %d", isp->active->i); -+ else -+ dprintk(2, "actie = NULL"); -+ if (isp->next) -+ dprintk(2, "next->i = %d", isp->next->i); -+ else -+ dprintk(2, "next = NULL"); -+ return IRQ_HANDLED; -+ } -+ -+ spin_lock_irqsave(&isp->lock, flags); -+ -+ if (!list_empty(&isp->capture)) { -+ isp->next = list_entry(isp->capture.next, -+ struct videobuf_buffer, queue); -+ isp->next->state = VIDEOBUF_ACTIVE; -+ bufbase = videobuf_to_dma_contig(isp->next); -+ mrst_isp_update_marvinvfaddr(isp, bufbase, -+ CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ dprintk(1, "updating new addr, next = %d", -+ isp->next->i); -+ } else { -+ isp->stopflag = 1; -+ dprintk(0, "stop isp"); -+ } -+ -+ mrst_isp_to_do_mblk_line = 0; -+ -+ spin_unlock_irqrestore(&isp->lock, flags); -+ -+ /* return IRQ_HANDLED; */ -+ } -+ -+ if (mi_irq && isp->pixelformat != V4L2_PIX_FMT_JPEG && -+ !jpe_status_irq) { -+ dprintk(1, "view finding case"); -+ -+ if (!isp->active) { -+ dprintk(0, "no active queue, You should not go here"); -+ mrst_isp_to_do_mblk_line = 1; -+ REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON); -+ return IRQ_HANDLED; -+ } -+ -+ spin_lock_irqsave(&isp->lock, flags); -+ -+ /* update captured frame status */ -+ vb = isp->active; -+ /* vb->size = ci_isp_mif_get_byte_cnt(); */ -+ /* if this buffer has been dq-ed, set nothing to state*/ -+ if (vb->state != VIDEOBUF_IDLE) -+ vb->state = VIDEOBUF_DONE; -+ vb->field_count++; -+ -+ isp->active = NULL; -+ dprintk(1, "buf %d size = %lx", vb->i, vb->size); -+ do_gettimeofday(&vb->ts); -+ wake_up(&vb->done); -+ -+ if (!isp->next) { -+ if (!list_empty(&isp->capture)) { -+ isp->active = list_entry(isp->capture.next, -+ struct videobuf_buffer, queue); -+ list_del_init(&isp->active->queue); -+ isp->active->state = VIDEOBUF_ACTIVE; -+ dprintk(3, "start next frame %d", -+ isp->active->i); -+ mrst_isp_to_do_mblk_line = 1; -+ REG_SET_SLICE(mrv_reg->mi_imsc, -+ MRV_MI_MBLK_LINE, ON); -+ } else { -+ mrst_isp_to_do_mblk_line = 1; -+ REG_SET_SLICE(mrv_reg->mi_imsc, -+ MRV_MI_MBLK_LINE, ON); -+ mrst_isp_disable_interrupt(isp); -+ dprintk(3, "no frame right now"); -+ } -+ } else { -+ isp->active = isp->next; -+ list_del_init(&isp->next->queue); -+ isp->next = NULL; -+ dprintk(1, "active = next = %d, next = NULL", -+ isp->active->i); -+ mrst_isp_to_do_mblk_line = 1; -+ REG_SET_SLICE(mrv_reg->mi_imsc, MRV_MI_MBLK_LINE, ON); -+ } -+ -+ spin_unlock_irqrestore(&isp->lock, flags); -+ return IRQ_HANDLED; -+ } -+ -+ if (jpe_status_irq) { -+ dprintk(2, "jpeg capture case"); -+ -+ if (!isp->active) -+ return IRQ_HANDLED; -+ -+ spin_lock_irqsave(&isp->lock, flags); -+ -+ vb = isp->active; -+ vb->size = ci_isp_mif_get_byte_cnt(); -+ vb->state = VIDEOBUF_DONE; -+ do_gettimeofday(&vb->ts); -+ vb->field_count++; -+ wake_up(&vb->done); -+ isp->active = NULL; -+ -+ dprintk(2, "index =%d, bufsize = %lx", vb->i, vb->size); -+ -+ spin_unlock_irqrestore(&isp->lock, flags); -+ -+ return IRQ_HANDLED; -+ } -+ -+ if (jpe_error_irq) -+ dprintk(2, "entered jpe_error_irq"); -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+static void __devexit mrst_isp_pci_remove(struct pci_dev *pdev) -+{ -+ struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); -+ struct mrst_isp_device *isp = to_isp(v4l2_dev); -+ -+ DBG_entering; -+ -+ ci_isp_stop(CI_ISP_CFG_UPDATE_FRAME_SYNC); -+ mrst_isp_disable_interrupt(isp); -+ -+#if IRQ -+ free_irq(pdev->irq, isp); -+#endif -+ -+ if (isp->vdev) { -+ dprintk(2, "isp->vdev = %p", isp->vdev); -+ video_unregister_device(isp->vdev); -+ } -+ -+ dma_release_declared_memory(&pdev->dev); -+ -+ iounmap(isp->regs); -+ -+ pci_release_regions(pdev); -+ -+ pci_disable_device(pdev); -+ -+ v4l2_device_unregister(&isp->v4l2_dev); -+ -+ kfree(isp); -+ -+ DBG_leaving; -+} -+ -+static int __devinit mrst_isp_pci_probe(struct pci_dev *pdev, -+ const struct pci_device_id *pci_id) -+{ -+ struct mrst_isp_device *isp; -+ unsigned int start = 0; -+ unsigned int len = 0; -+ int ret = 0; -+ -+ DBG_entering; -+ -+ /* alloc device struct */ -+ isp = kzalloc(sizeof(struct mrst_isp_device), GFP_KERNEL); -+ if (NULL == isp) { -+ printk(KERN_ERR "mrstisp: fail to kzalloc mrst_isp_device\n"); -+ ret = -ENOMEM; -+ goto exit; -+ } -+ -+ /* register v4l2 device */ -+ ret = v4l2_device_register(&pdev->dev, &isp->v4l2_dev); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: fail to register v4l2 device\n"); -+ goto exit_free_isp; -+ } -+ -+ /* PCI operations */ -+ ret = pci_enable_device(pdev); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: can't enable isp\n"); -+ goto exit_unregister_v4l2; -+ } -+ -+ pci_set_master(pdev); -+ -+ ret = pci_request_regions(pdev, "mrst isp"); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: can't request regions\n"); -+ goto exit_disable_isp; -+ } -+ -+ /* mem bar 0 */ -+ start = isp->mb0 = pci_resource_start(pdev, 0); -+ len = isp->mb0_size = pci_resource_len(pdev, 0); -+ -+ isp->regs = ioremap_nocache(start, len); -+ mrst_isp_regs = isp->regs; -+ if (isp->regs == NULL) { -+ printk(KERN_ERR "mrstisp: fail to ioremap isp registers\n"); -+ goto exit_release_regions; -+ } -+ -+ dprintk(1, "isp mb0 = %lx, mb0_size = %lx, regs = %p", -+ isp->mb0, isp->mb0_size, isp->regs); -+ -+ /* mem bar 1 */ -+ start = isp->mb1 = pci_resource_start(pdev, 1); -+ len = isp->mb1_size = pci_resource_len(pdev, 1); -+ -+ dprintk(1, "isp mb1 = %lx, mb1_size = %lx", isp->mb1, isp->mb1_size); -+ -+ ret = dma_declare_coherent_memory(&pdev->dev, start, -+ /* start, len - 640 * 480 * 2, */ -+ start, len, -+ DMA_MEMORY_MAP); -+ /* -+ DMA_MEMORY_MAP -+ | DMA_MEMORY_EXCLUSIVE); -+ */ -+ if (!ret) { -+ dprintk(0, "failed to declare dma memory"); -+ ret = -ENXIO; -+ goto exit_iounmap; -+ } -+ -+ /* init device struct */ -+ INIT_LIST_HEAD(&isp->capture); -+ spin_lock_init(&isp->lock); -+ mutex_init(&isp->mutex); -+ -+ pci_read_config_word(pdev, PCI_VENDOR_ID, &isp->vendorID); -+ pci_read_config_word(pdev, PCI_DEVICE_ID, &isp->deviceID); -+ -+ mrst_isp_defcfg_all_load(&isp->sys_conf.isp_cfg); -+ -+ isp->bufwidth = 640; -+ isp->bufheight = 480; -+ isp->depth = 12; -+ isp->pixelformat = V4L2_PIX_FMT_YVU420; -+ isp->streaming = 0; -+ isp->buffer_required = 0; -+ -+ -+ /* probe sensor */ -+ ret = mrst_ci_sensor_probe(isp); -+ if (ret) { -+ dprintk(0, "failed to sensor probe\n"); -+ goto exit_dma_release; -+ } -+ -+ /* regiter video device */ -+ isp->vdev = &mrst_isp_vdev; -+ isp->vdev->parent = &pdev->dev; -+ video_set_drvdata(isp->vdev, isp); -+ -+ ret = video_register_device(isp->vdev, VFL_TYPE_GRABBER, -1); -+ if (ret) { -+ dprintk(0, "fail to register video deivice"); -+ goto exit_dma_release; -+ } -+ -+ dprintk(0, "registered dev/video%d", isp->vdev->num); -+ dprintk(0, "isp->vdev = %p", isp->vdev); -+ -+#if IRQ -+ /* request irq */ -+ ret = request_irq(pdev->irq, mrst_isp_irq_handler, IRQF_SHARED, -+ /* pci_name(pdev), isp); */ -+ "mrst_camera_imaging", isp); -+ if (ret) { -+ dprintk(0, "fail to request irq"); -+ goto exit_unregister_video; -+ } -+ -+ mrst_isp_disable_interrupt(isp); -+#endif -+ -+ /* probe flash */ -+ mrst_ci_flash_probe(isp); -+ -+ mrst_isp_to_do_mblk_line = 0; -+ -+ dprintk(0, "mrstisp driver module successfully loaded"); -+ return 0; -+ -+exit_unregister_video: -+ video_unregister_device(isp->vdev); -+exit_dma_release: -+ dma_release_declared_memory(&pdev->dev); -+exit_iounmap: -+ iounmap(isp->regs); -+exit_release_regions: -+ pci_release_regions(pdev); -+exit_disable_isp: -+ pci_disable_device(pdev); -+exit_unregister_v4l2: -+ v4l2_device_unregister(&isp->v4l2_dev); -+exit_free_isp: -+ kfree(isp); -+exit: -+ return ret; -+} -+ -+#ifdef CONFIG_PM -+static int mrst_isp_pci_suspend(struct pci_dev *pdev, pm_message_t state) -+{ -+ struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); -+ struct mrst_isp_device *isp = to_isp(v4l2_dev); -+ int ret; -+ -+ DBG_entering; -+ -+ ci_isp_off(); -+ -+ ret = pci_save_state(pdev); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: pci_save_state failed %d\n", ret); -+ return ret; -+ } -+ -+ ret = pci_set_power_state(pdev, PCI_D3cold); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: fail to set power state\n"); -+ return ret; -+ } -+ -+/* -+ ret = ci_sensor_suspend(); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: Fail to suspend sensor\n"); -+ return ret; -+ } -+*/ -+ if (isp->sensor_soc) -+ v4l2_subdev_call(isp->sensor_soc, core, s_gpio, 1); -+ if (isp->sensor_raw) -+ v4l2_subdev_call(isp->sensor_raw, core, s_gpio, 1); -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static int mrst_isp_pci_resume(struct pci_dev *pdev) -+{ -+ struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); -+ struct mrst_isp_device *isp = to_isp(v4l2_dev); -+ int ret; -+ -+ DBG_entering; -+ -+ pci_set_power_state(pdev, PCI_D0); -+ pci_restore_state(pdev); -+ -+ ret = pci_enable_device(pdev); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: fail to enable device in resume\n"); -+ return ret; -+ } -+ -+/* -+ ret = ci_sensor_resume(); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: Fail to resume sensor\n"); -+ return ret; -+ } -+*/ -+ if (isp->sensor_soc) -+ v4l2_subdev_call(isp->sensor_soc, core, s_gpio, 0); -+ if (isp->sensor_raw) -+ v4l2_subdev_call(isp->sensor_raw, core, s_gpio, 0); -+ -+ ci_isp_init(); -+ -+ DBG_leaving; -+ return 0; -+} -+#endif -+ -+static struct pci_device_id mrst_isp_pci_tbl[] __devinitdata = { -+ { PCI_DEVICE(0x8086, 0x080B) }, -+ {0,} -+}; -+ -+MODULE_DEVICE_TABLE(pci, mrst_isp_pci_tbl); -+ -+static struct pci_driver mrst_isp_pci_driver = { -+ .name = "mrstisp", -+ .id_table = mrst_isp_pci_tbl, -+ .probe = mrst_isp_pci_probe, -+ .remove = mrst_isp_pci_remove, -+ #ifdef CONFIG_PM -+ .suspend = mrst_isp_pci_suspend, -+ .resume = mrst_isp_pci_resume, -+ #endif -+}; -+ -+static int __init mrst_isp_pci_init(void) -+{ -+ int ret; -+ -+ DBG_entering; -+ -+ ret = pci_register_driver(&mrst_isp_pci_driver); -+ if (ret) { -+ printk(KERN_ERR "mrstisp: Unable to register driver\n"); -+ return ret; -+ } -+ -+ if (ret) -+ dprintk(1, "Unable to register flash driver"); -+ -+ DBG_leaving; -+ return 0; -+} -+ -+static void __exit mrst_isp_pci_exit(void) -+{ -+ DBG_entering; -+ -+ pci_unregister_driver(&mrst_isp_pci_driver); -+ -+ DBG_leaving; -+} -+ -+module_init(mrst_isp_pci_init); -+/* late_initcall(mrst_isp_pci_init); */ -+module_exit(mrst_isp_pci_exit); -+ -+MODULE_DESCRIPTION("Intel Moorestown ISP driver"); -+MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>"); -+MODULE_LICENSE("GPL"); -+MODULE_SUPPORTED_DEVICE("video"); -+ -diff --git a/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c b/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c -new file mode 100644 -index 0000000..a05731a ---- /dev/null -+++ b/drivers/media/video/mrstci/mrstisp/mrstisp_mif.c -@@ -0,0 +1,763 @@ -+/* -+ * Support for Moorestown Langwell Camera Imaging ISP subsystem. -+ * -+ * Copyright (c) 2009 Intel Corporation. All Rights Reserved. -+ * -+ * Copyright (c) Silicon Image 2008 www.siliconimage.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License version -+ * 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ * -+ * -+ * Xiaolin Zhang <xiaolin.zhang@intel.com> -+ */ -+ -+#include "mrstisp_stdinc.h" -+ -+/* -+ * sets all main picture and self picture buffer offsets back to 0 -+ */ -+void ci_isp_mif_reset_offsets(enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ REG_SET_SLICE(mrv_reg->mi_mp_y_offs_cnt_init, -+ MRV_MI_MP_Y_OFFS_CNT_INIT, 0); -+ REG_SET_SLICE(mrv_reg->mi_mp_cb_offs_cnt_init, -+ MRV_MI_MP_CB_OFFS_CNT_INIT, 0); -+ REG_SET_SLICE(mrv_reg->mi_mp_cr_offs_cnt_init, -+ MRV_MI_MP_CR_OFFS_CNT_INIT, 0); -+ -+ REG_SET_SLICE(mrv_reg->mi_sp_y_offs_cnt_init, -+ MRV_MI_SP_Y_OFFS_CNT_INIT, 0); -+ REG_SET_SLICE(mrv_reg->mi_sp_cb_offs_cnt_init, -+ MRV_MI_SP_CB_OFFS_CNT_INIT, 0); -+ REG_SET_SLICE(mrv_reg->mi_sp_cr_offs_cnt_init, -+ MRV_MI_SP_CR_OFFS_CNT_INIT, 0); -+ -+ REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_OFFSET_EN, ON); -+ REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_BASE_EN, ON); -+ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ break; -+ default: -+ break; -+ } -+} -+ -+/* -+ * This function get the byte count from the last JPEG or raw data transfer -+ */ -+u32 ci_isp_mif_get_byte_cnt(void) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ -+ return (u32) REG_GET_SLICE(mrv_reg->mi_byte_cnt, MRV_MI_BYTE_CNT); -+} -+ -+/* -+ * Sets the desired self picture orientation, if possible. -+ */ -+static int ci_isp_mif_set_self_pic_orientation(enum ci_isp_mif_sp_mode -+ mrv_mif_sp_mode, -+ int activate_self_path) -+{ -+ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ u32 mi_ctrl = REG_READ(mrv_reg->mi_ctrl); -+ -+ u32 output_format = REG_GET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT); -+ -+ /* apply the desired self picture orientation, if possible */ -+ switch (mrv_mif_sp_mode) { -+ case CI_ISP_MIF_SP_ORIGINAL: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, 0); -+ break; -+ -+ case CI_ISP_MIF_SP_HORIZONTAL_FLIP: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_H_FLIP); -+ break; -+ -+ case CI_ISP_MIF_SP_VERTICAL_FLIP: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_V_FLIP); -+ break; -+ -+ case CI_ISP_MIF_SP_ROTATION_090_DEG: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_ROTATE); -+ break; -+ -+ case CI_ISP_MIF_SP_ROTATION_180_DEG: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_H_FLIP | -+ MRV_MI_ROT_AND_FLIP_V_FLIP); -+ break; -+ -+ case CI_ISP_MIF_SP_ROTATION_270_DEG: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_H_FLIP | -+ MRV_MI_ROT_AND_FLIP_V_FLIP | -+ MRV_MI_ROT_AND_FLIP_ROTATE); -+ break; -+ -+ case CI_ISP_MIF_SP_ROT_090_V_FLIP: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_V_FLIP | -+ MRV_MI_ROT_AND_FLIP_ROTATE); -+ break; -+ -+ case CI_ISP_MIF_SP_ROT_270_V_FLIP: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP, -+ MRV_MI_ROT_AND_FLIP_H_FLIP | -+ MRV_MI_ROT_AND_FLIP_ROTATE); -+ break; -+ -+ default: -+ eprintk("unknown value for mrv_mif_sp_mode"); -+ return CI_STATUS_NOTSUPP; -+ } -+ -+ if (REG_GET_SLICE(mi_ctrl, MRV_MI_ROT_AND_FLIP) & -+ MRV_MI_ROT_AND_FLIP_ROTATE) { -+ switch (output_format) { -+ case MRV_MI_SP_OUTPUT_FORMAT_RGB888: -+ case MRV_MI_SP_OUTPUT_FORMAT_RGB666: -+ case MRV_MI_SP_OUTPUT_FORMAT_RGB565: -+ /* rotation supported on this output modes */ -+ break; -+ default: -+ eprintk("rotation is only allowed for RGB modes."); -+ return CI_STATUS_NOTSUPP; -+ } -+ } -+ -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_ENABLE, -+ (activate_self_path) ? ENABLE : DISABLE); -+ REG_WRITE(mrv_reg->mi_ctrl, mi_ctrl); -+ REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON); -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Checks the main or self picture path buffer structure. -+ */ -+static int ci_isp_mif_check_mi_path_conf(const struct ci_isp_mi_path_conf -+ *isp_mi_path_conf, int main_buffer) -+{ -+ if (!isp_mi_path_conf) { -+ eprintk("isp_mi_path_conf is NULL"); -+ return CI_STATUS_NULL_POINTER; -+ } -+ -+ if (!isp_mi_path_conf->ybuffer.pucbuffer) { -+ eprintk("isp_mi_path_conf->ybuffer.pucbuffer is NULL"); -+ return CI_STATUS_NULL_POINTER; -+ } -+ -+ if (main_buffer) { -+ if ((((unsigned long)(isp_mi_path_conf->ybuffer.pucbuffer) -+ & ~(MRV_MI_MP_Y_BASE_AD_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->ybuffer.size -+ & ~(MRV_MI_MP_Y_SIZE_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->ybuffer.size -+ & (MRV_MI_MP_Y_SIZE_INIT_VALID_MASK)) == 0) -+ || -+ ((isp_mi_path_conf->ybuffer.offs -+ & ~(MRV_MI_MP_Y_OFFS_CNT_INIT_VALID_MASK)) != 0)) { -+ return CI_STATUS_OUTOFRANGE; -+ } -+ } else { -+ if ((((unsigned long) isp_mi_path_conf->ybuffer.pucbuffer -+ & ~(MRV_MI_SP_Y_BASE_AD_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->ybuffer.size & -+ ~(MRV_MI_SP_Y_SIZE_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->ybuffer.size & -+ (MRV_MI_SP_Y_SIZE_INIT_VALID_MASK)) == 0) -+ || -+ ((isp_mi_path_conf->ybuffer.offs & -+ ~(MRV_MI_SP_Y_OFFS_CNT_INIT_VALID_MASK)) != -+ 0) -+ || -+ ((isp_mi_path_conf->llength & -+ ~(MRV_MI_SP_Y_LLENGTH_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf-> -+ llength & (MRV_MI_SP_Y_LLENGTH_VALID_MASK)) == 0)) { -+ return CI_STATUS_OUTOFRANGE; -+ } -+ } -+ -+ if (isp_mi_path_conf->cb_buffer.pucbuffer != 0) { -+ if (main_buffer) { -+ if ((((unsigned long) -+ isp_mi_path_conf->cb_buffer.pucbuffer -+ & ~(MRV_MI_MP_CB_BASE_AD_INIT_VALID_MASK)) != -+ 0) -+ || -+ ((isp_mi_path_conf->cb_buffer.size & -+ ~(MRV_MI_MP_CB_SIZE_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->cb_buffer.size & -+ (MRV_MI_MP_CB_SIZE_INIT_VALID_MASK)) == 0) -+ || -+ ((isp_mi_path_conf->cb_buffer.offs & -+ ~(MRV_MI_MP_CB_OFFS_CNT_INIT_VALID_MASK)) != -+ 0)) { -+ return CI_STATUS_OUTOFRANGE; -+ } -+ } else { -+ if ((((unsigned long) -+ isp_mi_path_conf->cb_buffer.pucbuffer -+ & ~(MRV_MI_SP_CB_BASE_AD_INIT_VALID_MASK)) != -+ 0) -+ || -+ ((isp_mi_path_conf->cb_buffer.size & -+ ~(MRV_MI_SP_CB_SIZE_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->cb_buffer.size & -+ (MRV_MI_SP_CB_SIZE_INIT_VALID_MASK)) == 0) -+ || -+ ((isp_mi_path_conf->cb_buffer.offs & -+ ~(MRV_MI_SP_CB_OFFS_CNT_INIT_VALID_MASK)) != -+ 0)) { -+ return CI_STATUS_OUTOFRANGE; -+ } -+ } -+ } -+ -+ if (isp_mi_path_conf->cr_buffer.pucbuffer != 0) { -+ if (main_buffer) { -+ if ((((unsigned long) -+ isp_mi_path_conf->cr_buffer.pucbuffer -+ & ~(MRV_MI_MP_CR_BASE_AD_INIT_VALID_MASK)) != -+ 0) -+ || -+ ((isp_mi_path_conf->cr_buffer.size & -+ ~(MRV_MI_MP_CR_SIZE_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->cr_buffer.size & -+ (MRV_MI_MP_CR_SIZE_INIT_VALID_MASK)) == 0) -+ || -+ ((isp_mi_path_conf->cr_buffer.offs & -+ ~(MRV_MI_MP_CR_OFFS_CNT_INIT_VALID_MASK)) != -+ 0)){ -+ return CI_STATUS_OUTOFRANGE; -+ } -+ } else { -+ if ((((unsigned long) -+ isp_mi_path_conf->cr_buffer.pucbuffer -+ & ~(MRV_MI_SP_CR_BASE_AD_INIT_VALID_MASK)) -+ != 0) -+ || -+ ((isp_mi_path_conf->cr_buffer.size & -+ ~(MRV_MI_SP_CR_SIZE_INIT_VALID_MASK)) != 0) -+ || -+ ((isp_mi_path_conf->cr_buffer.size & -+ (MRV_MI_SP_CR_SIZE_INIT_VALID_MASK)) == 0) -+ || -+ ((isp_mi_path_conf->cr_buffer.offs & -+ ~(MRV_MI_SP_CR_OFFS_CNT_INIT_VALID_MASK)) != 0)) { -+ return CI_STATUS_OUTOFRANGE; -+ } -+ } -+ } -+ -+ return CI_STATUS_SUCCESS; -+} -+ -+/* -+ * Configures the main picture path buffers of the MI. -+ */ -+int ci_isp_mif_set_main_buffer(const struct ci_isp_mi_path_conf -+ *isp_mi_path_conf, -+ enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ int error = CI_STATUS_FAILURE; -+ -+ error = ci_isp_mif_check_mi_path_conf(isp_mi_path_conf, true); -+ if (error != CI_STATUS_SUCCESS) -+ return error; -+ -+ /* set register values */ -+ REG_SET_SLICE(mrv_reg->mi_mp_y_base_ad_init, -+ MRV_MI_MP_Y_BASE_AD_INIT, -+ (u32)(unsigned long)isp_mi_path_conf->ybuffer.pucbuffer); -+ REG_SET_SLICE(mrv_reg->mi_mp_y_size_init, MRV_MI_MP_Y_SIZE_INIT, -+ isp_mi_path_conf->ybuffer.size); -+ REG_SET_SLICE(mrv_reg->mi_mp_y_offs_cnt_init, -+ MRV_MI_MP_Y_OFFS_CNT_INIT, -+ isp_mi_path_conf->ybuffer.offs); -+ -+ if (isp_mi_path_conf->cb_buffer.pucbuffer != 0) { -+ REG_SET_SLICE(mrv_reg->mi_mp_cb_base_ad_init, -+ MRV_MI_MP_CB_BASE_AD_INIT, -+ (u32)(unsigned long) isp_mi_path_conf->cb_buffer. -+ pucbuffer); -+ REG_SET_SLICE(mrv_reg->mi_mp_cb_size_init, -+ MRV_MI_MP_CB_SIZE_INIT, -+ isp_mi_path_conf->cb_buffer.size); -+ REG_SET_SLICE(mrv_reg->mi_mp_cb_offs_cnt_init, -+ MRV_MI_MP_CB_OFFS_CNT_INIT, -+ isp_mi_path_conf->cb_buffer.offs); -+ } -+ -+ if (isp_mi_path_conf->cr_buffer.pucbuffer != 0) { -+ REG_SET_SLICE(mrv_reg->mi_mp_cr_base_ad_init, -+ MRV_MI_MP_CR_BASE_AD_INIT, -+ (u32)(unsigned long) isp_mi_path_conf->cr_buffer. -+ pucbuffer); -+ REG_SET_SLICE(mrv_reg->mi_mp_cr_size_init, -+ MRV_MI_MP_CR_SIZE_INIT, -+ isp_mi_path_conf->cr_buffer.size); -+ REG_SET_SLICE(mrv_reg->mi_mp_cr_offs_cnt_init, -+ MRV_MI_MP_CR_OFFS_CNT_INIT, -+ isp_mi_path_conf->cr_buffer.offs); -+ } -+ -+ /* -+ * update base and offset registers during next immediate or -+ * automatic update request -+ */ -+ REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE); -+ REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE); -+ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ /* -+ * frame synchronous update of shadow registers, -+ * update is done after the curr frame -+ */ -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ /* -+ * immediate update of shadow registers -+ * (will disturb an ongoing frame processing) -+ */ -+ REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ /* no update from within this function */ -+ break; -+ default: -+ break; -+ } -+ -+ return error; -+} -+ -+/* -+ * Configures the self picture path buffers of the MI. -+ * -+ */ -+int ci_isp_mif_set_self_buffer(const struct ci_isp_mi_path_conf -+ *isp_mi_path_conf, -+ enum ci_isp_conf_update_time update_time) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ int error = CI_STATUS_FAILURE; -+ -+ error = ci_isp_mif_check_mi_path_conf(isp_mi_path_conf, false); -+ if (error != CI_STATUS_SUCCESS) -+ return error; -+ -+ /* set register values */ -+ REG_SET_SLICE(mrv_reg->mi_sp_y_base_ad_init, -+ MRV_MI_SP_Y_BASE_AD_INIT, -+ (u32)(unsigned long)isp_mi_path_conf->ybuffer.pucbuffer); -+ REG_SET_SLICE(mrv_reg->mi_sp_y_size_init, MRV_MI_SP_Y_SIZE_INIT, -+ isp_mi_path_conf->ybuffer.size); -+ REG_SET_SLICE(mrv_reg->mi_sp_y_offs_cnt_init, -+ MRV_MI_SP_Y_OFFS_CNT_INIT, -+ isp_mi_path_conf->ybuffer.offs); -+ -+ /* -+ * llength is counted in pixels and this value could be stored -+ * directly into the register -+ */ -+ REG_SET_SLICE(mrv_reg->mi_sp_y_llength, MRV_MI_SP_Y_LLENGTH, -+ isp_mi_path_conf->llength); -+ -+ if (isp_mi_path_conf->cb_buffer.pucbuffer) { -+ REG_SET_SLICE(mrv_reg->mi_sp_cb_base_ad_init, -+ MRV_MI_SP_CB_BASE_AD_INIT, -+ (u32) (unsigned long)isp_mi_path_conf->cb_buffer. -+ pucbuffer); -+ REG_SET_SLICE(mrv_reg->mi_sp_cb_size_init, -+ MRV_MI_SP_CB_SIZE_INIT, -+ isp_mi_path_conf->cb_buffer.size); -+ REG_SET_SLICE(mrv_reg->mi_sp_cb_offs_cnt_init, -+ MRV_MI_SP_CB_OFFS_CNT_INIT, -+ isp_mi_path_conf->cb_buffer.offs); -+ } -+ -+ if (isp_mi_path_conf->cr_buffer.pucbuffer) { -+ REG_SET_SLICE(mrv_reg->mi_sp_cr_base_ad_init, -+ MRV_MI_SP_CR_BASE_AD_INIT, -+ (u32) (unsigned long)isp_mi_path_conf->cr_buffer. -+ pucbuffer); -+ REG_SET_SLICE(mrv_reg->mi_sp_cr_size_init, -+ MRV_MI_SP_CR_SIZE_INIT, -+ isp_mi_path_conf->cr_buffer.size); -+ REG_SET_SLICE(mrv_reg->mi_sp_cr_offs_cnt_init, -+ MRV_MI_SP_CR_OFFS_CNT_INIT, -+ isp_mi_path_conf->cr_buffer.offs); -+ } -+ -+ if ((!isp_mi_path_conf->ypic_width) -+ || (!isp_mi_path_conf->ypic_height)) { -+ return CI_STATUS_FAILURE; -+ } -+ -+ REG_SET_SLICE(mrv_reg->mi_sp_y_pic_width, MRV_MI_SP_Y_PIC_WIDTH, -+ isp_mi_path_conf->ypic_width); -+ REG_SET_SLICE(mrv_reg->mi_sp_y_pic_height, MRV_MI_SP_Y_PIC_HEIGHT, -+ isp_mi_path_conf->ypic_height); -+ REG_SET_SLICE(mrv_reg->mi_sp_y_pic_size, MRV_MI_SP_Y_PIC_SIZE, -+ isp_mi_path_conf->ypic_height * -+ isp_mi_path_conf->llength); -+ -+ /* -+ * update base and offset registers during next immediate or -+ * automatic update request -+ */ -+ REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE); -+ REG_SET_SLICE(mrv_reg->mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE); -+ -+ switch (update_time) { -+ case CI_ISP_CFG_UPDATE_FRAME_SYNC: -+ REG_SET_SLICE(mrv_reg->isp_ctrl, MRV_ISP_ISP_GEN_CFG_UPD, -+ ON); -+ break; -+ case CI_ISP_CFG_UPDATE_IMMEDIATE: -+ REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON); -+ break; -+ case CI_ISP_CFG_UPDATE_LATER: -+ break; -+ default: -+ break; -+ } -+ -+ return error; -+} -+ -+/* -+ * Configures the DMA path of the MI. -+ * -+ */ -+int ci_isp_mif_set_path_and_orientation(const struct ci_isp_mi_ctrl -+ *mrv_mi_ctrl) -+{ -+ struct isp_register *mrv_reg = (struct isp_register *) MEM_MRV_REG_BASE; -+ int error = CI_STATUS_OUTOFRANGE; -+ u32 mi_ctrl = 0; -+ -+ if (!mrv_mi_ctrl) { -+ eprintk("mrv_mi_ctrl is NULL"); -+ return CI_STATUS_NULL_POINTER; -+ } -+ -+ if ((mrv_mi_ctrl->irq_offs_init & -+ ~(MRV_MI_MP_Y_IRQ_OFFS_INIT_VALID_MASK)) != 0) { -+ eprintk("bad mrv_mi_ctrl->irq_offs_init value"); -+ return error; -+ } -+ -+ REG_SET_SLICE(mrv_reg->mi_mp_y_irq_offs_init, -+ MRV_MI_MP_Y_IRQ_OFFS_INIT, mrv_mi_ctrl->irq_offs_init); -+ -+ /* main picture path */ -+ switch (mrv_mi_ctrl->main_path) { -+ case CI_ISP_PATH_OFF: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, OFF); -+ break; -+ case CI_ISP_PATH_ON: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_MP_ENABLE, ON); -+ break; -+ case CI_ISP_PATH_JPE: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_JPEG_ENABLE, ON); -+ break; -+ case CI_ISP_PATH_RAW8: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, ON); -+ break; -+ case CI_ISP_PATH_RAW816: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_RAW_ENABLE, ON); -+ REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT, -+ MRV_MI_MP_WRITE_FORMAT_INTERLEAVED); -+ break; -+ default: -+ eprintk("bad mrv_mi_ctrl->main_path value"); -+ return error; -+ } -+ -+ /* self picture path output format */ -+ switch (mrv_mi_ctrl->mrv_mif_sp_out_form) { -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_422: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_YUV422); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_444: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_YUV444); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_420: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_YUV420); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_400: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_YUV400); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_RGB_565: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_RGB565); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_RGB_888: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_RGB888); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_RGB_666: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_OUTPUT_FORMAT, -+ MRV_MI_SP_OUTPUT_FORMAT_RGB666); -+ break; -+ -+ default: -+ eprintk("bad mrv_mi_ctrl->mrv_mif_sp_out_form value"); -+ return error; -+ } -+ -+ /* self picture path input format */ -+ switch (mrv_mi_ctrl->mrv_mif_sp_in_form) { -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_422: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT, -+ MRV_MI_SP_INPUT_FORMAT_YUV422); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_444: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT, -+ MRV_MI_SP_INPUT_FORMAT_YUV444); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_420: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT, -+ MRV_MI_SP_INPUT_FORMAT_YUV420); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_YCBCR_400: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_INPUT_FORMAT, -+ MRV_MI_SP_INPUT_FORMAT_YUV400); -+ break; -+ case CI_ISP_MIF_COL_FORMAT_RGB_565: -+ case CI_ISP_MIF_COL_FORMAT_RGB_666: -+ case CI_ISP_MIF_COL_FORMAT_RGB_888: -+ default: -+ eprintk("bad mrv_mi_ctrl->mrv_mif_sp_in_form value"); -+ return error; -+ } -+ -+ error = CI_STATUS_SUCCESS; -+ -+ /* self picture path write format */ -+ switch (mrv_mi_ctrl->mrv_mif_sp_pic_form) { -+ case CI_ISP_MIF_PIC_FORM_PLANAR: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT, -+ MRV_MI_SP_WRITE_FORMAT_PLANAR); -+ break; -+ case CI_ISP_MIF_PIC_FORM_SEMI_PLANAR: -+ if ((mrv_mi_ctrl->mrv_mif_sp_out_form == -+ CI_ISP_MIF_COL_FORMAT_YCBCR_422) -+ || (mrv_mi_ctrl->mrv_mif_sp_out_form == -+ CI_ISP_MIF_COL_FORMAT_YCBCR_420)) { -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT, -+ MRV_MI_SP_WRITE_FORMAT_SEMIPLANAR); -+ } else { -+ error = CI_STATUS_NOTSUPP; -+ } -+ break; -+ case CI_ISP_MIF_PIC_FORM_INTERLEAVED: -+ if (mrv_mi_ctrl->mrv_mif_sp_out_form == -+ CI_ISP_MIF_COL_FORMAT_YCBCR_422) { -+ REG_SET_SLICE(mi_ctrl, MRV_MI_SP_WRITE_FORMAT, -+ MRV_MI_SP_WRITE_FORMAT_INTERLEAVED); -+ } else { -+ error = CI_STATUS_NOTSUPP; -+ } -+ break; -+ default: -+ error = CI_STATUS_OUTOFRANGE; -+ break; -+ -+ } -+ -+ if (error != CI_STATUS_SUCCESS) { -+ eprintk("bad mrv_mi_ctrl->mrv_mif_sp_pic_form value"); -+ return error; -+ } -+ -+ if (mrv_mi_ctrl->main_path == CI_ISP_PATH_ON) { -+ /* for YCbCr mode only, permitted for raw mode */ -+ /* main picture path write format */ -+ switch (mrv_mi_ctrl->mrv_mif_mp_pic_form) { -+ case CI_ISP_MIF_PIC_FORM_PLANAR: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT, -+ MRV_MI_MP_WRITE_FORMAT_PLANAR); -+ break; -+ case CI_ISP_MIF_PIC_FORM_SEMI_PLANAR: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT, -+ MRV_MI_MP_WRITE_FORMAT_SEMIPLANAR); -+ break; -+ case CI_ISP_MIF_PIC_FORM_INTERLEAVED: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_MP_WRITE_FORMAT, -+ MRV_MI_MP_WRITE_FORMAT_INTERLEAVED); -+ break; -+ default: -+ error = CI_STATUS_OUTOFRANGE; -+ break; -+ } -+ } -+ -+ if (error != CI_STATUS_SUCCESS) { -+ eprintk("bad mrv_mi_ctrl->mrv_mif_mp_pic_form value"); -+ return error; -+ } -+ -+ /* burst length for chrominance for write port */ -+ /* setting burst mode to 16 bits -+ switch (mrv_mi_ctrl->burst_length_chrom) { -+ case CI_ISP_MIF_BURST_LENGTH_4: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM, -+ MRV_MI_BURST_LEN_CHROM_4); -+ break; -+ case CI_ISP_MIF_BURST_LENGTH_8: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM, -+ MRV_MI_BURST_LEN_CHROM_8); -+ break; -+ case CI_ISP_MIF_BURST_LENGTH_16: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM, -+ MRV_MI_BURST_LEN_CHROM_16); -+ break; -+ default: -+ error = CI_STATUS_OUTOFRANGE; -+ break; -+ } -+ */ -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_CHROM, -+ MRV_MI_BURST_LEN_CHROM_16); -+ -+ if (error != CI_STATUS_SUCCESS) { -+ eprintk("bad mrv_mi_ctrl->burst_length_chrom value"); -+ return error; -+ } -+ -+ /* burst length for luminance for write port */ -+ /* setting burst mode to 16 bits -+ switch (mrv_mi_ctrl->burst_length_lum) { -+ case CI_ISP_MIF_BURST_LENGTH_4: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM, -+ MRV_MI_BURST_LEN_LUM_4); -+ break; -+ case CI_ISP_MIF_BURST_LENGTH_8: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM, -+ MRV_MI_BURST_LEN_LUM_8); -+ break; -+ case CI_ISP_MIF_BURST_LENGTH_16: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM, -+ MRV_MI_BURST_LEN_LUM_16); -+ break; -+ default: -+ error = CI_STATUS_OUTOFRANGE; -+ break; -+ } -+ */ -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BURST_LEN_LUM, -+ MRV_MI_BURST_LEN_LUM_16); -+ -+ if (error != CI_STATUS_SUCCESS) { -+ eprintk("bad mrv_mi_ctrl->burst_length_lum value"); -+ return error; -+ } -+ -+ /* enable updating of the shadow registers for main and self picture -+ * to their init values -+ */ -+ switch (mrv_mi_ctrl->init_vals) { -+ case CI_ISP_MIF_NO_INIT_VALS: -+ break; -+ case CI_ISP_MIF_INIT_OFFS: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE); -+ break; -+ case CI_ISP_MIF_INIT_BASE: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE); -+ break; -+ case CI_ISP_MIF_INIT_OFFSAndBase: -+ REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_OFFSET_EN, ENABLE); -+ REG_SET_SLICE(mi_ctrl, MRV_MI_INIT_BASE_EN, ENABLE); -+ break; -+ default: -+ error = CI_STATUS_OUTOFRANGE; -+ break; -+ } -+ -+ if (error != CI_STATUS_SUCCESS) { -+ eprintk("bad mrv_mi_ctrl->init_vals value"); -+ return error; -+ } -+ -+ /* enable change of byte order for write port */ -+ REG_SET_SLICE(mi_ctrl, MRV_MI_BYTE_SWAP, -+ (mrv_mi_ctrl->byte_swap_enable) ? ON : OFF); -+ -+ /* enable or disable the last pixel signalization */ -+ REG_SET_SLICE(mi_ctrl, MRV_MI_LAST_PIXEL_SIG_EN, -+ (mrv_mi_ctrl->last_pixel_enable) ? ON : OFF); -+ -+ /* now write settings into register */ -+ REG_WRITE(mrv_reg->mi_ctrl, mi_ctrl); -+ -+ dprintk(2, "mi_ctrl = 0x%x", mi_ctrl); -+ -+ /* self picture path operating mode */ -+ if ((mrv_mi_ctrl->self_path == CI_ISP_PATH_ON) || -+ (mrv_mi_ctrl->self_path == CI_ISP_PATH_OFF)) { -+ -+ /* do not call if not supported */ -+ -+ /* support has been restricted to >= MI_V2 && <= MI_V3 in -+ * ci_isp_mif_set_self_pic_orientation, so we do the same here -+ */ -+ -+ error = ci_isp_mif_set_self_pic_orientation( -+ mrv_mi_ctrl->mrv_mif_sp_mode, -+ (int) (mrv_mi_ctrl->self_path -+ == CI_ISP_PATH_ON)); -+ } else { -+ eprintk("bad mrv_mi_ctrl->self_path value"); -+ error = CI_STATUS_OUTOFRANGE; -+ } -+ -+ REG_SET_SLICE(mrv_reg->mi_init, MRV_MI_MI_CFG_UPD, ON); -+ -+ return error; -+} --- -1.6.0.6 - |