fimc-is: Initial import from SM-N910 Android LL release code
authorMarek Szyprowski <m.szyprowski@samsung.com>
Thu, 6 Aug 2015 13:20:55 +0000 (15:20 +0200)
committerJunghoon Kim <jhoon20.kim@samsung.com>
Thu, 14 Feb 2019 05:57:00 +0000 (14:57 +0900)
Import fimc-is driver from SM-N910C_LL_Opensource (verified 32-bit
Android kernel) from opensource.samsung.com

Change-Id: I62eec9bc33a21c5742d2c5d5f79facfcb1ec59c9
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
110 files changed:
drivers/media/platform/exynos/fimc-is/Kconfig [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/Makefile [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/crc32.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/crc32.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-clk-gate.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-clk-gate.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-cmd.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-companion-dt.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-companion-dt.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-companion.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-companion.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-companion_address.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-config.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-core.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-core.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-af.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-af.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-companion.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-companion.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-csi.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-csi.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-eeprom.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-flite.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-flite.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-ischain.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-ischain.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-ois.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-ois.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-sensor.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-device-sensor.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-dt.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-dt.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-dvfs.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-dvfs.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-err.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-fan53555.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-fan53555.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-framemgr.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-framemgr.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-groupmgr.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-groupmgr.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-hw-csi.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-hw-ischain.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-hw.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-interface.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-interface.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-mem.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-mem.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-metadata.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-ncp6335b.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-ncp6335b.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-param.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-regs.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-resourcemgr.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-resourcemgr.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-sec-define.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-sec-define.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-spi.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-subdev-ctrl.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-subdev-ctrl.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-time.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-time.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-type.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-3aa.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-3aac.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-companion.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-isp.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-scc.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-scp.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-sensor.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-vdisc.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video-vdiso.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/fimc-is-video.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2_12m.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2_12m.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p3.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p3.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h5.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h5.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7_sunny.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7_sunny.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3l2.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3l2.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4e5.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4e5.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4h5.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4h5.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6a3.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6a3.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6b2.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6b2.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6d1.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6d1.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-8b1.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-8b1.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx134.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx134.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx135.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx135.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx175.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx175.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx219.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx219.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx240.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx240.h [new file with mode: 0644]

diff --git a/drivers/media/platform/exynos/fimc-is/Kconfig b/drivers/media/platform/exynos/fimc-is/Kconfig
new file mode 100644 (file)
index 0000000..2c2bd68
--- /dev/null
@@ -0,0 +1,182 @@
+config VIDEO_EXYNOS_FIMC_IS
+        bool "Exynos FIMC-IS (Image Subsystem) driver"
+        depends on VIDEO_EXYNOS
+        select MEDIA_EXYNOS
+        select USE_VENDER_FEATURE
+        default n
+        help
+          This is a v4l2 driver for exynos FIMC-IS device.
+config CAMERA_EEPROM_SUPPORT_REAR
+        bool "Enable eeprom for rear cam"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Enable eeprom for rear cam.
+config CAMERA_EEPROM_SUPPORT_FRONT
+        bool "Enable eeprom for front cam"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Enable eeprom for front cam.
+config COMPANION_USE
+        bool "Enable to companion"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Enable to companion.
+config OIS_USE
+        bool "Enable to ois"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Enable to ois.
+config OIS_FW_UPDATE_THREAD_USE
+        bool "Enable to ois fw update thread"
+        depends on OIS_USE
+        default n
+        help
+          Enable to ois fw update thread.
+config AF_HOST_CONTROL
+        bool "Enable to af control"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Enable to af control.
+config USE_VENDER_FEATURE
+        bool "Use vendor specific features"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Enable to use the vender.
+config CAMERA_SENSOR_8B1
+        bool "Use 8B1 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use 8B1 camera sensor.
+config CAMERA_SENSOR_6D1
+        bool "Use 6D1 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use 6D1 camera sensor.
+config CAMERA_SENSOR_8B1_OBJ
+        bool "Use 8B1 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 8B1 camera sensor.
+config CAMERA_SENSOR_6D1_OBJ
+        bool "Use 6D1 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 6D1 camera sensor.
+config CAMERA_SENSOR_6B2_OBJ
+        bool "Use 6B2 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 6B2 camera sensor.
+config CAMERA_SENSOR_6A3_OBJ
+        bool "Use 6A3 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 6A3 camera sensor.
+config CAMERA_SENSOR_IMX135_OBJ
+        bool "Use IMX135 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build IMX135 camera sensor.
+config CAMERA_SENSOR_IMX134_OBJ
+        bool "Use IMX134 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build IMX134 camera sensor.
+config CAMERA_SENSOR_3L2_OBJ
+        bool "Use 3L2 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 3L2 camera sensor.
+config CAMERA_SENSOR_2P2_OBJ
+        bool "Use 2P2 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 2P2 camera sensor.
+config CAMERA_SENSOR_2P2_12M_OBJ
+        bool "Use 2P2_12M camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 2P2_12M camera sensor.
+config CAMERA_SENSOR_2P3_OBJ
+        bool "Use 2P3 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 2P3 camera sensor.
+config CAMERA_SENSOR_3H5_OBJ
+        bool "Use 3H5 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 3H5 camera sensor.
+config CAMERA_SENSOR_3H7_OBJ
+        bool "Use 3H7 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 3H7 camera sensor.
+config CAMERA_SENSOR_3H7_SUNNY_OBJ
+        bool "Use 3H7_SUNNY camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 3H7_SUNNY camera sensor.
+config CAMERA_SENSOR_4E5_OBJ
+        bool "Use 4E5 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 4E5 camera sensor.
+config CAMERA_SENSOR_IMX175_OBJ
+        bool "Use IMX175 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build IMX175 camera sensor.
+config CAMERA_SENSOR_IMX219_OBJ
+        bool "Use IMX219 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build IMX219 camera sensor.
+config CAMERA_SENSOR_IMX240_OBJ
+        bool "Use IMX240 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build IMX240 camera sensor.
+config CAMERA_SENSOR_4H5_OBJ
+        bool "Use 4H5 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build 4H5 camera sensor.
+config CAMERA_SENSOR_SR261_OBJ
+        bool "Use SR261 camera sensor"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build SR261 camera sensor.
+config CAMERA_SENSOR_TEMP
+        bool "camera sensor temp"
+        depends on VIDEO_EXYNOS_FIMC_IS
+        default n
+        help
+          Use to build camera sensor temp.
diff --git a/drivers/media/platform/exynos/fimc-is/Makefile b/drivers/media/platform/exynos/fimc-is/Makefile
new file mode 100644 (file)
index 0000000..efe18a5
--- /dev/null
@@ -0,0 +1,62 @@
+fimc-is-objs   := fimc-is-core.o \
+               fimc-is-mem.o \
+               fimc-is-framemgr.o \
+               fimc-is-groupmgr.o \
+               fimc-is-resourcemgr.o \
+               fimc-is-video.o \
+               fimc-is-video-sensor.o \
+               fimc-is-video-3aa.o \
+               fimc-is-video-3aac.o \
+               fimc-is-video-isp.o \
+               fimc-is-video-scc.o \
+               fimc-is-video-scp.o \
+               fimc-is-video-vdisc.o \
+               fimc-is-video-vdiso.o \
+               fimc-is-hw-csi.o \
+               fimc-is-hw-ischain.o \
+               fimc-is-subdev-ctrl.o \
+               fimc-is-device-csi.o \
+               fimc-is-device-flite.o \
+               fimc-is-device-sensor.o \
+               fimc-is-device-ischain.o \
+               fimc-is-interface.o \
+               fimc-is-time.o \
+               fimc-is-dvfs.o \
+               fimc-is-dt.o \
+               fimc-is-clk-gate.o
+
+obj-$(CONFIG_USE_VENDER_FEATURE) := fimc-is-spi.o \
+                               fimc-is-sec-define.o \
+                               crc32.o
+
+obj-$(CONFIG_COMPANION_USE)    += fimc-is-companion.o \
+                               fimc-is-fan53555.o \
+                               fimc-is-ncp6335b.o \
+                               fimc-is-companion-dt.o \
+                               fimc-is-device-companion.o \
+                               fimc-is-video-companion.o
+
+obj-$(CONFIG_VIDEO_EXYNOS_FIMC_IS) += fimc-is.o
+obj-$(CONFIG_OIS_USE)  += fimc-is-device-ois.o
+obj-$(CONFIG_AF_HOST_CONTROL)  += fimc-is-device-af.o
+obj-$(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)       += fimc-is-device-eeprom.o
+obj-$(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)      += fimc-is-device-eeprom.o
+
+obj-$(CONFIG_CAMERA_SENSOR_6B2_OBJ) += sensor/fimc-is-device-6b2.o
+obj-$(CONFIG_CAMERA_SENSOR_8B1_OBJ) += sensor/fimc-is-device-8b1.o
+obj-$(CONFIG_CAMERA_SENSOR_6D1_OBJ) += sensor/fimc-is-device-6d1.o
+obj-$(CONFIG_CAMERA_SENSOR_IMX134_OBJ) += sensor/fimc-is-device-imx134.o
+obj-$(CONFIG_CAMERA_SENSOR_IMX135_OBJ) += sensor/fimc-is-device-imx135.o
+obj-$(CONFIG_CAMERA_SENSOR_3L2_OBJ) += sensor/fimc-is-device-3l2.o
+obj-$(CONFIG_CAMERA_SENSOR_2P2_OBJ) += sensor/fimc-is-device-2p2.o
+obj-$(CONFIG_CAMERA_SENSOR_2P2_12M_OBJ) += sensor/fimc-is-device-2p2_12m.o
+obj-$(CONFIG_CAMERA_SENSOR_2P3_OBJ) += sensor/fimc-is-device-2p3.o
+obj-$(CONFIG_CAMERA_SENSOR_3H5_OBJ) += sensor/fimc-is-device-3h5.o
+obj-$(CONFIG_CAMERA_SENSOR_3H7_OBJ) += sensor/fimc-is-device-3h7.o
+obj-$(CONFIG_CAMERA_SENSOR_3H7_SUNNY_OBJ) += sensor/fimc-is-device-3h7_sunny.o
+obj-$(CONFIG_CAMERA_SENSOR_4E5_OBJ) += sensor/fimc-is-device-4e5.o
+obj-$(CONFIG_CAMERA_SENSOR_6A3_OBJ) += sensor/fimc-is-device-6a3.o
+obj-$(CONFIG_CAMERA_SENSOR_IMX175_OBJ) += sensor/fimc-is-device-imx175.o
+obj-$(CONFIG_CAMERA_SENSOR_IMX240_OBJ) += sensor/fimc-is-device-imx240.o
+obj-$(CONFIG_CAMERA_SENSOR_IMX219_OBJ) += sensor/fimc-is-device-imx219.o
+obj-$(CONFIG_CAMERA_SENSOR_4H5_OBJ) += sensor/fimc-is-device-4h5.o
\ No newline at end of file
diff --git a/drivers/media/platform/exynos/fimc-is/crc32.c b/drivers/media/platform/exynos/fimc-is/crc32.c
new file mode 100644 (file)
index 0000000..5aae140
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include "crc32.h"
+
+/* #define DEBUG_CRC */
+
+static void makeCRCtable(unsigned long *table, unsigned long id)
+{
+       unsigned long i, j, k;
+
+       for(i = 0; i < 256; ++i) {
+               k = i;
+
+               for(j = 0; j < 8; ++j) {
+                       if(k & 1)
+                               k = (k >> 1) ^ id;
+                       else
+                               k >>= 1;
+               }
+
+               table[i] = k;
+       }
+}
+
+unsigned long getCRC(volatile unsigned short *mem, signed long count,
+       volatile unsigned short *crcH, volatile unsigned short *crcL)
+{
+       unsigned char mem0, mem1;
+       int i;
+       unsigned long CRC = 0;
+#ifndef DEBUG_CRC
+       unsigned long table[256];
+#else
+       unsigned long table[256] = {
+               0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+               0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+               0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+               0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+               0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+               0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+               0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+               0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+               0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+               0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+               0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+               0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+               0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+               0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+               0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+               0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+               0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+               0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+               0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+               0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+               0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+               0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+               0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+               0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+               0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+               0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+               0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+               0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+               0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+               0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+               0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+               0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+       };
+#endif
+
+       /* duration : under 1 ms */
+       makeCRCtable(table, 0xEDB88320);
+
+       CRC = ~CRC;
+       for(i = 0; i < count; i++) {
+               mem0 = (unsigned char)(mem[i] & 0x00ff);
+               mem1 = (unsigned char)((mem[i] >> 8) & 0x00ff);
+
+               CRC = table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8);
+               CRC = table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8);
+       }
+       CRC = ~CRC;
+
+       /*
+        * high 2 byte of crc32
+        * g_CAL[0page 31 addr.] or g_CAL[127page 31 addr.]
+        */
+       if(crcH)
+               *crcH = (unsigned short)((CRC >> 16)&(0x0000ffff));
+       /*
+        * low 2 byte of crc32
+        * g_CAL[0page 30 addr.] or g_CAL[127page 30 addr.]
+        */
+       if(crcL)
+               *crcL = (unsigned short)((CRC) & (0x0000ffff));
+
+       return CRC;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/crc32.h b/drivers/media/platform/exynos/fimc-is/crc32.h
new file mode 100644 (file)
index 0000000..324793c
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef CRC32_H
+#define CRC32_H
+
+/* unit of count is 2byte */
+unsigned long getCRC(volatile unsigned short *mem, signed long count,
+       volatile unsigned short *crcH, volatile unsigned short *crcL);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-clk-gate.c b/drivers/media/platform/exynos/fimc-is/fimc-is-clk-gate.c
new file mode 100644 (file)
index 0000000..47b1b71
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Samsung Exynos SoC series FIMC-IS driver
+ *
+ * exynos fimc-is core functions
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include "fimc-is-clk-gate.h"
+
+int fimc_is_clk_gate_init(struct fimc_is_core *core)
+{
+       struct fimc_is_clk_gate_ctrl *gate_ctrl;
+
+       pr_info("%s\n", __func__);
+
+       if (!core) {
+               err("core is NULL\n");
+               return -EINVAL;
+       }
+
+       gate_ctrl = &core->resourcemgr.clk_gate_ctrl;
+       memset(gate_ctrl, 0x0, sizeof(struct fimc_is_clk_gate_ctrl));
+
+       /* init spin_lock for clock gating */
+       spin_lock_init(&gate_ctrl->lock);
+       core->resourcemgr.clk_gate_ctrl.gate_info = core->pdata->gate_info;
+
+       /* ISSR53 is clock gating debugging region.
+        * High means clock on state.
+        * To prevent telling A5 wrong clock off state,
+        * clock on state should be set before clock off is set.
+        */
+       writel(0xFFFFFFFF, core->ischain[0].interface->regs + ISSR53);
+
+       return 0;
+}
+
+int fimc_is_clk_gate_lock_set(struct fimc_is_core *core, u32 instance, u32 is_start)
+{
+       spin_lock(&core->resourcemgr.clk_gate_ctrl.lock);
+       core->resourcemgr.clk_gate_ctrl.msk_lock_by_ischain[instance] = is_start;
+       spin_unlock(&core->resourcemgr.clk_gate_ctrl.lock);
+       return 0;
+}
+
+#if 0
+/* This function may be used when clk_enable api will be faster than now */
+int fimc_is_clk_gate_reg_set(struct fimc_is_core *core,
+               bool is_on, const char* gate_str, u32 clk_gate_id,
+               struct exynos_fimc_is_clk_gate_info *gate_info)
+{
+       struct platform_device *pdev = core->pdev;
+       if (is_on) {
+               if (gate_info->clk_on(pdev, gate_str) < 0) {
+                       pr_err("%s: could not enable %s\n", __func__, gate_str);
+                       return -EINVAL;
+               }
+       } else {
+               if (gate_info->clk_off(pdev, gate_str) < 0) {
+                       pr_err("%s: could not disable %s\n", __func__, gate_str);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+#endif
+
+int fimc_is_wrap_clk_gate_set(struct fimc_is_core *core,
+                       int msk_group_id, bool is_on)
+{
+       int i;
+
+       for (i = 0; i < FIMC_IS_GRP_MAX; i++) {
+               if (msk_group_id & (1 << i))
+                       fimc_is_clk_gate_set(core, i, is_on, true, false);
+       }
+
+       return 0;
+}
+
+inline bool fimc_is_group_otf(struct fimc_is_device_ischain *device, int group_id)
+{
+       struct fimc_is_group *group;
+
+       switch (group_id) {
+       case GROUP_ID_3A0:
+       case GROUP_ID_3A1:
+               group = &device->group_3aa;
+               break;
+       case GROUP_ID_ISP:
+               group = &device->group_isp;
+               break;
+       case GROUP_ID_DIS:
+               group = &device->group_dis;
+               break;
+       default:
+               group = NULL;
+               pr_err("%s unresolved group id %d", __func__,  group_id);
+               return false;
+       }
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state))
+               return true;
+       else
+               return false;
+}
+
+int fimc_is_clk_gate_set(struct fimc_is_core *core,
+                       int group_id, bool is_on, bool skip_set_state, bool user_scenario)
+{
+       int ret = 0;
+       int cfg = 0;
+       int i;
+       struct fimc_is_clk_gate_ctrl *gate_ctrl;
+       struct exynos_fimc_is_clk_gate_info *gate_info;
+       u32 mask_on, mask_off, mask_cond_depend;
+
+       gate_ctrl = &core->resourcemgr.clk_gate_ctrl;
+       gate_info = gate_ctrl->gate_info;
+
+       pr_debug("%s in\n", __func__);
+       spin_lock(&gate_ctrl->lock);
+
+       /* Set State */
+       if (is_on) {
+               if (skip_set_state == false) {
+                       (gate_ctrl->chk_on_off_cnt[group_id])++; /* for debuging */
+                       (gate_ctrl->msk_cnt[group_id])++;
+                       set_bit(group_id, &gate_ctrl->msk_state);
+               }
+               gate_info->groups[group_id].mask_clk_on_mod =
+                       gate_info->groups[group_id].mask_clk_on_org;
+       } else {
+               (gate_ctrl->chk_on_off_cnt[group_id])--; /* for debuging */
+               (gate_ctrl->msk_cnt[group_id])--;
+               if ((gate_ctrl->msk_cnt[group_id]) < 0) {
+                       pr_warn("%s msk_cnt[%d] is lower than zero !!\n", __func__, group_id);
+                       (gate_ctrl->msk_cnt[group_id]) = 0;
+               }
+               if ((gate_ctrl->msk_cnt[group_id]) == 0)
+                       clear_bit(group_id, &gate_ctrl->msk_state);
+               /* if there's some processing group shot, don't clock off */
+               if (test_bit(group_id, &gate_ctrl->msk_state))
+                       goto exit;
+               gate_info->groups[group_id].mask_clk_off_self_mod =
+                       gate_info->groups[group_id].mask_clk_off_self_org;
+       }
+
+       /* Don't off!! when other instance opening/closing */
+       if (is_on == false) {
+               for (i = 0; i < FIMC_IS_MAX_NODES; i++) {
+                       if ((!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &core->ischain[i].state)) &&
+                                       (gate_ctrl->msk_lock_by_ischain[i])) {
+                               pr_info("%s lock(on) due to instance(%d)\n", __func__, i);
+                               goto exit;
+                       }
+                       /* don't off! if there is at least this group that is OTF */
+                       if (fimc_is_group_otf(&core->ischain[i], group_id)) {
+                               pr_debug("%s don't off!! this instance(%d) group(%d) is OTF\n",
+                                       __func__, i, group_id);
+                               goto exit;
+                       }
+               }
+       }
+
+       /* Check user scenario */
+       if (user_scenario && gate_info->user_clk_gate) {
+               if (fimc_is_set_user_clk_gate(group_id,
+                                       core,
+                                       is_on,
+                                       gate_ctrl->msk_state,
+                                       gate_info) < 0) {
+                       pr_debug("%s user scenario is skip!! [%d] !!\n", __func__, group_id);
+                       goto exit;
+               }
+       }
+
+       /* Get the region for clock gating debug */
+       cfg = readl(core->ischain[0].interface->regs + ISSR53);
+
+       /* Get Mask of self-on/off */
+       if (is_on)
+               mask_on = gate_info->groups[group_id].mask_clk_on_mod;
+       else
+               mask_off = gate_info->groups[group_id].mask_clk_off_self_mod;
+
+       /* Clock on */
+       if (is_on && ((gate_ctrl->msk_clk_on_off_state) !=  mask_on)) {
+               cfg |= (mask_on << 16); /* shortly before clock on */
+               writel(cfg, core->ischain[0].interface->regs + ISSR53);
+
+               ret = gate_info->clk_on_off(mask_on, is_on);
+               gate_ctrl->msk_clk_on_off_state |= mask_on;
+
+               cfg |= (mask_on); /* after clock on */
+               writel(cfg, core->ischain[0].interface->regs + ISSR53);
+       }
+
+       /* Clock off and check dependancy (it's for only clock-off) */
+       if (is_on == false) {
+               mask_cond_depend = gate_info->groups[group_id].mask_cond_for_depend;
+               /* check dependancy */
+               if (mask_cond_depend > 0 &&
+                               (mask_cond_depend & (gate_ctrl->msk_state))) {
+                       mask_off |= gate_info->groups[group_id].mask_clk_off_depend;
+               }
+               /* clock off */
+               if (((gate_ctrl->msk_clk_on_off_state) & mask_off) > 0) {
+                       cfg &= ~(mask_off << 16); /* shortly before clock off */
+                       writel(cfg, core->ischain[0].interface->regs + ISSR53);
+
+                       ret = gate_info->clk_on_off(mask_off, is_on);
+                       gate_ctrl->msk_clk_on_off_state &= ~(mask_off);
+
+                       cfg &= ~(mask_off); /* after clock off */
+                       writel(cfg, core->ischain[0].interface->regs + ISSR53);
+               }
+       }
+exit:
+       spin_unlock(&gate_ctrl->lock);
+       pr_debug("%s out\n", __func__);
+
+       return ret;
+}
+
+int fimc_is_set_user_clk_gate(u32 group_id,
+               struct fimc_is_core *core,
+               bool is_on,
+               unsigned long msk_state,
+               struct exynos_fimc_is_clk_gate_info *gate_info)
+{
+       u32 user_scenario_id = 0;
+
+       /* deside what user scenario is */
+#if defined(ENABLE_FULL_BYPASS)
+       if (group_id == GROUP_ID_ISP)
+               user_scenario_id = CLK_GATE_FULL_BYPASS_SN;
+#else
+       if (group_id == GROUP_ID_ISP)
+               user_scenario_id = CLK_GATE_NOT_FULL_BYPASS_SN;
+
+#endif
+       if (group_id == GROUP_ID_ISP &&
+               test_bit(FIMC_IS_SUBDEV_START,
+                       &core->ischain[0].dis.state))
+               user_scenario_id = CLK_GATE_DIS_SN;
+
+       if (gate_info->user_clk_gate(group_id,
+                       is_on,
+                       user_scenario_id,
+                       msk_state,
+                       gate_info) < 0) {
+               pr_err("%s user_clk_gate failed(%d) !!\n", __func__, group_id);
+       }
+
+       return 0;
+}
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-clk-gate.h b/drivers/media/platform/exynos/fimc-is/fimc-is-clk-gate.h
new file mode 100644 (file)
index 0000000..79b9de6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_CLK_GATE_H
+#define FIMC_IS_CLK_GATE_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include "fimc-is-time.h"
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-groupmgr.h"
+#include "fimc-is-device-ischain.h"
+
+int fimc_is_clk_gate_init(struct fimc_is_core *core);
+int fimc_is_clk_gate_lock_set(struct fimc_is_core *core, u32 instance, u32 is_start);
+int fimc_is_clk_gate_reg_set(struct fimc_is_core *core,
+               bool is_on, const char* gate_str, u32 clk_gate_id,
+               struct exynos_fimc_is_clk_gate_info *gate_info);
+/* For several groups */
+int fimc_is_wrap_clk_gate_set(struct fimc_is_core *core,
+                       int msk_group_id, bool is_on);
+/* For only single group */
+int fimc_is_clk_gate_set(struct fimc_is_core *core,
+                       int group_id, bool is_on, bool skip_set_state, bool user_scenario);
+
+int fimc_is_set_user_clk_gate(u32 group_id,
+               struct fimc_is_core *core,
+               bool is_on,
+               unsigned long msk_state,
+               struct exynos_fimc_is_clk_gate_info *gate_info);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-cmd.h b/drivers/media/platform/exynos/fimc-is/fimc-is-cmd.h
new file mode 100644 (file)
index 0000000..f54961a
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_CMD_H
+#define FIMC_IS_CMD_H
+
+#include "fimc-is-config.h"
+
+#define IS_COMMAND_VER 132 /* IS COMMAND VERSION 1.32 */
+
+enum is_cmd {
+       /* HOST -> IS */
+       HIC_PREVIEW_STILL = 0x1,
+       HIC_PREVIEW_VIDEO,
+       HIC_CAPTURE_STILL,
+       HIC_CAPTURE_VIDEO,
+       HIC_PROCESS_START,
+       HIC_PROCESS_STOP,
+       HIC_STREAM_ON /* 7 */,
+       HIC_STREAM_OFF /* 8 */,
+       HIC_SHOT,
+       HIC_GET_STATIC_METADATA /* 10 */,
+       HIC_SET_CAM_CONTROL,
+       HIC_GET_CAM_CONTROL,
+       HIC_SET_PARAMETER /* 13 */,
+       HIC_GET_PARAMETER,
+       HIC_SET_A5_MAP /* 15 */,
+       HIC_SET_A5_UNMAP /* 16 */,
+       HIC_GET_STATUS,
+       /* SENSOR PART*/
+       HIC_OPEN_SENSOR,
+       HIC_CLOSE_SENSOR,
+       HIC_SIMMIAN_INIT /* 20 */,
+       HIC_SIMMIAN_WRITE,
+       HIC_SIMMIAN_READ,
+       HIC_POWER_DOWN,
+       HIC_GET_SET_FILE_ADDR,
+       HIC_LOAD_SET_FILE,
+       HIC_MSG_CONFIG,
+       HIC_MSG_TEST,
+       HIC_ISP_I2C_CONTROL,
+       HIC_CALIBRATE_ACTUATOR,
+       HIC_GET_IP_STATUS /* 30 */,
+       HIC_I2C_CONTROL_LOCK,
+#if (SUPPORTED_IS_CMD_VER >= 132)
+       HIC_SYSTEM_CONTROL,
+       HIC_SENSOR_MODE_CHANGE,
+#elif (SUPPORTED_IS_CMD_VER >= 131)
+       HIC_SENSOR_MODE_CHANGE,
+#endif
+       HIC_ADJUST_SET_FILE,
+       HIC_CHECK_A5_TASK_CPU_USAGE,
+       HIC_COMMAND_END,
+
+       /* IS -> HOST */
+       IHC_GET_SENSOR_NUMBER = 0x1000,
+       /* Parameter1 : Address of space to copy a setfile */
+       /* Parameter2 : Space szie */
+       IHC_SET_SHOT_MARK,
+       /* PARAM1 : a frame number */
+       /* PARAM2 : confidence level(smile 0~100) */
+       /* PARMA3 : confidence level(blink 0~100) */
+       IHC_SET_FACE_MARK,
+       /* PARAM1 : coordinate count */
+       /* PARAM2 : coordinate buffer address */
+       IHC_FRAME_DONE,
+       /* PARAM1 : frame start number */
+       /* PARAM2 : frame count */
+       IHC_AA_DONE,
+       IHC_NOT_READY,
+       IHC_FLASH_READY,
+#if (SUPPORTED_IS_CMD_VER >= 131)
+       IHC_REPORT_ERR,
+#endif
+       IHC_COMMAND_END
+};
+
+/* supported command macros by F/W version */
+#define FW_HAS_SYS_CTRL_CMD    (SUPPORTED_IS_CMD_VER >= 132)
+#define FW_HAS_SENSOR_MODE_CMD (SUPPORTED_IS_CMD_VER >= 131)
+#define FW_HAS_REPORT_ERR_CMD  (SUPPORTED_IS_CMD_VER >= 131)
+
+enum is_reply {
+       ISR_DONE        = 0x2000,
+       ISR_NDONE
+};
+
+enum is_scenario_id {
+       ISS_PREVIEW_STILL,
+       ISS_PREVIEW_VIDEO,
+       ISS_CAPTURE_STILL,
+       ISS_CAPTURE_VIDEO,
+       ISS_END
+};
+
+enum is_subscenario_id {
+       ISS_SUB_SCENARIO_STILL_PREVIEW = 0,     /* 0: still preview */
+       ISS_SUB_SCENARIO_VIDEO = 1,             /* 1: video */
+       ISS_SUB_SCENARIO_DUAL_STILL = 2,        /* 2: dual still preview */
+       ISS_SUB_SCENARIO_DUAL_VIDEO = 3,        /* 3: dual video */
+       ISS_SUB_SCENARIO_VIDEO_HIGH_SPEED = 4,  /* 4: video high speed */
+       ISS_SUB_SCENARIO_STILL_CAPTURE = 5,     /* 5: still capture */
+       ISS_SUB_SCENARIO_FHD_60FPS = 6,         /* 6: video FHD 60fps */
+       ISS_SUB_SCENARIO_UHD_30FPS = 7,         /* 7: video UHD 30fps */
+       ISS_SUB_SCENARIO_WVGA_300FPS = 8,       /* 8: video WVGA 300fps */
+       ISS_SUB_SCENARIO_STILL_PREVIEW_WDR = 9,
+       ISS_SUB_SCENARIO_VIDEO_WDR = 10,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_WDR = 11,
+       ISS_SUB_SCENARIO_UHD_30FPS_WDR = 12,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_ZOOM = 13,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_ZOOM_OUTDOOR = 14,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_ZOOM_INDOOR = 15,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_WDR_ZOOM = 16,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_WDR_ZOOM_OUTDOOR = 17,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_WDR_ZOOM_INDOOR = 18,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_LLS = 19,
+       ISS_SUB_SCENARIO_STILL_CAPTURE_WDR_LLS = 20,
+       ISS_SUB_END,
+
+       /* These values will be deprecated */
+       ISS_SUB_SCENARIO_FRONT_VT1 = 4,         /* 4: front camera VT1 for 3G (Temporary) */
+       ISS_SUB_SCENARIO_FRONT_VT2 = 5,         /* 5: front camera VT2 for LTE (Temporary) */
+       ISS_SUB_SCENARIO_FRONT_SMART_STAY = 6,  /* 6: front camera smart stay (Temporary) */
+       ISS_SUB_SCENARIO_FRONT_PANORAMA = 7,    /* 7: front camera front panorama (Temporary) */
+};
+
+enum is_system_control_id {
+       IS_SYS_CLOCK_GATE       = 0,
+       IS_SYS_END              = 1,
+};
+
+enum is_system_control_cmd {
+       SYS_CONTROL_DISABLE     = 0,
+       SYS_CONTROL_ENABLE      = 1,
+};
+
+enum is_msg_test_id {
+       IS_MSG_TEST_SYNC_LOG = 1,
+};
+
+struct is_setfile_header_element {
+       u32 binary_addr;
+       u32 binary_size;
+};
+
+struct is_setfile_header {
+       struct is_setfile_header_element isp[ISS_END];
+       struct is_setfile_header_element drc[ISS_END];
+       struct is_setfile_header_element fd[ISS_END];
+};
+
+#define HOST_SET_INT_BIT       0x00000001
+#define HOST_CLR_INT_BIT       0x00000001
+#define IS_SET_INT_BIT         0x00000001
+#define IS_CLR_INT_BIT         0x00000001
+
+#define HOST_SET_INTERRUPT(base)       (base->uiINTGR0 |= HOST_SET_INT_BIT)
+#define HOST_CLR_INTERRUPT(base)       (base->uiINTCR0 |= HOST_CLR_INT_BIT)
+#define IS_SET_INTERRUPT(base)         (base->uiINTGR1 |= IS_SET_INT_BIT)
+#define IS_CLR_INTERRUPT(base)         (base->uiINTCR1 |= IS_CLR_INT_BIT)
+
+struct is_common_reg {
+       u32 hicmd;
+       u32 hic_sensorid;
+       u32 hic_param1;
+       u32 hic_param2;
+       u32 hic_param3;
+       u32 hic_param4;
+
+       u32 power_down_debug_number;
+
+       u32 reserved1[2];
+
+       u32 ihcmd_iflag;
+       u32 ihcmd;
+       u32 ihc_sensorid;
+       u32 ihc_param1;
+       u32 ihc_param2;
+       u32 ihc_param3;
+       u32 ihc_param4;
+
+       u32 reserved2[2];
+
+       u32 taa0c_iflag;
+       u32 taa0c_sensor_id;
+       u32 taa0c_param1;
+       u32 taa0c_param2;
+       u32 taa0c_param3;
+
+       u32 reserved3[2];
+
+       u32 taa1c_iflag;
+       u32 taa1c_sensor_id;
+       u32 taa1c_param1;
+       u32 taa1c_param2;
+       u32 taa1c_param3;
+
+       u32 reserved4[2];
+
+       u32 scc_iflag;
+       u32 scc_sensor_id;
+       u32 scc_param1;
+       u32 scc_param2;
+       u32 scc_param3;
+
+       u32 reserved5[2];
+
+       u32 dis_iflag;
+       u32 dis_sensor_id;
+       u32 dis_param1;
+       u32 dis_param2;
+       u32 dis_param3;
+
+       u32 reserved6[2];
+
+       u32 scp_iflag;
+       u32 scp_sensor_id;
+       u32 scp_param1;
+       u32 scp_param2;
+       u32 scp_param3;
+
+       u32 reserved7[3];
+
+       u32 shot_iflag;
+       u32 shot_sensor_id;
+       u32 shot_param1;
+       u32 shot_param2;
+       u32 shot_param3;
+
+       u32 grp1_done_frame_num;
+
+       u32 fcount_sen3;
+       u32 fcount_sen2;
+       u32 fcount_sen1;
+       u32 fcount_sen0;
+};
+
+struct is_mcuctl_reg {
+       u32 mcuctl;
+       u32 bboar;
+
+       u32 intgr0;
+       u32 intcr0;
+       u32 intmr0;
+       u32 intsr0;
+       u32 intmsr0;
+
+       u32 intgr1;
+       u32 intcr1;
+       u32 intmr1;
+       u32 intsr1;
+       u32 intmsr1;
+
+       u32 intcr2;
+       u32 intmr2;
+       u32 intsr2;
+       u32 intmsr2;
+
+       u32 gpoctrl;
+       u32 cpoenctlr;
+       u32 gpictlr;
+
+       u32 pad[0xD];
+
+       struct is_common_reg common_reg;
+};
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-companion-dt.c b/drivers/media/platform/exynos/fimc-is/fimc-is-companion-dt.c
new file mode 100644 (file)
index 0000000..d52c9d4
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <mach/exynos-fimc-is-sensor.h>
+#include <mach/exynos-fimc-is.h>
+#include <media/exynos_mc.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+
+#include "fimc-is-dt.h"
+#include "fimc-is-companion-dt.h"
+
+#ifdef CONFIG_OF
+int fimc_is_sensor_parse_dt_with_companion(struct platform_device *pdev)
+{
+       int ret = 0;
+       u32 temp;
+       char *pprop;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       struct device *dev;
+       const char *name;
+       u32 id;
+
+       BUG_ON(!pdev);
+       BUG_ON(!pdev->dev.of_node);
+
+       dev = &pdev->dev;
+       dnode = dev->of_node;
+
+       pdata = kzalloc(sizeof(struct exynos_platform_fimc_is_sensor), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: no memory for platform data\n", __func__);
+               return -ENOMEM;
+       }
+
+       pdata->gpio_cfg = exynos_fimc_is_sensor_pins_cfg;
+       pdata->iclk_cfg = exynos_fimc_is_sensor_iclk_cfg;
+       pdata->iclk_on = exynos_fimc_is_sensor_iclk_on;
+       pdata->iclk_off = exynos_fimc_is_sensor_iclk_off;
+       pdata->mclk_on = exynos_fimc_is_sensor_mclk_on;
+       pdata->mclk_off = exynos_fimc_is_sensor_mclk_off;
+
+       ret = of_property_read_u32(dnode, "scenario", &pdata->scenario);
+       if (ret) {
+               err("scenario read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "mclk_ch", &pdata->mclk_ch);
+       if (ret) {
+               err("mclk_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "csi_ch", &pdata->csi_ch);
+       if (ret) {
+               err("csi_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "flite_ch", &pdata->flite_ch);
+       if (ret) {
+               err("flite_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "i2c_ch", &pdata->i2c_ch);
+       if (ret) {
+               err("i2c_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "i2c_addr", &pdata->i2c_addr);
+       if (ret) {
+               err("i2c_addr read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "is_bns", &pdata->is_bns);
+       if (ret) {
+               err("is_bns read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "id", &id);
+       if (ret) {
+               err("id read is fail(%d)", ret);
+               goto p_err;
+       }
+       pdata->id = id;
+
+       DT_READ_U32(dnode, "flash_first_gpio", pdata->flash_first_gpio);
+       DT_READ_U32(dnode, "flash_second_gpio", pdata->flash_second_gpio);
+
+       ret = of_property_read_string(dnode, "sensor_name", &name);
+       if (ret) {
+               err("sensor_name read is fail(%d)", ret);
+               goto p_err;
+       }
+       strcpy(pdata->sensor_name, name);
+
+       ret = of_property_read_u32(dnode, "sensor_id", &pdata->sensor_id);
+       if (ret) {
+               err("sensor_id read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       dev->platform_data = pdata;
+
+       if (id == SENSOR_POSITION_REAR)
+               ret = fimc_is_power_initpin(dev);
+       else {
+               ret = fimc_is_power_setpin(dev, id, pdata->sensor_id);
+       }
+       if (ret)
+               err("power_setpin(or initpin) failed(%d). id %d", ret, id);
+
+       pdev->id = id;
+
+       pdata->pinctrl = devm_pinctrl_get(dev);
+       if (IS_ERR(pdata->pinctrl)) {
+               err("devm_pinctrl_get is fail");
+               goto p_err;
+       } else {
+               ret = get_pin_lookup_state(dev, pdata);
+               if (ret < 0) {
+                       err("fimc_is_get_pin_lookup_state is fail");
+                       goto p_err;
+               }
+       }
+
+       return ret;
+p_err:
+       kfree(pdata);
+       return ret;
+}
+
+int fimc_is_companion_parse_dt(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       struct device *dev;
+
+       BUG_ON(!pdev);
+       BUG_ON(!pdev->dev.of_node);
+
+       dev = &pdev->dev;
+       dnode = dev->of_node;
+
+       pdata = kzalloc(sizeof(struct exynos_platform_fimc_is_sensor), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: no memory for platform data\n", __func__);
+               return -ENOMEM;
+       }
+
+       pdata->gpio_cfg = exynos_fimc_is_sensor_pins_cfg;
+       pdata->iclk_cfg = exynos_fimc_is_companion_iclk_cfg;
+       pdata->iclk_on = exynos_fimc_is_companion_iclk_on;
+       pdata->iclk_off = exynos_fimc_is_companion_iclk_off;
+       pdata->mclk_on = exynos_fimc_is_companion_mclk_on;
+       pdata->mclk_off = exynos_fimc_is_companion_mclk_off;
+
+       ret = of_property_read_u32(dnode, "scenario", &pdata->scenario);
+       if (ret) {
+               err("scenario read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "mclk_ch", &pdata->mclk_ch);
+       if (ret) {
+               err("mclk_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       pdata->companion_use_pmic = of_property_read_bool(dnode, "companion_use_pmic");
+       if (!pdata->companion_use_pmic) {
+               err("use_pmic not use(%d)", pdata->companion_use_pmic);
+       }
+
+       ret = of_property_read_u32(dnode, "sensor_id", &pdata->sensor_id);
+       if (ret) {
+               err("sensor_id read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       dev->platform_data = pdata;
+
+       ret = fimc_is_power_setpin(dev, SENSOR_POSITION_REAR, pdata->sensor_id);
+       if (ret)
+               err("power_setpin failed(%d)", ret);
+
+       pdata->pinctrl = devm_pinctrl_get(dev);
+       if (IS_ERR(pdata->pinctrl)) {
+               err("devm_pinctrl_get is fail");
+               goto p_err;
+       } else {
+               ret = get_pin_lookup_state(dev, pdata);
+               if (ret < 0) {
+                       err("fimc_is_get_pin_lookup_state is fail");
+                       goto p_err;
+               }
+       }
+
+       return ret;
+p_err:
+       kfree(pdata);
+       return ret;
+}
+#endif
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-companion-dt.h b/drivers/media/platform/exynos/fimc-is/fimc-is-companion-dt.h
new file mode 100644 (file)
index 0000000..f3746c7
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_COMPANION_DT_H
+#define FIMC_IS_COMPANION_DT_H
+
+int fimc_is_sensor_parse_dt_with_companion(struct platform_device *pdev);
+int fimc_is_companion_parse_dt(struct platform_device *pdev);
+#endif
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-companion.c b/drivers/media/platform/exynos/fimc-is/fimc-is-companion.c
new file mode 100644 (file)
index 0000000..691d0af
--- /dev/null
@@ -0,0 +1,1409 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include "fimc-is-sec-define.h"
+#include "fimc-is-companion.h"
+#include "fimc-is-device-ischain.h"
+#include "fimc-is-fan53555.h"
+#ifdef USE_ION_ALLOC
+#include <linux/dma-buf.h>
+#include <linux/exynos_ion.h>
+#include <linux/ion.h>
+#endif
+
+#define COMP_FW_EVT0                   "companion_fw_evt0.bin"
+#define COMP_FW_EVT1                   "companion_fw_evt1.bin"
+#define COMP_SETFILE_MASTER            "companion_master_setfile.bin"
+#define COMP_SETFILE_MODE              "companion_mode_setfile.bin"
+#define COMP_CAL_DATA          "cal"
+#define COMP_LSC                       "lsc"
+#define COMP_PDAF                      "pdaf"
+#define COMP_COEF_CAL                  "coef"
+#define COMP_DEFAULT_LSC               "companion_default_lsc.bin"
+#define COMP_DEFAULT_COEF              "companion_default_coef.bin"
+
+#define COMP_SETFILE_VIRSION_SIZE      16
+#define COMP_MAGIC_NUMBER              (0x73c1)
+#define FIMC_IS_COMPANION_LSC_SIZE     6600
+#define FIMC_IS_COMPANION_PDAF_SIZE    512
+#define FIMC_IS_COMPANION_COEF_TOTAL_SIZE      (4096 * 6)
+#define FIMC_IS_COMPANION_LSC_I0_SIZE  2
+#define FIMC_IS_COMPANION_LSC_J0_SIZE  2
+#define FIMC_IS_COMPANION_LSC_A_SIZE   4
+#define FIMC_IS_COMPANION_LSC_K4_SIZE  4
+#define FIMC_IS_COMPANION_LSC_SCALE_SIZE       2
+#define FIMC_IS_COMPANION_WCOEF1_SIZE  10
+#define FIMC_IS_COMPANION_COEF_CAL_SIZE        4032
+#define FIMC_IS_COMPANION_AF_INF_SIZE  2
+#define FIMC_IS_COMPANION_AF_MACRO_SIZE        2
+#define LITTLE_ENDIAN 0
+#define BIG_ENDIAN 1
+extern bool companion_lsc_isvalid;
+extern bool companion_coef_isvalid;
+extern bool crc32_c1_check;
+static u16 companion_ver;
+static u32 concord_fw_size;
+char companion_crc[10];
+
+#if 1
+static int fimc_is_comp_spi_read(struct spi_device *spi,
+               void *buf, u16 rx_addr, size_t size)
+{
+       unsigned char req_data[4] = { 0x03,  };
+       int ret;
+
+       struct spi_transfer t_c;
+       struct spi_transfer t_r;
+
+       struct spi_message m;
+
+       memset(&t_c, 0x00, sizeof(t_c));
+       memset(&t_r, 0x00, sizeof(t_r));
+
+       req_data[1] = (rx_addr & 0xFF00) >> 8;
+       req_data[2] = (rx_addr & 0xFF);
+
+       t_c.tx_buf = req_data;
+       t_c.len = 4;
+       t_c.cs_change = 1;
+       t_c.bits_per_word = 32;
+
+       t_r.rx_buf = buf;
+       t_r.len = size;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t_c, &m);
+       spi_message_add_tail(&t_r, &m);
+
+       ret = spi_sync(spi, &m);
+       if (ret) {
+               err("spi sync error - can't read data");
+               return -EIO;
+       } else
+               return 0;
+}
+#endif
+
+static int fimc_is_comp_spi_single_write(struct spi_device *spi, u16 addr, u16 data)
+{
+       int ret = 0;
+       u8 tx_buf[5];
+
+       tx_buf[0] = 0x02; /* write cmd */
+       tx_buf[1] = (addr >> 8) & 0xFF; /* address */
+       tx_buf[2] = (addr >> 0) & 0xFF; /* address */
+       tx_buf[3] = (data >>  8) & 0xFF; /* data */
+       tx_buf[4] = (data >>  0) & 0xFF; /* data */
+
+       ret = spi_write(spi, &tx_buf[0], 5);
+       if (ret)
+               err("spi sync error - can't read data");
+
+       return ret;
+}
+
+/* Burst mode: <command><address><data data data ...>
+ * Burst width: Maximun value is 512.
+ */
+static int fimc_is_comp_spi_burst_write(struct spi_device *spi,
+       u8 *buf, size_t size, size_t burst_width, int endian)
+{
+       int ret = 0;
+       u32 i = 0, j = 0;
+       u8 tx_buf[512];
+       size_t burst_size;
+
+       /* check multiples of 2 */
+       burst_width = (burst_width + 2 - 1) / 2 * 2;
+
+       burst_size = size / burst_width * burst_width;
+
+       for (i = 0; i < burst_size; i += burst_width) {
+               tx_buf[0] = 0x02; /* write cmd */
+               tx_buf[1] = 0x6F; /* address */
+               tx_buf[2] = 0x12; /* address */
+               if (endian == LITTLE_ENDIAN) {
+                       for (j = 0; j < burst_width; j++)
+                               tx_buf[j + 3] = *(buf + i + j); /* data for big endian */
+               } else if (endian == BIG_ENDIAN) {
+                       for (j = 0; j < burst_width; j += 2) {
+                               tx_buf[j + 3] = *(buf + i + j + 1); /* data for little endian */
+                               tx_buf[j + 4] = *(buf + i + j);
+                       }
+               }
+
+               ret = spi_write(spi, &tx_buf[0], j + 3);
+               if (ret) {
+                       err("spi write error - can't write data");
+                       goto p_err;
+               }
+       }
+
+       tx_buf[0] = 0x02; /* write cmd */
+       tx_buf[1] = 0x6F; /* address */
+       tx_buf[2] = 0x12; /* address */
+       if (endian == LITTLE_ENDIAN) {
+               for (j = 0; j < (size - burst_size); j ++) {
+                       tx_buf[j + 3] = *(buf + i + j); /* data for big endian */
+               }
+       } else if (endian == BIG_ENDIAN) {
+               for (j = 0; j < (size - burst_size); j += 2) {
+                       tx_buf[j + 3] = *(buf + i + j + 1); /* data for little endian */
+                       tx_buf[j + 4] = *(buf + i + j);
+               }
+       }
+
+       ret = spi_write(spi, &tx_buf[0], j + 3);
+       if (ret)
+               err("spi write error - can't write data");
+
+
+p_err:
+       return ret;
+}
+
+#if 0
+static int fimc_is_comp_i2c_read(struct i2c_client *client, u16 addr, u16 *data)
+{
+       int err;
+       u8 rxbuf[2], txbuf[2];
+       struct i2c_msg msg[2];
+
+       rxbuf[0] = (addr & 0xff00) >> 8;
+       rxbuf[1] = (addr & 0xff);
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = rxbuf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 2;
+       msg[1].buf = txbuf;
+
+       err = i2c_transfer(client->adapter, msg, 2);
+       if (unlikely(err != 2)) {
+               pr_err("%s: register read fail\n", __func__);
+               return -EIO;
+       }
+
+       *data = ((txbuf[0] << 8) | txbuf[1]);
+       return 0;
+}
+#endif
+
+#ifndef USE_SPI
+static int fimc_is_comp_i2c_write(struct i2c_client *client ,u16 addr, u16 data)
+{
+        int retries = I2C_RETRY_COUNT;
+        int ret = 0, err = 0;
+        u8 buf[4] = {0,};
+        struct i2c_msg msg = {
+                .addr   = client->addr,
+                .flags  = 0,
+                .len    = 4,
+                .buf    = buf,
+        };
+
+        buf[0] = addr >> 8;
+        buf[1] = addr;
+        buf[2] = data >> 8;
+        buf[3] = data & 0xff;
+
+#if 0
+        pr_info("%s : W(0x%02X%02X%02X%02X)\n",__func__, buf[0], buf[1], buf[2], buf[3]);
+#endif
+
+        do {
+                ret = i2c_transfer(client->adapter, &msg, 1);
+                if (likely(ret == 1))
+                        break;
+
+                usleep_range(10000,11000);
+                err = ret;
+        } while (--retries > 0);
+
+        /* Retry occured */
+        if (unlikely(retries < I2C_RETRY_COUNT)) {
+                pr_err("i2c_write: error %d, write (%04X, %04X), retry %d\n",
+                        err, addr, data, I2C_RETRY_COUNT - retries);
+        }
+
+        if (unlikely(ret != 1)) {
+                pr_err("I2C does not work\n\n");
+                return -EIO;
+        }
+
+        return 0;
+}
+#endif
+
+static int fimc_is_comp_single_write(struct fimc_is_core *core , u16 addr, u16 data)
+{
+       int ret = 0;
+#ifdef USE_SPI
+       struct spi_device *spi = core->spi1;
+       ret = fimc_is_comp_spi_single_write(spi, addr, data);
+       if (ret) {
+               err("spi_single_write() fail");
+       }
+#else
+       struct i2c_client *client = core->client0;
+       fimc_is_s_int_comb_isp(core, true, INTMR2_INTMCIS22); /* interrupt on */
+       ret = fimc_is_comp_i2c_write(client, addr, data);
+       if (ret) {
+               err("i2c write fail");
+       }
+       fimc_is_s_int_comb_isp(core, false, INTMR2_INTMCIS22); /* interrupt off */
+#endif
+
+       return ret;
+}
+
+static int fimc_is_comp_single_read(struct fimc_is_core *core , u16 addr, u16 *data, size_t size)
+{
+       int ret = 0;
+//#ifdef USE_SPI
+#if 1
+       struct spi_device *spi = core->spi1;
+       ret = fimc_is_comp_spi_read(spi, (void *)data, addr, size);
+       if (ret) {
+               err("spi_single_read() fail");
+       }
+       *data = *data << 8 | *data >> 8;
+#else
+       struct i2c_client *client = core->client0;
+       fimc_is_s_int_comb_isp(core, true, INTMR2_INTMCIS22); /* I2C0 interrupt on */
+       ret = fimc_is_comp_i2c_read(client, addr, data);
+       if (ret) {
+               err("i2c read fail");
+       }
+       fimc_is_s_int_comb_isp(core, false, INTMR2_INTMCIS22); /* I2C0 interrupt off */
+#endif
+
+       return ret;
+}
+
+static int fimc_is_comp_check_crc32(struct fimc_is_core *core, char *name)
+{
+       int ret = 0;
+       int  retries = CRC_RETRY_COUNT;
+       u32 checksum, from_checksum = 0;
+       u16 addr1, addr2, read_addr, data_size1, data_size2;
+       u16 result_data, cmd_data, temp_data;
+       struct fimc_is_from_info *sysfs_finfo;
+       char *cal_buf;
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+       fimc_is_sec_get_cal_buf(&cal_buf);
+
+       if (!strcmp(name, COMP_LSC)) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_LSC_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0xA000;
+               if (companion_lsc_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->lsc_gain_crc_addr]);
+               else
+                       from_checksum = 0x043DC8F8;
+       } else if (!strcmp(name, COMP_PDAF)) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_PDAF_SIZE;
+               addr1 = 0x2000;
+               addr2 = 0xB900;
+               from_checksum = *((u32 *)&cal_buf[sysfs_finfo->pdaf_crc_addr]);
+       } else if (!strcmp(name, COMP_FW_EVT1) || !strcmp(name, COMP_FW_EVT0)) {
+               concord_fw_size = concord_fw_size - 4;
+               data_size1 = (concord_fw_size >> 16) & 0xFFFF;
+               data_size2 = concord_fw_size & 0xFFFF;
+               addr1 = 0x0000;
+               addr2 = 0x0000;
+               from_checksum = *((u32 *)&companion_crc[0]);
+       } else if (!strcmp(name, COMP_COEF_CAL)) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_COEF_CAL_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0x0000;
+               if (companion_coef_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->coef1_crc_addr]);
+               else
+                       from_checksum = 0x98E85DAC;
+       } else if (!strcmp(name, "coef2")) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_COEF_CAL_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0x1000;
+               if (companion_coef_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->coef2_crc_addr]);
+               else
+                       from_checksum = 0x88358F49;
+       } else if (!strcmp(name, "coef3")) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_COEF_CAL_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0x2000;
+               if (companion_coef_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->coef3_crc_addr]);
+               else
+                       from_checksum = 0x138AF2AB;
+       } else if (!strcmp(name, "coef4")) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_COEF_CAL_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0x3000;
+               if (companion_coef_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->coef4_crc_addr]);
+               else
+                       from_checksum = 0x4447017A;
+       } else if (!strcmp(name, "coef5")) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_COEF_CAL_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0x4000;
+               if (companion_coef_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->coef5_crc_addr]);
+               else
+                       from_checksum = 0xDBB05433;
+       } else if (!strcmp(name, "coef6")) {
+               data_size1 = 0;
+               data_size2 = FIMC_IS_COMPANION_COEF_CAL_SIZE;
+               addr1 = 0x2001;
+               addr2 = 0x5000;
+               if (companion_coef_isvalid)
+                       from_checksum = *((u32 *)&cal_buf[sysfs_finfo->coef6_crc_addr]);
+               else
+                       from_checksum = 0x66064DFA;
+       } else {
+               err("wrong companion cal data name\n");
+               return -EINVAL;
+       }
+
+       ret = fimc_is_comp_single_write(core, 0x0024, 0x0000);
+       ret |= fimc_is_comp_single_write(core, 0x0026, 0x0000);//clear result register
+       ret |= fimc_is_comp_single_write(core, 0x0014, addr1);
+       ret |= fimc_is_comp_single_write(core, 0x0016, addr2);// source address
+       ret |= fimc_is_comp_single_write(core, 0x0018, data_size1);
+       ret |= fimc_is_comp_single_write(core, 0x001A, data_size2);//source size
+       ret |= fimc_is_comp_single_write(core, 0x000C, 0x000C);
+       ret |= fimc_is_comp_single_write(core, 0x6806, 0x0001);//interrupt on
+       if (ret) {
+               err("fimc_is_comp_check_crc32() i2c write fail");
+               return -EIO;
+       }
+
+       read_addr = 0x000C;
+       do {
+               fimc_is_comp_single_read(core, read_addr, &cmd_data, 2);
+               usleep_range(500, 500);
+               if (--retries < 0) {
+                       err("Read register failed!!!!, data = 0x%04x\n", cmd_data);
+                       break;
+               }
+       } while (cmd_data);
+       read_addr = 0x0024;
+       fimc_is_comp_single_read(core, read_addr, &result_data, 2);
+       read_addr = 0x0026;
+       fimc_is_comp_single_read(core, read_addr, &temp_data, 2);
+
+       checksum = result_data << 16 | temp_data;
+       if (checksum != from_checksum) {
+               err("[%s] CRC check is failed. Checksum = 0x%08x, FROM checksum = 0x%08x\n",
+                       name, checksum, from_checksum);
+               return -EIO;
+       }
+
+       return ret;
+}
+
+static int fimc_is_comp_load_binary(struct fimc_is_core *core, char *name)
+{
+       int ret = 0;
+       u32 size = 0;
+       const struct firmware *fw_blob = NULL;
+       static char fw_name[100];
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long nread;
+       int fw_requested = 1;
+       u32 i;
+       u8 *buf = NULL;
+       u32 data, cal_addr;
+       char version_str[60];
+       u16 addr1, addr2;
+       char companion_ver[12] = {0, };
+       struct fimc_is_from_info *sysfs_finfo;
+#ifdef USE_ION_ALLOC
+       struct ion_handle *handle = NULL;
+#endif
+       int retry_count = 0;
+
+       BUG_ON(!core);
+       BUG_ON(!core->pdev);
+       BUG_ON(!core->companion);
+       BUG_ON(!core->companion->pdev);
+       BUG_ON(!name);
+#ifdef USE_ION_ALLOC
+       BUG_ON(!core->fimc_ion_client);
+#endif
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       snprintf(fw_name, sizeof(fw_name), "%s%s",FIMC_IS_SETFILE_SDCARD_PATH, name);
+       fp = filp_open(fw_name, O_RDONLY, 0);
+       if (IS_ERR_OR_NULL(fp)) {
+               goto request_fw;
+       }
+
+       fw_requested = 0;
+       size = fp->f_path.dentry->d_inode->i_size;
+       pr_info("start read sdcard, file path %s, size %d Bytes\n", fw_name, size);
+
+#ifdef USE_ION_ALLOC
+       handle = ion_alloc(core->fimc_ion_client, (size_t)size, 0,
+                               EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+       if (IS_ERR_OR_NULL(handle)) {
+               err("fimc_is_comp_load_binary:failed to ioc_alloc\n");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       buf = (u8 *)ion_map_kernel(core->fimc_ion_client, handle);
+       if (IS_ERR_OR_NULL(buf)) {
+               err("fimc_is_comp_load_binary:fail to ion_map_kernle\n");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+#else
+       buf = vmalloc(size);
+       if (!buf) {
+               err("failed to allocate memory");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+#endif
+
+       nread = vfs_read(fp, (char __user *)buf, size, &fp->f_pos);
+       if (nread != size) {
+               err("failed to read firmware file, %ld Bytes\n", nread);
+               ret = -EIO;
+               goto p_err;
+       }
+       if ((!strcmp(name, COMP_FW_EVT0)) || (!strcmp(name, sysfs_finfo->load_c1_fw_name))) {
+               strncpy(companion_crc, buf+nread-4, 4);
+               strncpy(companion_ver, buf+nread - 16, 11);
+       }
+
+request_fw:
+       if (fw_requested) {
+               snprintf(fw_name, sizeof(fw_name), "%s", name);
+               set_fs(old_fs);
+               retry_count = 3;
+               ret = request_firmware(&fw_blob, fw_name, &core->companion->pdev->dev);
+               while (--retry_count && ret == -EAGAIN) {
+                       err("request_firmware retry(count:%d)", retry_count);
+                       ret = request_firmware(&fw_blob, fw_name, &core->companion->pdev->dev);
+               }
+
+               if (ret) {
+                       err("request_firmware is fail(ret:%d)", ret);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!fw_blob) {
+                       err("fw_blob is NULL");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!fw_blob->data) {
+                       err("fw_blob->data is NULL");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               size = fw_blob->size;
+#ifdef USE_ION_ALLOC
+               handle = ion_alloc(core->fimc_ion_client, (size_t)size, 0,
+                               EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+               if (IS_ERR_OR_NULL(handle)) {
+                       err("fimc_is_comp_load_binary:failed to ioc_alloc\n");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+
+               buf = (u8 *)ion_map_kernel(core->fimc_ion_client, handle);
+               if (IS_ERR_OR_NULL(buf)) {
+                       err("fimc_is_comp_load_binary:fail to ion_map_kernle\n");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+#else
+               buf = vmalloc(size);
+               if (!buf) {
+                       err("failed to allocate memory");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+#endif
+               memcpy((void *)buf, fw_blob->data, size);
+               if ((!strcmp(name, COMP_FW_EVT0)) || (!strcmp(name, sysfs_finfo->load_c1_fw_name))) {
+                       memcpy((void *)companion_crc, fw_blob->data + size - 4, 4);
+                       memcpy((void *)companion_ver, fw_blob->data + size - 16, 11);
+               }
+       }
+
+       if (!strcmp(name, COMP_FW_EVT0)) {
+               ret = fimc_is_comp_spi_burst_write(core->spi1, buf, size, 256, LITTLE_ENDIAN);
+               if (ret) {
+                       err("fimc_is_comp_spi_write() fail");
+                       goto p_err;
+               }
+               concord_fw_size = size;
+               info("%s version : %s\n", name, companion_ver);
+       } else if (!strcmp(name, sysfs_finfo->load_c1_fw_name)) {
+               ret = fimc_is_comp_spi_burst_write(core->spi1, buf, size, 256, LITTLE_ENDIAN);
+               if (ret) {
+                       err("fimc_is_comp_spi_write() fail");
+                       goto p_err;
+               }
+               concord_fw_size = size;
+               info("%s version : %s\n", name, companion_ver);
+       } else if (!strcmp(name, COMP_DEFAULT_LSC)) {
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       cal_addr = MEM_GRAS_B_IMX240;
+               } else {
+                       cal_addr = MEM_GRAS_B_2P2;
+               }
+               addr1 = (cal_addr >> 16) & 0xFFFF;
+               addr2 = cal_addr & 0xFFFF;
+               ret = fimc_is_comp_single_write(core, 0x6428, addr1);
+               if (ret) {
+                       err("fimc_is_comp_load_cal() write fail");
+               }
+               ret = fimc_is_comp_single_write(core, 0x642A, addr2);
+               if (ret) {
+                       err("fimc_is_comp_load_cal() write fail");
+               }
+               ret = fimc_is_comp_spi_burst_write(core->spi1, buf, size, 256, BIG_ENDIAN);
+               if (ret) {
+                       err("fimc_is_comp_spi_write() fail");
+                       goto p_err;
+               }
+       } else if (!strcmp(name, COMP_DEFAULT_COEF)) {
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       cal_addr = MEM_XTALK_10_IMX240;
+               } else {
+                       cal_addr = MEM_XTALK_10_2P2;
+               }
+               addr1 = (cal_addr >> 16) & 0xFFFF;
+               addr2 = cal_addr & 0xFFFF;
+               ret = fimc_is_comp_single_write(core, 0x6428, addr1);
+               if (ret) {
+                       err("fimc_is_comp_load_cal() write fail");
+               }
+               ret = fimc_is_comp_single_write(core, 0x642A, addr2);
+               if (ret) {
+                       err("fimc_is_comp_load_cal() write fail");
+               }
+               ret = fimc_is_comp_spi_burst_write(core->spi1, buf, size, 256, LITTLE_ENDIAN);
+               if (ret) {
+                       err("fimc_is_comp_spi_write() fail");
+                       goto p_err;
+               }
+       } else {
+               u32 offset = size - COMP_SETFILE_VIRSION_SIZE;
+               for (i = 0; i < offset; i += 4) {
+                       data =  *(buf + i + 0) << 24 |
+                               *(buf + i + 1) << 16 |
+                               *(buf + i + 2) << 8 |
+                               *(buf + i + 3) << 0;
+                       if(!strcmp(name, sysfs_finfo->load_c1_mastersetf_name)) {
+                               ret = fimc_is_comp_spi_single_write(core->spi1, (data >> 16), (u16)data);
+                               if (ret) {
+                                       err("fimc_is_comp_spi_setf_write() fail");
+                                       break;
+                               }
+                       } else {
+                               ret = fimc_is_comp_single_write(core, (data >> 16), (u16)data);
+                               if (ret) {
+                                       err("fimc_is_comp_write() fail");
+                                       break;
+                               }
+                       }
+               }
+
+               memcpy(version_str, buf + offset, COMP_SETFILE_VIRSION_SIZE);
+               version_str[COMP_SETFILE_VIRSION_SIZE] = '\0';
+
+               info("%s version : %s\n", name, version_str);
+       }
+
+p_err:
+#ifdef USE_ION_ALLOC
+       if (!IS_ERR_OR_NULL(buf)) {
+               ion_unmap_kernel(core->fimc_ion_client, handle);
+       }
+
+       if (!IS_ERR_OR_NULL(handle)) {
+               ion_free(core->fimc_ion_client, handle);
+       }
+#else
+       if (buf) {
+               vfree(buf);
+       }
+#endif
+       if (!fw_requested) {
+               if (!IS_ERR_OR_NULL(fp)) {
+                       filp_close(fp, current->files);
+               }
+               set_fs(old_fs);
+       } else {
+               if (!IS_ERR_OR_NULL(fw_blob)) {
+                       release_firmware(fw_blob);
+               }
+       }
+       return ret;
+}
+
+static int fimc_is_comp_load_cal(struct fimc_is_core *core, char *name)
+{
+
+       int ret = 0, endian;
+       u32 data_size = 0, offset;
+       struct fimc_is_from_info *sysfs_finfo;
+       char *cal_buf;
+       u16 data1, data2;
+       u32 comp_addr = 0;
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+       fimc_is_sec_get_cal_buf(&cal_buf);
+       pr_info("Camera: SPI write cal data, name = %s\n", name);
+
+       if (!strcmp(name, COMP_LSC)) {
+               data_size = FIMC_IS_COMPANION_LSC_SIZE;
+               offset = sysfs_finfo->lsc_gain_start_addr;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = MEM_GRAS_B_IMX240;
+               } else {
+                       comp_addr = MEM_GRAS_B_2P2;
+               }
+               endian = BIG_ENDIAN;
+       } else if (!strcmp(name, COMP_PDAF)) {
+               data_size = FIMC_IS_COMPANION_PDAF_SIZE;
+               offset = sysfs_finfo->pdaf_start_addr;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = MEM_AF_10_1_IMX240;
+               } else {
+                       comp_addr = MEM_AF_10_1_2P2;
+               }
+               endian = LITTLE_ENDIAN;
+       } else if (!strcmp(name, COMP_COEF_CAL)) {
+               data_size = FIMC_IS_COMPANION_COEF_TOTAL_SIZE;
+               offset = sysfs_finfo->coef1_start;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = MEM_XTALK_10_IMX240;
+               } else {
+                       comp_addr = MEM_XTALK_10_2P2;
+               }
+               endian = LITTLE_ENDIAN;
+       } else {
+               err("wrong companion cal data name\n");
+               return -EINVAL;
+       }
+       data1 = comp_addr >> 16;
+       data2 = (u16)comp_addr;
+       ret = fimc_is_comp_single_write(core, 0x6428, data1);
+       if (ret) {
+               err("fimc_is_comp_load_cal() i2c write fail");
+       }
+       ret = fimc_is_comp_single_write(core, 0x642A, data2);
+       if (ret) {
+               err("fimc_is_comp_load_cal() i2c write fail");
+       }
+
+       ret = fimc_is_comp_spi_burst_write(core->spi1, cal_buf + offset, data_size, 256, endian);
+       if (ret) {
+               err("fimc_is_comp_spi_write_cal() fail\n");
+       }
+       return ret;
+}
+
+#if 0
+static int fimc_is_comp_read_i2c_cal(struct fimc_is_core *core, u32 addr)
+{
+       int ret = 0;
+       u32 i,data_size = 0;
+       u16 data1, data2;
+       u8 read_data[2];
+
+       struct fimc_is_from_info *sysfs_finfo;
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+
+       fimc_is_s_int_comb_isp(core, true, INTMR2_INTMCIS22); /* interrupt on */
+       if (addr == sysfs_finfo->lsc_i0_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_I0_SIZE;
+               data1 = 0x0EF8;
+       } else if (addr == sysfs_finfo->lsc_j0_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_J0_SIZE;
+               data1 = 0x0EFA;
+       } else if (addr == sysfs_finfo->lsc_a_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_A_SIZE;
+               data1 = 0x0F00;
+       } else if (addr == sysfs_finfo->lsc_k4_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_K4_SIZE;
+               data1 = 0x0F04;
+       } else if (addr == sysfs_finfo->lsc_scale_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_SCALE_SIZE;
+               data1 = 0x0F08;
+       } else if (addr == sysfs_finfo->wcoefficient1_addr) {
+               data_size = FIMC_IS_COMPANION_WCOEF1_SIZE;
+               data1 = 0x1420;
+       } else {
+               err("wrong companion cal data addr\n");
+               return -EINVAL;
+       }
+       pr_info("===Camera: I2C read cal data, addr [0x%04x], size(%d)\n", addr,data_size);
+       ret = fimc_is_comp_i2c_write(core->client0, 0x642C, 0x4000);
+       if (ret) {
+               err("fimc_is_comp_load_i2c_cal() i2c write fail");
+       }
+       ret = fimc_is_comp_i2c_write(core->client0, 0x642E, data1);
+       if (ret) {
+               err("fimc_is_comp_load_i2c_cal() i2c write fail");
+       }
+
+       for (i = 0; i < data_size; i += 2) {
+               fimc_is_comp_spi_read(core->spi1, (void *)read_data, data1, 2);
+               data2 = read_data[0] << 8 | read_data[1] << 0;
+//             pr_info("===Camera: I2C read addr[0x%04x],data[0x%04x]\n", data1,data2);
+               if (ret) {
+                               err("fimc_is_comp_i2c_setf_write() fail");
+                               break;
+               }
+               data1 += 2;
+       }
+
+       fimc_is_s_int_comb_isp(core, false, INTMR2_INTMCIS22); /* interrupt off */
+
+       return ret;
+}
+#endif
+
+static int fimc_is_comp_load_i2c_cal(struct fimc_is_core *core, u32 addr)
+{
+       int ret = 0;
+       u8 *buf = NULL;
+       u32 i, j, data_size = 0;
+       u16 data1, data2, data3 = 0, data4 = 0xFFFF;
+       u32 comp_addr = 0;
+
+       struct fimc_is_from_info *sysfs_finfo;
+       char *cal_buf;
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+       fimc_is_sec_get_cal_buf(&cal_buf);
+
+       if (addr == sysfs_finfo->lsc_i0_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_I0_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_uParabolicCenterX_IMX240;
+               } else {
+                       comp_addr = grasTuning_uParabolicCenterX_2P2;
+               }
+               if (!companion_lsc_isvalid)
+                       data3 = 0x780A;
+       } else if (addr == sysfs_finfo->lsc_j0_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_J0_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_uParabolicCenterY_IMX240;
+               } else {
+                       comp_addr = grasTuning_uParabolicCenterY_2P2;
+               }
+               if (!companion_lsc_isvalid)
+                       data3 = 0xEC05;
+       } else if (addr == sysfs_finfo->lsc_a_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_A_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_uBiQuadFactorA_IMX240;
+               } else {
+                       comp_addr = grasTuning_uBiQuadFactorA_2P2;
+               }
+               if (!companion_lsc_isvalid) {
+                       data3 = 0x6A2A;
+                       data4 = 0x0100;
+               }
+       } else if (addr == sysfs_finfo->lsc_k4_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_K4_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_uBiQuadFactorB_IMX240;
+               } else {
+                       comp_addr = grasTuning_uBiQuadFactorB_2P2;
+               }
+               if (!companion_lsc_isvalid) {
+                       data3 = 0x0040;
+                       data4 = 0x0000;
+               }
+       } else if (addr == sysfs_finfo->lsc_scale_gain_addr) {
+               data_size = FIMC_IS_COMPANION_LSC_SCALE_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_uBiQuadScaleShiftAdder_IMX240;
+               } else {
+                       comp_addr = grasTuning_uBiQuadScaleShiftAdder_2P2;
+               }
+               if (!companion_lsc_isvalid)
+                       data3 = 0x0600;
+       } else if (addr == sysfs_finfo->wcoefficient1_addr) {
+               data_size = FIMC_IS_COMPANION_WCOEF1_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = xtalkTuningParams_wcr_IMX240;
+               } else {
+                       comp_addr = xtalkTuningParams_wcr_2P2;
+               }
+       } else if (addr == sysfs_finfo->af_inf_addr) {
+               data_size = FIMC_IS_COMPANION_AF_INF_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_actuatorPositionToShadingPowerLut_0_IMX240;
+               } else {
+                       comp_addr = grasTuning_actuatorPositionToShadingPowerLut_0_2P2;
+               }
+       } else if (addr == sysfs_finfo->af_macro_addr) {
+               data_size = FIMC_IS_COMPANION_AF_MACRO_SIZE;
+               if (sysfs_finfo->sensor_id == COMPANION_SENSOR_IMX240) {
+                       comp_addr = grasTuning_actuatorPositionToShadingPowerLut_9_IMX240;
+               } else {
+                       comp_addr = grasTuning_actuatorPositionToShadingPowerLut_9_2P2;
+               }
+       } else {
+               err("wrong companion cal data name\n");
+               return -EINVAL;
+       }
+       data1 = comp_addr >> 16;
+       data2 = (u16)comp_addr;
+
+       ret = fimc_is_comp_single_write(core, 0x6028, data1);
+       if (ret) {
+               err("fimc_is_comp_load_i2c_cal() i2c write fail");
+       }
+       ret = fimc_is_comp_single_write(core, 0x602A, data2);
+       if (ret) {
+               err("fimc_is_comp_load_i2c_cal() i2c write fail");
+       }
+
+       buf = cal_buf + addr;
+       if (addr == sysfs_finfo->af_inf_addr || addr == sysfs_finfo->af_macro_addr) {
+               data3 = *((u16 *)buf) / 2;
+               ret = fimc_is_comp_single_write(core, data2, data3);
+       } else {
+               if (addr == sysfs_finfo->wcoefficient1_addr) {
+                       if (companion_coef_isvalid) {
+                               for (i = 0; i < data_size; i += 2) {
+                                       data3 = (*(buf + i + 1) << 8) | (*(buf + i));
+                                       ret = fimc_is_comp_single_write(core, data2, data3);
+                                       if (ret) {
+                                               err("fimc_is_comp_i2c_setf_write() fail");
+                                               break;
+                                       }
+                                       data2 += 2;
+                               }
+                       } else {
+                               ret = fimc_is_comp_single_write(core, data2, 0x0203);
+                               ret |= fimc_is_comp_single_write(core, data2 + 2, 0xB902);
+                               ret |= fimc_is_comp_single_write(core, data2 + 4, 0xA903);
+                               ret |= fimc_is_comp_single_write(core, data2 + 6, 0x2900);
+                               ret |= fimc_is_comp_single_write(core, data2 + 8, 0x4900);
+                               if (ret) {
+                                       err("fimc_is_comp_i2c_setf_write() fail");
+                               }
+                       }
+               } else {
+                       if (companion_lsc_isvalid) {
+                               j = data_size - 1;
+                               for (i = 0; i < data_size; i += 2) {
+                                       data3 = (*(buf + j) << 8) | (*(buf + j - 1));
+                                       ret = fimc_is_comp_single_write(core, data2, data3);
+                                       if (ret) {
+                                               err("fimc_is_comp_i2c_setf_write() fail");
+                                               break;
+                                       }
+                                       data2 += 2;
+                                       j -= 2;
+                               }
+                       } else {
+                               ret = fimc_is_comp_single_write(core, data2, data3);
+                               if (ret) {
+                                       err("fimc_is_comp_i2c_setf_write() fail");
+                               }
+                               if (data4 != 0xFFFF) {
+                                       data2 += 2;
+                                       ret = fimc_is_comp_single_write(core, data2, data4);
+                                       if (ret) {
+                                               err("fimc_is_comp_i2c_setf_write() fail");
+                                       }
+                               }
+                       }
+               }
+       }
+//     ret = fimc_is_comp_read_i2c_cal(core, addr);
+       return ret;
+}
+
+int fimc_is_power_binning(struct fimc_is_core *core)
+{
+       int ret = 0;
+       int err_check = 0, vout_sel = 0;
+       u16 read_value = 0x80;
+       int vout = 0;
+       char buf[2]={0,};
+       loff_t pos = 0;
+       char *dcdc_name;
+       struct dcdc_power *dcdc = &core->companion_dcdc;
+
+       if (DCDC_VENDOR_NONE == dcdc->type) {
+               pr_err("%s: warning, DCDC power not exist\n", __func__);
+               return -ENODEV;
+       } else {
+               dcdc_name = (DCDC_VENDOR_FAN53555 == dcdc->type) ? "FAN" :
+                               (DCDC_VENDOR_NCP6335B == dcdc->type) ? "NCP" : "Unkknown";
+       }
+
+       /*read BIN_INFO 0x5000 500C*/
+#if 0
+       ret = fimc_is_comp_single_write(core, 0x602C, 0x5000);
+               if (ret)
+                       err("fimc_is_comp_i2c_setf_write() fail");
+       ret = fimc_is_comp_single_write(core, 0x602E, 0x500C);
+               if (ret)
+                       err("fimc_is_comp_i2c_setf_write() fail");
+#endif
+
+       ret = read_data_from_file(FIMC_IS_ISP_CV, buf, 1, &pos);
+       if(ret > 0) {
+               if (kstrtoint(buf, 10, &vout_sel))
+                       pr_err("%s: error, convert fail\n", __func__);
+
+               vout = dcdc->get_vout_val(vout_sel);
+               ret = dcdc->set_vout(dcdc->client, vout);
+               if (ret < 0 )
+                       pr_err("%s: error, dcdc set_vout(%d). sel %d\n", __func__, ret, vout_sel);
+
+               pr_info("[%s::%d][BIN_INFO::%s, sel %d] read path(%s), DCDC %s\n",
+                               __FUNCTION__, __LINE__, buf, vout_sel, FIMC_IS_ISP_CV, dcdc_name);
+               return vout_sel;
+       }
+
+       ret = fimc_is_comp_spi_single_write(core->spi1, 0x642C, 0x5000);
+       if (ret) {
+               err_check = 1;
+               err("spi_single_write() fail");
+       }
+
+       ret = fimc_is_comp_spi_single_write(core->spi1, 0x642E, 0x500C);
+       if (ret) {
+               err_check = 1;
+               err("spi_single_write() fail");
+       }
+
+       ret = fimc_is_comp_single_read(core, 0x6F12, &read_value, 2);
+       if (ret) {
+               err_check = 1;
+               err("fimc_is_comp_single_read() fail");
+       }
+
+       pr_info("[%s::%d][BIN_INFO::0x%04x]\n", __FUNCTION__, __LINE__, read_value);
+
+       if (read_value & 0x3F) {
+               if (read_value & (1<<CC_BIN6)) {
+                       buf[0]='6';
+               } else if (read_value & (1<<CC_BIN5)) {
+                       buf[0]='5';
+               } else if (read_value & (1<<CC_BIN4)) {
+                       buf[0]='4';
+               } else if (read_value & (1<<CC_BIN3)) {
+                       buf[0]='3';
+               } else if (read_value & (1<<CC_BIN2)) {
+                       buf[0]='2';
+               } else if (read_value & (1<<CC_BIN1)) {
+                       buf[0]='1';
+               } else {
+                       buf[0]='6';
+               }
+       } else {
+               buf[0]='6';
+               err_check = 1;
+       }
+       if (kstrtoint(buf, 10, &vout_sel))
+               pr_err("%s: error, convert fail\n", __func__);
+
+       vout = dcdc->get_vout_val(vout_sel);
+       ret = dcdc->set_vout(dcdc->client, vout);
+       if (ret < 0)
+               pr_err("%s: error, dcdc set_vout(%d), sel %d\n", __func__, ret, vout_sel);
+
+       if (err_check == 0) {
+               ret = write_data_to_file(FIMC_IS_ISP_CV, buf, 1, &pos);
+               if (ret < 0)
+                       pr_err("bin_info_file_write() fail(%s)",buf);
+       }
+
+       pr_info("[%s::%d][BIN_INFO::0x%04x] buf(%s) write. sel %d, DCDC %s\n",
+                       __FUNCTION__, __LINE__, read_value,buf, vout_sel, dcdc_name);
+
+       return vout_sel;
+}
+
+int fimc_is_comp_is_valid(struct fimc_is_core *core)
+{
+       int ret = 0;
+       u16 companion_id = 0, read_addr = 0;
+
+       if (!core->spi1) {
+               pr_info("spi1 device is not available");
+               goto exit;
+       }
+
+       /* check validation(Read data must be 0x73C1) */
+       read_addr = 0x0;
+       fimc_is_comp_single_read(core, read_addr, &companion_id, 2);
+       pr_info("Companion vaildation: 0x%04x\n", companion_id);
+#if 0
+#if defined(CONFIG_SOC_EXYNOS5430)
+       if (companion_id != COMP_MAGIC_NUMBER)
+               ret = -EINVAL;
+#endif
+#endif
+exit:
+       return ret;
+}
+
+int fimc_is_comp_read_ver(struct fimc_is_core *core)
+{
+       int ret = 0;
+#if 0
+       u16 read_addr;
+#endif
+
+       if (!core->spi1) {
+               pr_info("spi1 device is not available");
+               goto exit;
+       }
+
+       /* check validation(Read data must be 0x73C1) */
+#if 0
+       read_addr = 0x02;
+       fimc_is_comp_single_read(core, read_addr, &companion_ver, 2);
+#else
+       companion_ver = 0x00B0;
+       pr_info("Default Companion Version is 0x00B0(EVT1)\n");
+#endif
+
+       if (companion_ver == 0x00A0) {
+               pr_info("Companion version: 0x%04x\n", companion_ver);
+               ret = fimc_is_comp_single_write(core, 0x0256, 0x0001);
+       } else if (companion_ver == 0x00B0) {
+               pr_info("Companion version: 0x%04x\n", companion_ver);
+               ret = fimc_is_comp_single_write(core, 0x0122, 0x0001);
+       }
+       if (ret)
+               err("fimc_is_comp_read_ver() fail");
+
+exit:
+       return ret;
+}
+
+u8 fimc_is_comp_is_compare_ver(struct fimc_is_core *core)
+{
+       u8 ret = 0;
+       u32 from_ver = 0, def_ver = 0;
+       char *cal_buf;
+       char ver[3] = {'V', '0', '0'};
+
+       fimc_is_sec_get_cal_buf(&cal_buf);
+
+       if (!core->spi1) {
+               pr_info("spi1 device is not available");
+               goto exit;
+       }
+
+       def_ver = ver[0] << 16 | ver[1] << 8 | ver[2];
+       from_ver = cal_buf[96] << 16 | cal_buf[97] << 8 | cal_buf[98];
+       if (from_ver == def_ver) {
+               return cal_buf[99];
+       } else {
+               pr_err("FROM core version is invalid. version is %c%c%c%c\n", cal_buf[96], cal_buf[97], cal_buf[98], cal_buf[99]);
+               return 0;
+       }
+exit:
+       return ret;
+}
+
+int fimc_is_comp_loadcal(struct fimc_is_core *core)
+{
+       int ret = 0;
+       struct fimc_is_from_info *sysfs_finfo;
+       bool pdaf_valid = false;
+       int retry_count = 3;
+
+       if (!crc32_c1_check) {
+               pr_debug("CRC check fail.Do not apply cal data.");
+               return 0;
+       }
+
+       if (!core->spi1) {
+               pr_debug("spi1 device is not available");
+               goto p_err;
+       }
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+retry:
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->lsc_i0_gain_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->lsc_i0_gain_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->lsc_j0_gain_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail",sysfs_finfo->lsc_j0_gain_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->lsc_a_gain_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->lsc_a_gain_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->lsc_k4_gain_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->lsc_k4_gain_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->lsc_scale_gain_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->lsc_scale_gain_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->wcoefficient1_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->wcoefficient1_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+       }
+#if 0
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->af_inf_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->af_inf_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+               ret = fimc_is_comp_load_i2c_cal(core, sysfs_finfo->af_macro_addr);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(0x%04x) fail", sysfs_finfo->af_macro_addr);
+                       goto p_err;
+               }
+               usleep_range(1000, 1000);
+       }
+#endif
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               if (companion_lsc_isvalid) {
+                       ret = fimc_is_comp_load_cal(core, COMP_LSC);
+                       if (ret) {
+                               err("fimc_is_comp_load_binary(%s) fail", COMP_LSC);
+                               goto p_err;
+                       }
+                       pr_info("LSC from FROM loaded");
+               }
+#ifdef USE_DEFAULT_CAL
+               else {
+                       ret = fimc_is_comp_load_binary(core, COMP_DEFAULT_LSC);
+                       if (ret) {
+                               err("fimc_is_comp_load_binary(%s) fail", COMP_DEFAULT_LSC);
+                               goto p_err;
+                       }
+                       pr_info("Default LSC loaded");
+               }
+#endif
+               usleep_range(1000, 1000);
+       } else {
+               pr_info("Did not load LSC cal data");
+       }
+       /*Workaround : If FROM has ver.V003, Skip PDAF Cal loading to companion.*/
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               ret = fimc_is_comp_load_cal(core, COMP_PDAF);
+               if (ret) {
+                       err("fimc_is_comp_load_binary(%s) fail", COMP_PDAF);
+                       goto p_err;
+               }
+               pdaf_valid = true;
+               usleep_range(1000, 1000);
+       }
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               if (companion_coef_isvalid) {
+                       ret = fimc_is_comp_load_cal(core, COMP_COEF_CAL);
+                       if (ret) {
+                               err("fimc_is_comp_load_binary(%s) fail", COMP_COEF_CAL);
+                               goto p_err;
+                       }
+                       pr_info("COEF from FROM loaded");
+               }
+#ifdef USE_DEFAULT_CAL
+               else {
+                       ret = fimc_is_comp_load_binary(core, COMP_DEFAULT_COEF);
+                       if (ret) {
+                               err("fimc_is_comp_load_binary(%s) fail", COMP_DEFAULT_COEF);
+                               goto p_err;
+                       }
+                       pr_info("Default COEF loaded");
+               }
+#endif
+               usleep_range(1000, 1000);
+       } else {
+               pr_info("Did not load COEF cal data");
+       }
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               ret = fimc_is_comp_check_crc32(core, COMP_LSC);
+               if (pdaf_valid)
+                       ret |= fimc_is_comp_check_crc32(core, COMP_PDAF);
+               ret |= fimc_is_comp_check_crc32(core, COMP_COEF_CAL);
+               ret |= fimc_is_comp_check_crc32(core, "coef2");
+               ret |= fimc_is_comp_check_crc32(core, "coef3");
+               ret |= fimc_is_comp_check_crc32(core, "coef4");
+               ret |= fimc_is_comp_check_crc32(core, "coef5");
+               ret |= fimc_is_comp_check_crc32(core, "coef6");
+               if ((ret < 0) && (retry_count > 0)) {
+                       retry_count--;
+                       goto retry;
+               }
+       }
+       usleep_range(5000, 5000);
+p_err:
+       return 0;
+}
+
+int fimc_is_comp_loadfirm(struct fimc_is_core *core)
+{
+       int ret = 0;
+       int retry_count = 3;
+       struct fimc_is_from_info *sysfs_finfo;
+
+       if (!core->spi1) {
+               err("spi1 device is not available");
+               goto p_err;
+       }
+
+       ret = fimc_is_comp_read_ver(core);
+       if (ret) {
+               err("fimc_is_comp_read_ver fail");
+               goto p_err;
+       }
+       msleep(1);
+
+retry:
+       ret = fimc_is_comp_single_write(core, 0x6042, 0x0001);
+       if (ret) {
+               err("fimc_is_comp_i2c_setf_write() fail");
+       }
+
+       ret = fimc_is_comp_single_write(core, 0x6428, 0x0000);
+       if (ret) {
+               err("fimc_is_comp_i2c_setf_write() fail");
+       }
+
+       ret = fimc_is_comp_single_write(core, 0x642A, 0x0000);
+       if (ret) {
+               err("fimc_is_comp_i2c_setf_write() fail");
+       }
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+       if (companion_ver == 0x00A0)
+               ret = fimc_is_comp_load_binary(core, COMP_FW_EVT0);
+       else if (companion_ver == 0x00B0)
+               ret = fimc_is_comp_load_binary(core, sysfs_finfo->load_c1_fw_name);
+       if (ret) {
+               err("fimc_is_comp_load_firmware fail");
+               goto p_err;
+       }
+
+       ret = fimc_is_comp_single_write(core, 0x6014, 0x0001);
+       if (ret) {
+               err("fimc_is_comp_i2c_setf_write() fail");
+       }
+
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               if (companion_ver == 0x00A0)
+                       ret = fimc_is_comp_check_crc32(core, COMP_FW_EVT0);
+               else if (companion_ver == 0x00B0)
+                       ret = fimc_is_comp_check_crc32(core, COMP_FW_EVT1);
+               if ((ret < 0) && (retry_count > 0)) {
+                       retry_count--;
+                       goto retry;
+               }
+       }
+       usleep_range(5000, 5000);
+p_err:
+       return ret;
+}
+
+int fimc_is_comp_loadsetf(struct fimc_is_core *core)
+{
+       int ret = 0;
+       struct fimc_is_from_info *sysfs_finfo;
+
+       if (!core->spi1) {
+               pr_debug("spi1 device is not available");
+               goto p_err;
+       }
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+       ret = fimc_is_comp_load_binary(core, sysfs_finfo->load_c1_mastersetf_name);
+       if (ret) {
+               err("fimc_is_comp_load_binary(%s) fail", sysfs_finfo->load_c1_mastersetf_name);
+               goto p_err;
+       }
+
+       ret = fimc_is_comp_load_binary(core, sysfs_finfo->load_c1_modesetf_name);
+       if (ret) {
+               err("fimc_is_comp_load_binary(%s) fail", sysfs_finfo->load_c1_modesetf_name);
+               goto p_err;
+       }
+       usleep_range(5000, 5000);
+       /*Stream on concord*/
+       ret = fimc_is_comp_single_write(core, 0x6800, 0x0001);
+       if (ret) {
+               err("fimc_is_comp_i2c_setf_write() fail");
+       }
+p_err:
+       return ret;
+}
+
+void fimc_is_s_int_comb_isp(struct fimc_is_core *core,bool on, u32 ch)
+{
+        u32 cfg = ~0x0;
+
+        if(on) {
+                cfg &= ~ch;
+                writel(cfg, core->regs + INTMR2);
+        } else {
+                cfg = 0xFFFFFFFF;
+                writel(cfg, core->regs + INTMR2);
+        }
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-companion.h b/drivers/media/platform/exynos/fimc-is/fimc-is-companion.h
new file mode 100644 (file)
index 0000000..3de736d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+#ifndef FIMC_IS_COMPANION_H
+#define FIMC_IS_COMPANION_H
+
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-companion_address.h"
+#include "fimc-is-interface.h"
+
+#define CRC_RETRY_COUNT         40
+
+#define FIMC_IS_ISP_CV "/data/ISP_CV"
+
+enum dcdc_vendor{
+       DCDC_VENDOR_NONE = 0,
+       DCDC_VENDOR_FAN53555,
+       DCDC_VENDOR_NCP6335B,
+       DCDC_VENDOR_MAX,
+};
+
+struct dcdc_power {
+       enum dcdc_vendor type;
+       struct i2c_client *client;
+
+       /* Get i2c register value to set vout of dcdc regulator */
+       int (*get_vout_val)(int);
+
+       /* Get voltage name of vout as string */
+       const char *(*get_vout_str)(int);
+
+       /* Set dcdc vout with i2c register value */
+       int (*set_vout)(struct i2c_client *client, int vout);
+};
+
+int fimc_is_comp_is_valid(struct fimc_is_core *core);
+int fimc_is_comp_loadfirm(struct fimc_is_core *core);
+int fimc_is_comp_loadsetf(struct fimc_is_core *core);
+int fimc_is_comp_loadcal(struct fimc_is_core *core);
+u8 fimc_is_comp_is_compare_ver(struct fimc_is_core *core);
+int fimc_is_power_binning(struct fimc_is_core *core);
+void fimc_is_s_int_comb_isp(struct fimc_is_core *core,bool on, u32 ch);
+
+#endif /* FIMC_IS_COMPANION_H */
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-companion_address.h b/drivers/media/platform/exynos/fimc-is/fimc-is-companion_address.h
new file mode 100644 (file)
index 0000000..a16bfad
--- /dev/null
@@ -0,0 +1,26 @@
+/*2P2 Address*/
+#define        MEM_GRAS_B_2P2                                          0x2001A000      //      0x00000000      0x1A00  0x2001A000      0x0020
+#define        MEM_AF_10_1_2P2                                         0x2000B900      //      0x00000000      0x0200  0x2000B900      0x0020
+#define        MEM_XTALK_10_2P2                                                0x20010000      //      0x00000000      0x0FC0  0x20010000      0x0020
+#define        grasTuning_uParabolicCenterX_2P2                                0x400008A8      //          0x0A68      0x0002  0x200008A8      0x0002
+#define        grasTuning_uParabolicCenterY_2P2                                0x400008AA      //          0x05DC      0x0002  0x200008AA      0x0002
+#define        grasTuning_uBiQuadFactorA_2P2                           0x400008B4      //      0x00008000      0x0004  0x200008B4      0x0003
+#define        grasTuning_uBiQuadFactorB_2P2                           0x400008B8      //      0x00004000      0x0004  0x200008B8      0x0003
+#define        grasTuning_uBiQuadScaleShiftAdder_2P2                   0x400008BC      //          0x0000      0x0002  0x200008BC      0x0002
+#define        xtalkTuningParams_wcr_2P2                                       0x40000EA0      //          0xFFF7      0x0002  0x20000EA0      0x0002
+#define        grasTuning_actuatorPositionToShadingPowerLut_0_2P2              0x40000984      //          0x0032      0x0002  0x2000097C      0x0002
+#define        grasTuning_actuatorPositionToShadingPowerLut_9_2P2              0x40000996      //          0x00CF      0x0002  0x2000098E      0x0002
+
+/*IMX240 Address*/
+#define        MEM_GRAS_B_IMX240                                               0x2001A000      //      0x00000000      0x1A00  0x2001A000      0x0020
+#define        MEM_AF_10_1_IMX240                                              0x2000B900      //      0x00000000      0x0200  0x2000B900      0x0020
+#define        MEM_XTALK_10_IMX240                                             0x20010000      //      0x00000000      0x0FC0  0x20010000      0x0020
+#define        grasTuning_uParabolicCenterX_IMX240                             0x400008A8      //          0x0A68      0x0002  0x200008A8      0x0002
+#define        grasTuning_uParabolicCenterY_IMX240                             0x400008AA      //          0x05DC      0x0002  0x200008AA      0x0002
+#define        grasTuning_uBiQuadFactorA_IMX240                                0x400008B4      //      0x00008000      0x0004  0x200008B4      0x0003
+#define        grasTuning_uBiQuadFactorB_IMX240                                0x400008B8      //      0x00004000      0x0004  0x200008B8      0x0003
+#define        grasTuning_uBiQuadScaleShiftAdder_IMX240                        0x400008BC      //          0x0000      0x0002  0x200008BC      0x0002
+#define        xtalkTuningParams_wcr_IMX240                                    0x40000EC0      //          0xFFF7      0x0002  0x20000EC0      0x0002
+#define        grasTuning_actuatorPositionToShadingPowerLut_0_IMX240           0x40000984      //          0x0032      0x0002  0x2000097C      0x0002
+#define        grasTuning_actuatorPositionToShadingPowerLut_9_IMX240           0x40000996      //          0x00CF      0x0002  0x2000098E      0x0002
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-config.h b/drivers/media/platform/exynos/fimc-is/fimc-is-config.h
new file mode 100644 (file)
index 0000000..1e83b21
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_CONFIG_H
+#define FIMC_IS_CONFIG_H
+
+/* configuration - default post processing */
+#define ENABLE_SETFILE
+#define ENABLE_DRC
+/* #define ENABLE_ODC */
+/* #define ENABLE_VDIS */
+/* #define ENABLE_TDNR */
+#define ENABLE_FD
+#define ENABLE_CLOCK_GATE
+/* #define HAS_FW_CLOCK_GATE */
+/* #define ENABLE_CACHE */
+#define ENABLE_FULL_BYPASS
+#define ENABLE_FAST_SHOT
+#define USE_OWN_FAULT_HANDLER
+/* #define ENABLE_MIF_400 */
+#define ENABLE_DTP
+#define USE_ION_ALLOC
+
+#define CSI_VERSION_0000_0000  0x0
+#define CSI_VERSION_0310_0100  0x03100100
+
+#define FIMC_IS_VERSION_000    0x0
+#define FIMC_IS_VERSION_250    0x250
+
+#if defined(CONFIG_PM_DEVFREQ)
+#define ENABLE_DVFS
+#define START_DVFS_LEVEL FIMC_IS_SN_MAX
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5430)
+#undef ENABLE_SETFILE
+#define SUPPORTED_IS_CMD_VER   132
+#define TARGET_SPI_CH_FOR_PERI 0
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0000_0000
+#define FIMC_IS_VERSION                FIMC_IS_VERSION_000
+#define HAS_FW_CLOCK_GATE
+
+#elif defined(CONFIG_SOC_EXYNOS5433)
+#define SUPPORTED_IS_CMD_VER   132
+#define TARGET_SPI_CH_FOR_PERI 0
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0000_0000
+#define FIMC_IS_VERSION        FIMC_IS_VERSION_000
+#define HAS_FW_CLOCK_GATE
+#define MAX_ZOOM_LEVEL 8
+
+#elif defined(CONFIG_SOC_EXYNOS5422)
+#undef ENABLE_SETFILE
+#define SUPPORTED_IS_CMD_VER   132
+#define TARGET_SPI_CH_FOR_PERI 0
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0000_0000
+#define FIMC_IS_VERSION                FIMC_IS_VERSION_000
+
+#elif defined(CONFIG_SOC_EXYNOS5260)
+#undef ENABLE_SETFILE
+#undef ENABLE_DRC
+#undef ENABLE_FULL_BYPASS
+#define SUPPORTED_EARLY_BUF_DONE
+#define SUPPORTED_IS_CMD_VER   131
+#define TARGET_SPI_CH_FOR_PERI 1
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0310_0100
+#define FIMC_IS_VERSION                FIMC_IS_VERSION_000
+#define SCALER_PARALLEL_MODE
+
+#elif defined(CONFIG_SOC_EXYNOS4415)
+#undef ENABLE_SETFILE
+#undef ENABLE_DRC
+#define SUPPORTED_IS_CMD_VER   132
+#define TARGET_SPI_CH_FOR_PERI 1
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0310_0100
+#define FIMC_IS_VERSION                FIMC_IS_VERSION_250
+
+#elif defined(CONFIG_SOC_EXYNOS3470)
+#undef ENABLE_SETFILE
+#undef ENABLE_DRC
+#undef ENABLE_FULL_BYPASS
+#define SUPPORTED_EARLY_BUF_DONE
+#define ENABLE_IFLAG
+#define SUPPORTED_IS_CMD_VER   131
+#define TARGET_SPI_CH_FOR_PERI 1
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0000_0000
+#define FIMC_IS_VERSION                FIMC_IS_VERSION_000
+#define SCALER_PARALLEL_MODE
+
+#elif defined(CONFIG_SOC_EXYNOS3472)
+#undef ENABLE_SETFILE
+#undef ENABLE_DRC
+#undef ENABLE_DVFS
+#undef ENABLE_FULL_BYPASS
+#define ENABLE_IFLAG
+#define SUPPORTED_IS_CMD_VER   131
+#define TARGET_SPI_CH_FOR_PERI 1
+#define FIMC_IS_CSI_VERSION    CSI_VERSION_0310_0100
+#define FIMC_IS_VERSION                FIMC_IS_VERSION_000
+
+#else
+#error fimc-is driver can NOT support this platform
+
+#endif
+
+#if !defined(MAX_ZOOM_LEVEL)
+/* default max zoom lv is 4 */
+#define MAX_ZOOM_LEVEL 4
+#endif
+
+/* notifier for MIF throttling */
+#if defined(CONFIG_ARM_EXYNOS5433_BUS_DEVFREQ) && defined(CONFIG_CPU_THERMAL_IPA)
+#define EXYNOS_MIF_ADD_NOTIFIER(nb) \
+       exynos_mif_add_notifier(nb)
+#else
+#define EXYNOS_MIF_ADD_NOTIFIER(nb)
+#endif
+
+#if defined(CONFIG_ARM_EXYNOS4415_BUS_DEVFREQ)
+#define CONFIG_FIMC_IS_BUS_DEVFREQ
+#endif
+#if defined(CONFIG_ARM_EXYNOS5260_BUS_DEVFREQ)
+#define CONFIG_FIMC_IS_BUS_DEVFREQ
+#endif
+#if defined(CONFIG_ARM_EXYNOS3470_BUS_DEVFREQ)
+#define CONFIG_FIMC_IS_BUS_DEVFREQ
+#endif
+#if defined(CONFIG_ARM_EXYNOS5422_BUS_DEVFREQ)
+#define CONFIG_FIMC_IS_BUS_DEVFREQ
+#endif
+#if defined(CONFIG_ARM_EXYNOS5430_BUS_DEVFREQ)
+#define CONFIG_FIMC_IS_BUS_DEVFREQ
+#endif
+#if defined(CONFIG_ARM_EXYNOS5433_BUS_DEVFREQ)
+#define CONFIG_FIMC_IS_BUS_DEVFREQ
+#endif
+
+/*
+ * -----------------------------------------------------------------------------
+ * Debug Message Configuration
+ * -----------------------------------------------------------------------------
+ */
+
+/* #define DEBUG */
+#define DBG_VIDEO
+#define DBG_DEVICE
+#define DBG_PER_FRAME
+/* #define DBG_STREAMING */
+#define DEBUG_INSTANCE 0xF
+#define BUG_ON_ENABLE
+/* #define FIXED_FPS_DEBUG */
+#define FIXED_FPS_VALUE 10
+/* #define DBG_CSIISR */
+/* #define DBG_FLITEISR */
+#define FW_DEBUG
+#define RESERVED_MEM
+/* #define SCALER_CROP_DZOOM */
+/* #define USE_ADVANCED_DZOOM */
+/* #define TASKLET_MSG */
+/* #define PRINT_CAPABILITY */
+/* #define PRINT_BUFADDR */
+/* #define PRINT_DZOOM */
+/* #define PRINT_PARAM */
+/* #define PRINT_I2CCMD */
+#define ISDRV_VERSION 244
+
+#if (defined(BAYER_CROP_DZOOM) && defined(SCALER_CROP_DZOOM))
+#error BAYER_CROP_DZOOM and SCALER_CROP_DZOOM can''t be enable together
+#endif
+
+/*
+ * driver version extension
+ */
+#ifdef ENABLE_CLOCK_GATE
+#define get_drv_clock_gate() 0x1
+#else
+#define get_drv_clock_gate() 0x0
+#endif
+#ifdef ENABLE_DVFS
+#define get_drv_dvfs() 0x2
+#else
+#define get_drv_dvfs() 0x0
+#endif
+
+#define GET_3AA_ID(video) ((video->id < 14) ? 0 : 1)
+#define GET_3AAC_ID(video) ((video->id < FIMC_IS_VIDEO_3A1_NUM) ? 0 : 1)
+
+/* sync log with HAL, FW */
+#define log_sync(sync_id) \
+       pr_info("[@]FIMC_IS_SYNC %d\n", sync_id)
+
+#ifdef err
+#undef err
+#endif
+#define err(fmt, args...) \
+       pr_err("[@][ERR]%s:%d: " fmt "\n", __func__, __LINE__, ##args)
+
+/* multi-stream */
+#define merr(fmt, object, args...) \
+       pr_err("[@][%d][ERR]%s:%d: " fmt "\n", object->instance, __func__, __LINE__, ##args)
+
+/* multi-stream & runtime error */
+#define mrerr(fmt, object, frame, args...) \
+       pr_err("[@][%d:F%d][ERR]%s:%d: " fmt "\n", object->instance, frame->fcount, __func__, __LINE__, ##args)
+
+/* multi-stream & group error */
+#define mgerr(fmt, object, group, args...) \
+        pr_err("[@][%d][GP%d][ERR]%s:%d:" fmt "\n", object->instance, group->id, __func__, __LINE__, ##args)
+
+#ifdef warn
+#undef warn
+#endif
+#define warn(fmt, args...) \
+       pr_warning("[@][WRN] " fmt "\n", ##args)
+
+#define mwarn(fmt, this, args...) \
+       pr_warning("[@][%d][WRN] " fmt "\n", this->instance, ##args)
+
+#define mgwarn(fmt, object, group, args...) \
+        pr_warning("[@][%d][GP%d][WRN]" fmt "\n", object->instance, group->id, ##args)
+
+#define info(fmt, args...) \
+       pr_info("[@]" fmt, ##args)
+
+#define minfo(fmt, object, args...) \
+       pr_info("[@][%d]" fmt, object->instance, ##args)
+
+#define mrinfo(fmt, object, frame, args...) \
+       pr_info("[@][%d:F%d]" fmt, object->instance, frame->fcount,  ##args)
+
+#define mrdbg(fmt, object, frame, args...) \
+       printk(KERN_DEBUG "[@][%d:F%d]" fmt, object->instance, frame->fcount,  ##args)
+
+#define mdbg_common(prefix, fmt, instance, args...)                            \
+       do {                                                                    \
+               if ((1<<(instance)) & DEBUG_INSTANCE)                           \
+                       pr_info("[@]" prefix fmt, instance, ##args);            \
+       } while (0)
+
+#if (defined(DEBUG) && defined(DBG_VIDEO))
+#define dbg(fmt, args...)
+
+#define dbg_warning(fmt, args...) \
+       printk(KERN_INFO "%s[WAR] Warning! " fmt, __func__, ##args)
+
+/* debug message for video node */
+#define mdbgv_vid(fmt, args...) \
+       pr_info("[@][VID:V] " fmt, ##args)
+
+#define mdbgv_sensor(fmt, this, args...) \
+       mdbg_common("[%d][SS%d:V] ", fmt, this->video->id, this->instance, ##args)
+
+#define mdbgv_3aa(fmt, this, args...) \
+       mdbg_common("[%d][3A%d:V] ", fmt, GET_3AA_ID(this->video), this->instance, ##args)
+
+#define mdbgv_3aac(fmt, this, args...) \
+       mdbg_common("[%d][3A%dC:V] ", fmt, GET_3AAC_ID(this->video), this->instance, ##args)
+
+#define dbg_isp(fmt, args...) \
+       printk(KERN_INFO "[ISP] " fmt, ##args)
+
+#define mdbgv_isp(fmt, this, args...) \
+       mdbg_common("[%d][ISP:V] ", fmt, this->instance, ##args)
+
+#define dbg_scp(fmt, args...) \
+       printk(KERN_INFO "[SCP] " fmt, ##args)
+
+#define mdbgv_scp(fmt, this, args...) \
+       mdbg_common("[%d][SCP:V] ", fmt, this->instance, ##args)
+
+#define dbg_scc(fmt, args...) \
+       printk(KERN_INFO "[SCC] " fmt, ##args)
+
+#define mdbgv_scc(fmt, this, args...) \
+       mdbg_common("[%d][SCC:V] ", fmt, this->instance, ##args)
+
+#define dbg_vdisc(fmt, args...) \
+       printk(KERN_INFO "[VDC] " fmt, ##args)
+
+#define mdbgv_vdc(fmt, this, args...) \
+       mdbg_common("[%d][VDC:V] ", fmt, this->instance, ##args)
+
+#define dbg_vdiso(fmt, args...) \
+       printk(KERN_INFO "[VDO] " fmt, ##args)
+
+#define mdbgv_vdo(fmt, this, args...) \
+       mdbg_common("[%d][VDO:V] ", fmt, this->instance, ##args)
+#else
+#define dbg(fmt, args...)
+
+/* debug message for video node */
+#define mdbgv_vid(fmt, this, args...)
+#define dbg_sensor(fmt, args...)
+#define mdbgv_sensor(fmt, this, args...)
+#define mdbgv_3aa(fmt, this, args...)
+#define mdbgv_3aac(fmt, this, args...)
+#define dbg_isp(fmt, args...)
+#define mdbgv_isp(fmt, this, args...)
+#define dbg_scp(fmt, args...)
+#define mdbgv_scp(fmt, this, args...)
+#define dbg_scc(fmt, args...)
+#define mdbgv_scc(fmt, this, args...)
+#define dbg_vdisc(fmt, args...)
+#define mdbgv_vdc(fmt, this, args...)
+#define dbg_vdiso(fmt, args...)
+#define mdbgv_vdo(fmt, this, args...)
+#endif
+
+#if (defined(DEBUG) && defined(DBG_DEVICE))
+/* debug message for device */
+#define mdbgd_sensor(fmt, this, args...) \
+       mdbg_common("[%d][SEN:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_front(fmt, this, args...) \
+       mdbg_common("[%d][FRT:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_back(fmt, this, args...) \
+       mdbg_common("[%d][BAK:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_3a0(fmt, this, args...) \
+       mdbg_common("[%d][3A0:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_3a1(fmt, this, args...) \
+       mdbg_common("[%d][3A1:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_isp(fmt, this, args...) \
+       mdbg_common("[%d][ISP:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_ischain(fmt, this, args...) \
+       mdbg_common("[%d][ISC:D] ", fmt, this->instance, ##args)
+
+#define mdbgd_group(fmt, group, args...) \
+       mdbg_common("[%d][GP%d:D] ", fmt, group->device->instance, group->id, ##args)
+
+#define dbg_core(fmt, args...) \
+       pr_info("[@][COR] " fmt, ##args)
+#else
+/* debug message for device */
+#define mdbgd_sensor(fmt, this, args...)
+#define mdbgd_front(fmt, this, args...)
+#define mdbgd_back(fmt, this, args...)
+#define mdbgd_isp(fmt, this, args...)
+#define dbg_ischain(fmt, args...)
+#define mdbgd_ischain(fmt, this, args...)
+#define dbg_core(fmt, args...)
+#define dbg_interface(fmt, args...)
+#define dbg_frame(fmt, args...)
+#define mdbgd_group(fmt, group, args...)
+#endif
+
+#if (defined(DEBUG) && defined(DBG_STREAMING))
+#define dbg_interface(fmt, args...) \
+       pr_info("[@][ITF] " fmt, ##args)
+#define dbg_frame(fmt, args...) \
+       pr_info("[@][FRM] " fmt, ##args)
+#else
+#define dbg_interface(fmt, args...)
+#define dbg_frame(fmt, args...)
+#endif
+
+#if (defined(DEBUG) && defined(DBG_PER_FRAME))
+#define mdbg_pframe(fmt, object, frame, args...) \
+       pr_info("[@][%d:F%d]" fmt, object->instance, frame->fcount,  ##args)
+#else
+#define mdbg_pframe(fmt, object, frame, args...)
+#endif
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-core.c b/drivers/media/platform/exynos/fimc-is/fimc-is-core.c
new file mode 100644 (file)
index 0000000..e01672c
--- /dev/null
@@ -0,0 +1,2413 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <mach/regs-clock.h>
+#include <linux/pm_qos.h>
+#include <linux/bug.h>
+#include <linux/v4l2-mediabus.h>
+#include <mach/devfreq.h>
+#include <mach/bts.h>
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#endif
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-framemgr.h"
+#include "fimc-is-dt.h"
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-clk-gate.h"
+#include "fimc-is-dvfs.h"
+#include "fimc-is-fan53555.h"
+#include "fimc-is-ncp6335b.h"
+
+#include "sensor/fimc-is-device-2p2.h"
+#include "sensor/fimc-is-device-3h5.h"
+#include "sensor/fimc-is-device-3h7.h"
+#include "sensor/fimc-is-device-3h7_sunny.h"
+#include "sensor/fimc-is-device-3l2.h"
+#include "sensor/fimc-is-device-4e5.h"
+#include "sensor/fimc-is-device-6a3.h"
+#include "sensor/fimc-is-device-6b2.h"
+#include "sensor/fimc-is-device-8b1.h"
+#include "sensor/fimc-is-device-6d1.h"
+#include "sensor/fimc-is-device-imx134.h"
+#include "sensor/fimc-is-device-imx135.h"
+#include "sensor/fimc-is-device-imx175.h"
+#include "sensor/fimc-is-device-imx240.h"
+#include "sensor/fimc-is-device-imx219.h"
+#include "sensor/fimc-is-device-4h5.h"
+#include "sensor/fimc-is-device-3l2.h"
+#include "sensor/fimc-is-device-2p2.h"
+#include "sensor/fimc-is-device-2p2_12m.h"
+#include "sensor/fimc-is-device-2p3.h"
+#ifdef CONFIG_USE_VENDER_FEATURE
+#include "fimc-is-sec-define.h"
+#ifdef CONFIG_OIS_USE
+#include "fimc-is-device-ois.h"
+#endif
+#endif
+#ifdef CONFIG_AF_HOST_CONTROL
+#include "fimc-is-device-af.h"
+#endif
+
+#ifdef USE_OWN_FAULT_HANDLER
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+#include <linux/exynos_iovmm.h>
+#else
+#include <plat/sysmmu.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#define PM_QOS_CAM_THROUGHPUT  PM_QOS_RESERVED
+#endif
+
+struct fimc_is_from_info *sysfs_finfo = NULL;
+struct fimc_is_from_info *sysfs_pinfo = NULL;
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+struct class *camera_class = NULL;
+struct device *camera_front_dev;
+struct device *camera_rear_dev;
+#ifdef CONFIG_OIS_USE
+struct device *camera_ois_dev;
+#endif
+#endif
+
+struct device *fimc_is_dev = NULL;
+struct fimc_is_core *sysfs_core;
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+extern bool crc32_fw_check;
+extern bool crc32_check;
+extern bool crc32_check_factory;
+extern bool fw_version_crc_check;
+extern bool is_latest_cam_module;
+extern bool is_final_cam_module;
+#if defined(CONFIG_SOC_EXYNOS5433)
+extern bool is_right_prj_name;
+#endif
+#ifdef CONFIG_COMPANION_USE
+extern bool crc32_c1_fw_check;
+extern bool crc32_c1_check;
+extern bool crc32_c1_check_factory;
+#endif /* CONFIG_COMPANION_USE */
+#endif
+
+extern struct pm_qos_request exynos_isp_qos_int;
+extern struct pm_qos_request exynos_isp_qos_mem;
+extern struct pm_qos_request exynos_isp_qos_cam;
+extern struct pm_qos_request exynos_isp_qos_disp;
+
+extern int fimc_is_3a0_video_probe(void *data);
+extern int fimc_is_3a1_video_probe(void *data);
+extern int fimc_is_isp_video_probe(void *data);
+extern int fimc_is_scc_video_probe(void *data);
+extern int fimc_is_scp_video_probe(void *data);
+extern int fimc_is_vdc_video_probe(void *data);
+extern int fimc_is_vdo_video_probe(void *data);
+extern int fimc_is_3a0c_video_probe(void *data);
+extern int fimc_is_3a1c_video_probe(void *data);
+
+/* sysfs global variable for debug */
+struct fimc_is_sysfs_debug sysfs_debug;
+
+static int fimc_is_ischain_allocmem(struct fimc_is_core *this)
+{
+       int ret = 0;
+       void *fw_cookie;
+       size_t fw_size =
+#ifdef ENABLE_ODC
+                               SIZE_ODC_INTERNAL_BUF * NUM_ODC_INTERNAL_BUF +
+#endif
+#ifdef ENABLE_VDIS
+                               SIZE_DIS_INTERNAL_BUF * NUM_DIS_INTERNAL_BUF +
+#endif
+#ifdef ENABLE_TDNR
+                               SIZE_DNR_INTERNAL_BUF * NUM_DNR_INTERNAL_BUF +
+#endif
+                       FIMC_IS_A5_MEM_SIZE;
+
+       fw_size = PAGE_ALIGN(fw_size);
+       dbg_core("Allocating memory for FIMC-IS firmware.\n");
+
+       fw_cookie = vb2_ion_private_alloc(this->mem.alloc_ctx, fw_size, 1, 0);
+
+       if (IS_ERR(fw_cookie)) {
+               err("Allocating bitprocessor buffer failed");
+               fw_cookie = NULL;
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       ret = vb2_ion_dma_address(fw_cookie, &this->minfo.dvaddr);
+       if ((ret < 0) || (this->minfo.dvaddr  & FIMC_IS_FW_BASE_MASK)) {
+               err("The base memory is not aligned to 64MB.");
+               vb2_ion_private_free(fw_cookie);
+               this->minfo.dvaddr = 0;
+               fw_cookie = NULL;
+               ret = -EIO;
+               goto exit;
+       }
+       dbg_core("Device vaddr = %08x , size = %08x\n",
+               this->minfo.dvaddr, FIMC_IS_A5_MEM_SIZE);
+
+       this->minfo.kvaddr = (u32)vb2_ion_private_vaddr(fw_cookie);
+       if (IS_ERR((void *)this->minfo.kvaddr)) {
+               err("Bitprocessor memory remap failed");
+               vb2_ion_private_free(fw_cookie);
+               this->minfo.kvaddr = 0;
+               fw_cookie = NULL;
+               ret = -EIO;
+               goto exit;
+       }
+
+       vb2_ion_sync_for_device(fw_cookie, 0, fw_size, DMA_BIDIRECTIONAL);
+
+exit:
+       info("[COR] Device virtual for internal: %08x\n", this->minfo.kvaddr);
+       this->minfo.fw_cookie = fw_cookie;
+
+       return ret;
+}
+
+static int fimc_is_ishcain_initmem(struct fimc_is_core *this)
+{
+       int ret = 0;
+       u32 offset;
+
+       dbg_core("fimc_is_init_mem - ION\n");
+
+       ret = fimc_is_ischain_allocmem(this);
+       if (ret) {
+               err("Couldn't alloc for FIMC-IS firmware\n");
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       offset = FW_SHARED_OFFSET;
+       this->minfo.dvaddr_fshared = this->minfo.dvaddr + offset;
+       this->minfo.kvaddr_fshared = this->minfo.kvaddr + offset;
+
+       offset = FIMC_IS_A5_MEM_SIZE - FIMC_IS_REGION_SIZE;
+       this->minfo.dvaddr_region = this->minfo.dvaddr + offset;
+       this->minfo.kvaddr_region = this->minfo.kvaddr + offset;
+
+       offset = FIMC_IS_A5_MEM_SIZE;
+#ifdef ENABLE_ODC
+       this->minfo.dvaddr_odc = this->minfo.dvaddr + offset;
+       this->minfo.kvaddr_odc = this->minfo.kvaddr + offset;
+       offset += (SIZE_ODC_INTERNAL_BUF * NUM_ODC_INTERNAL_BUF);
+#else
+       this->minfo.dvaddr_odc = 0;
+       this->minfo.kvaddr_odc = 0;
+#endif
+
+#ifdef ENABLE_VDIS
+       this->minfo.dvaddr_dis = this->minfo.dvaddr + offset;
+       this->minfo.kvaddr_dis = this->minfo.kvaddr + offset;
+       offset += (SIZE_DIS_INTERNAL_BUF * NUM_DIS_INTERNAL_BUF);
+#else
+       this->minfo.dvaddr_dis = 0;
+       this->minfo.kvaddr_dis = 0;
+#endif
+
+#ifdef ENABLE_TDNR
+       this->minfo.dvaddr_3dnr = this->minfo.dvaddr + offset;
+       this->minfo.kvaddr_3dnr = this->minfo.kvaddr + offset;
+       offset += (SIZE_DNR_INTERNAL_BUF * NUM_DNR_INTERNAL_BUF);
+#else
+       this->minfo.dvaddr_3dnr = 0;
+       this->minfo.kvaddr_3dnr = 0;
+#endif
+
+       dbg_core("fimc_is_init_mem done\n");
+
+exit:
+       return ret;
+}
+
+#if defined(CONFIG_ARM_EXYNOS5433_BUS_DEVFREQ) && defined(CONFIG_CPU_THERMAL_IPA)
+static int fimc_is_mif_throttling_notifier(struct notifier_block *nb,
+               unsigned long val, void *v)
+{
+       struct fimc_is_core *core = NULL;
+       struct fimc_is_device_sensor *device = NULL;
+       int i;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is null");
+               goto exit;
+       }
+
+       for (i = 0; i < FIMC_IS_MAX_NODES; i++) {
+               if (test_bit(FIMC_IS_SENSOR_OPEN, &core->sensor[i].state)) {
+                       device = &core->sensor[i];
+                       break;
+               }
+       }
+
+       if (device && !test_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state))
+               /* Set DTP */
+               set_bit(FIMC_IS_MIF_THROTTLING_STOP, &device->force_stop);
+       else
+               err("any sensor is not opened");
+
+exit:
+       err("MIF: cause of mif_throttling, mif_qos is [%lu]!!!\n", val);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block exynos_fimc_is_mif_throttling_nb = {
+       .notifier_call = fimc_is_mif_throttling_notifier,
+};
+#endif
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+static ssize_t camera_front_sensorid_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct exynos_platform_fimc_is_sensor *sensor = dev_get_drvdata(dev);
+
+       dev_info(dev, "%s: E", __func__);
+
+       if (unlikely(!sensor)) {
+               dev_err(dev, "%s: sensor null\n", __func__);
+               return -EFAULT;
+       }
+
+       return sprintf(buf, "%d\n", sensor->sensor_id);
+}
+
+static ssize_t camera_rear_sensorid_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct exynos_platform_fimc_is_sensor *sensor = dev_get_drvdata(dev);
+
+       dev_info(dev, "%s: E", __func__);
+
+       if (unlikely(!sensor)) {
+               dev_err(dev, "%s: sensor null\n", __func__);
+               return -EFAULT;
+       }
+
+       return sprintf(buf, "%d\n", sensor->sensor_id);
+}
+
+static DEVICE_ATTR(front_sensorid, S_IRUGO, camera_front_sensorid_show, NULL);
+static DEVICE_ATTR(rear_sensorid, S_IRUGO, camera_rear_sensorid_show, NULL);
+
+int fimc_is_get_sensor_data(struct device *dev, char *maker, char *name, int position)
+{
+       struct exynos_platform_fimc_is_sensor *sensor = dev_get_drvdata(dev);
+       struct fimc_is_core *core;
+       struct fimc_is_device_sensor *device;
+       int i;
+
+       if (unlikely(!sensor)) {
+               dev_err(dev, "%s: sensor null\n", __func__);
+               return -EFAULT;
+       }
+
+       if (!fimc_is_dev) {
+               dev_err(dev, "%s: fimc_is_dev is not yet probed", __func__);
+               return -ENODEV;
+       }
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               dev_err(dev, "%s: core is NULL", __func__);
+               return -EINVAL;
+       }
+
+       if (position == SENSOR_POSITION_FRONT || position == SENSOR_POSITION_REAR) {
+               device = &core->sensor[position];
+       } else {
+               dev_err(dev, "%s: position value is wrong", __func__);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < atomic_read(&core->resourcemgr.rsccount_module); i++) {
+               if (sensor->sensor_id == device->module_enum[i].id) {
+                       if (maker != NULL)
+                               sprintf(maker, "%s", device->module_enum[i].sensor_maker ?
+                                               device->module_enum[i].sensor_maker : "UNKNOWN");
+                       if (name != NULL)
+                               sprintf(name, "%s", device->module_enum[i].sensor_name ?
+                                               device->module_enum[i].sensor_name : "UNKNOWN");
+                       return 0;
+               }
+       }
+
+       dev_err(dev, "%s: there's no matched sensor id", __func__);
+
+       return -ENODEV;
+}
+
+static ssize_t camera_front_camtype_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char sensor_maker[50];
+       char sensor_name[50];
+       int ret;
+
+       ret = fimc_is_get_sensor_data(dev, sensor_maker, sensor_name, SENSOR_POSITION_FRONT);
+
+       if (ret < 0)
+               return sprintf(buf, "UNKNOWN_UNKNOWN_FIMC_IS\n");
+       else
+               return sprintf(buf, "%s_%s_FIMC_IS\n", sensor_maker, sensor_name);
+}
+
+static ssize_t camera_front_camfw_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char sensor_name[50];
+       int ret;
+
+       ret = fimc_is_get_sensor_data(dev, NULL, sensor_name, SENSOR_POSITION_FRONT);
+
+       if (ret < 0)
+               return sprintf(buf, "UNKNOWN UNKNOWN\n");
+       else
+               return sprintf(buf, "%s N\n", sensor_name);
+}
+
+static DEVICE_ATTR(front_camtype, S_IRUGO,
+               camera_front_camtype_show, NULL);
+static DEVICE_ATTR(front_camfw, S_IRUGO, camera_front_camfw_show, NULL);
+
+static struct fimc_is_from_info *pinfo = NULL;
+static struct fimc_is_from_info *finfo = NULL;
+
+int read_from_firmware_version(void)
+{
+       char fw_name[100];
+       char setf_name[100];
+#ifdef CONFIG_COMPANION_USE
+       char master_setf_name[100];
+       char mode_setf_name[100];
+#endif
+       struct device *is_dev = &sysfs_core->ischain[0].pdev->dev;
+
+       fimc_is_sec_get_sysfs_pinfo(&pinfo);
+       fimc_is_sec_get_sysfs_finfo(&finfo);
+
+       if (!finfo->is_caldata_read) {
+               if (finfo->bin_start_addr != 0x80000) {
+                       //fimc_is_sec_set_camid(CAMERA_DUAL_FRONT);
+#if defined(CONFIG_PM_RUNTIME)
+                       pr_debug("pm_runtime_suspended = %d\n",
+                       pm_runtime_suspended(is_dev));
+                       pm_runtime_get_sync(is_dev);
+#else
+                       fimc_is_runtime_resume(is_dev);
+                       printk(KERN_INFO "%s - fimc_is runtime resume complete\n", __func__);
+#endif
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+                       fimc_is_sec_fw_sel_eeprom(is_dev, fw_name, setf_name, SENSOR_POSITION_REAR, false);
+#else
+                       fimc_is_sec_fw_sel(sysfs_core, is_dev, fw_name, setf_name, false);
+#endif
+#ifdef CONFIG_COMPANION_USE
+                       fimc_is_sec_concord_fw_sel(sysfs_core, is_dev, fw_name, master_setf_name, mode_setf_name);
+#endif
+#if defined(CONFIG_PM_RUNTIME)
+                       pm_runtime_put_sync(is_dev);
+                       pr_debug("pm_runtime_suspended = %d\n",
+                               pm_runtime_suspended(is_dev));
+#else
+                       fimc_is_runtime_suspend(is_dev);
+#endif
+               }
+       }
+       return 0;
+}
+
+static ssize_t camera_rear_camtype_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char sensor_maker[50];
+       char sensor_name[50];
+       int ret;
+
+       ret = fimc_is_get_sensor_data(dev, sensor_maker, sensor_name, SENSOR_POSITION_REAR);
+
+       if (ret < 0)
+               return sprintf(buf, "UNKNOWN_UNKNOWN_FIMC_IS\n");
+       else
+               return sprintf(buf, "%s_%s_FIMC_IS\n", sensor_maker, sensor_name);
+}
+
+static ssize_t camera_rear_camfw_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char command_ack[20] = {0, };
+       char *loaded_fw;
+
+       read_from_firmware_version();
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+       loaded_fw = pinfo->header_ver;
+#else
+       fimc_is_sec_get_loaded_fw(&loaded_fw);
+#endif
+
+       if(fw_version_crc_check) {
+               if (crc32_fw_check && crc32_check_factory
+#ifdef CONFIG_COMPANION_USE
+                   && crc32_c1_fw_check && crc32_c1_check_factory
+#endif
+               ) {
+                       return sprintf(buf, "%s %s\n", finfo->header_ver, loaded_fw);
+               } else {
+                       strcpy(command_ack, "NG_");
+                       if (!crc32_fw_check)
+                               strcat(command_ack, "FW");
+                       if (!crc32_check_factory)
+                               strcat(command_ack, "CD");
+#ifdef CONFIG_COMPANION_USE
+                       if (!crc32_c1_fw_check)
+                               strcat(command_ack, "FW1");
+                       if (!crc32_c1_check_factory)
+                               strcat(command_ack, "CD1");
+#endif
+                       if (finfo->header_ver[3] != 'L')
+                               strcat(command_ack, "_Q");
+                       return sprintf(buf, "%s %s\n", finfo->header_ver, command_ack);
+               }
+       } else {
+               strcpy(command_ack, "NG_");
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+               strcat(command_ack, "CD");
+#else
+               strcat(command_ack, "FWCD");
+#endif
+#ifdef CONFIG_COMPANION_USE
+               strcat(command_ack, "FW1CD1");
+#endif
+               return sprintf(buf, "%s %s\n", finfo->header_ver, command_ack);
+       }
+}
+
+static ssize_t camera_rear_camfw_full_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char command_ack[20] = {0, };
+       char *loaded_fw;
+
+       read_from_firmware_version();
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+       loaded_fw = pinfo->header_ver;
+#else
+       fimc_is_sec_get_loaded_fw(&loaded_fw);
+#endif
+
+       if(fw_version_crc_check) {
+               if (crc32_fw_check && crc32_check_factory
+#ifdef CONFIG_COMPANION_USE
+                   && crc32_c1_fw_check && crc32_c1_check_factory
+#endif
+               ) {
+                       return sprintf(buf, "%s %s %s\n", finfo->header_ver, pinfo->header_ver, loaded_fw);
+               } else {
+                       strcpy(command_ack, "NG_");
+                       if (!crc32_fw_check)
+                               strcat(command_ack, "FW");
+                       if (!crc32_check_factory)
+                               strcat(command_ack, "CD");
+#ifdef CONFIG_COMPANION_USE
+                       if (!crc32_c1_fw_check)
+                               strcat(command_ack, "FW1");
+                       if (!crc32_c1_check_factory)
+                               strcat(command_ack, "CD1");
+#endif
+                       if (finfo->header_ver[3] != 'L')
+                               strcat(command_ack, "_Q");
+                       return sprintf(buf, "%s %s %s\n", finfo->header_ver, pinfo->header_ver, command_ack);
+               }
+       } else {
+               strcpy(command_ack, "NG_");
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+               strcat(command_ack, "CD");
+#else
+               strcat(command_ack, "FWCD");
+#endif
+#ifdef CONFIG_COMPANION_USE
+               strcat(command_ack, "FW1CD1");
+#endif
+               return sprintf(buf, "%s %s %s\n", finfo->header_ver, pinfo->header_ver, command_ack);
+       }
+}
+
+static ssize_t camera_rear_checkfw_user_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       read_from_firmware_version();
+
+       if(fw_version_crc_check) {
+               if (crc32_fw_check && crc32_check_factory
+#ifdef CONFIG_COMPANION_USE
+                   && crc32_c1_fw_check && crc32_c1_check_factory
+#endif
+               ) {
+                       if (!is_latest_cam_module
+#if defined(CONFIG_SOC_EXYNOS5433)
+                               || !is_right_prj_name
+#endif
+                       ) {
+                               return sprintf(buf, "%s\n", "NG");
+                       } else {
+                               return sprintf(buf, "%s\n", "OK");
+                       }
+               } else {
+                       return sprintf(buf, "%s\n", "NG");
+               }
+       } else {
+               return sprintf(buf, "%s\n", "NG");
+       }
+}
+
+static ssize_t camera_rear_checkfw_factory_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       read_from_firmware_version();
+
+       if(fw_version_crc_check) {
+               if (crc32_fw_check && crc32_check_factory
+#ifdef CONFIG_COMPANION_USE
+                   && crc32_c1_fw_check && crc32_c1_check_factory
+#endif
+               ) {
+                       if (!is_final_cam_module
+#if defined(CONFIG_SOC_EXYNOS5433)
+                               || !is_right_prj_name
+#endif
+                       ) {
+                               return sprintf(buf, "%s\n", "NG");
+                       } else {
+                               return sprintf(buf, "%s\n", "OK");
+                       }
+               } else {
+                       return sprintf(buf, "%s\n", "NG");
+               }
+       } else {
+               return sprintf(buf, "%s\n", "NG");
+       }
+}
+
+#ifdef CONFIG_COMPANION_USE
+static ssize_t camera_rear_companionfw_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char *loaded_c1_fw;
+
+       read_from_firmware_version();
+       fimc_is_sec_get_loaded_c1_fw(&loaded_c1_fw);
+
+       return sprintf(buf, "%s %s\n",
+               finfo->concord_header_ver, loaded_c1_fw);
+}
+
+static ssize_t camera_rear_companionfw_full_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char *loaded_c1_fw;
+
+       read_from_firmware_version();
+       fimc_is_sec_get_loaded_c1_fw(&loaded_c1_fw);
+
+       return sprintf(buf, "%s %s %s\n",
+               finfo->concord_header_ver, pinfo->concord_header_ver, loaded_c1_fw);
+}
+#endif
+
+static ssize_t camera_rear_camfw_write(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t size)
+{
+       ssize_t ret = -EINVAL;
+
+       if ((size == 1 || size == 2) && (buf[0] == 'F' || buf[0] == 'f')) {
+               fimc_is_sec_set_force_caldata_dump(true);
+               ret = size;
+       } else {
+               fimc_is_sec_set_force_caldata_dump(false);
+       }
+       return ret;
+}
+
+static ssize_t camera_rear_calcheck_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       char rear_sensor[10] = {0, };
+#ifdef CONFIG_COMPANION_USE
+       char rear_companion[10] = {0, };
+#endif
+
+       read_from_firmware_version();
+
+       if (crc32_check_factory)
+               strcpy(rear_sensor, "Normal");
+       else
+               strcpy(rear_sensor, "Abnormal");
+
+#ifdef CONFIG_COMPANION_USE
+       if (crc32_c1_check_factory)
+               strcpy(rear_companion, "Normal");
+       else
+               strcpy(rear_companion, "Abnormal");
+
+       return sprintf(buf, "%s %s %s\n", rear_sensor, rear_companion, "Null");
+#else
+       return sprintf(buf, "%s %s\n", rear_sensor, "Null");
+#endif
+}
+
+#ifdef CONFIG_COMPANION_USE
+static ssize_t camera_isp_core_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       int sel;
+
+       if (DCDC_VENDOR_NONE == sysfs_core->companion_dcdc.type)
+               return sprintf(buf, "none\n");
+
+       sel = fimc_is_power_binning(sysfs_core);
+       return sprintf(buf, "%s\n", sysfs_core->companion_dcdc.get_vout_str(sel));
+}
+#endif
+
+#ifdef CONFIG_OIS_USE
+static ssize_t camera_ois_power_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+
+{
+       switch (buf[0]) {
+       case '0':
+               fimc_is_ois_gpio_off(sysfs_core->companion);
+               break;
+       case '1':
+               fimc_is_ois_gpio_on(sysfs_core->companion);
+               msleep(150);
+               break;
+       default:
+               pr_debug("%s: %c\n", __func__, buf[0]);
+               break;
+       }
+
+       return count;
+}
+
+static ssize_t camera_ois_selftest_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       int result_total = 0;
+       bool result_offset = 0, result_selftest = 0;
+       int selftest_ret = 0;
+       long raw_data_x = 0, raw_data_y = 0;
+
+       fimc_is_ois_offset_test(sysfs_core, &raw_data_x, &raw_data_y);
+       msleep(50);
+       selftest_ret = fimc_is_ois_self_test(sysfs_core);
+
+       if (selftest_ret == 0x0) {
+               result_selftest = true;
+       } else {
+               result_selftest = false;
+       }
+
+       if (abs(raw_data_x) > 35000 || abs(raw_data_y) > 35000)  {
+               result_offset = false;
+       } else {
+               result_offset = true;
+       }
+
+       if (result_offset && result_selftest) {
+               result_total = 0;
+       } else if (!result_offset && !result_selftest) {
+               result_total = 3;
+       } else if (!result_offset) {
+               result_total = 1;
+       } else if (!result_selftest) {
+               result_total = 2;
+       }
+
+       if (raw_data_x < 0 && raw_data_y < 0) {
+               return sprintf(buf, "%d,-%ld.%03ld,-%ld.%03ld\n", result_total, abs(raw_data_x /1000), abs(raw_data_x % 1000),
+                       abs(raw_data_y /1000), abs(raw_data_y % 1000));
+       } else if (raw_data_x < 0) {
+               return sprintf(buf, "%d,-%ld.%03ld,%ld.%03ld\n", result_total, abs(raw_data_x /1000), abs(raw_data_x % 1000),
+                       raw_data_y /1000, raw_data_y % 1000);
+       } else if (raw_data_y < 0) {
+               return sprintf(buf, "%d,%ld.%03ld,-%ld.%03ld\n", result_total, raw_data_x /1000, raw_data_x % 1000,
+                       abs(raw_data_y /1000), abs(raw_data_y % 1000));
+       } else {
+               return sprintf(buf, "%d,%ld.%03ld,%ld.%03ld\n", result_total, raw_data_x /1000, raw_data_x % 1000,
+                       raw_data_y /1000, raw_data_y % 1000);
+       }
+}
+
+static ssize_t camera_ois_rawdata_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       long raw_data_x = 0, raw_data_y = 0;
+
+       fimc_is_ois_get_offset_data(sysfs_core, &raw_data_x, &raw_data_y);
+
+       if (raw_data_x < 0 && raw_data_y < 0) {
+               return sprintf(buf, "-%ld.%03ld,-%ld.%03ld\n", abs(raw_data_x /1000), abs(raw_data_x % 1000),
+                       abs(raw_data_y /1000), abs(raw_data_y % 1000));
+       } else if (raw_data_x < 0) {
+               return sprintf(buf, "-%ld.%03ld,%ld.%03ld\n", abs(raw_data_x /1000), abs(raw_data_x % 1000),
+                       raw_data_y /1000, raw_data_y % 1000);
+       } else if (raw_data_y < 0) {
+               return sprintf(buf, "%ld.%03ld,-%ld.%03ld\n", raw_data_x /1000, raw_data_x % 1000,
+                       abs(raw_data_y /1000), abs(raw_data_y % 1000));
+       } else {
+               return sprintf(buf, "%ld.%03ld,%ld.%03ld\n", raw_data_x /1000, raw_data_x % 1000,
+                       raw_data_y /1000, raw_data_y % 1000);
+       }
+}
+
+static ssize_t camera_ois_version_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct fimc_is_ois_info *ois_minfo = NULL;
+       struct fimc_is_ois_info *ois_pinfo = NULL;
+       u8 checksum = 0, caldata = 0;
+
+       if (!sysfs_core->running_rear_camera) {
+               fimc_is_ois_gpio_on(sysfs_core->companion);
+               msleep(150);
+               if (!sysfs_core->ois_ver_read) {
+                       fimc_is_ois_check_fw(sysfs_core);
+               }
+
+               fimc_is_ois_fw_status(sysfs_core, &checksum, &caldata);
+
+               if (!sysfs_core->running_rear_camera) {
+                       fimc_is_ois_gpio_off(sysfs_core->companion);
+               }
+       }
+
+       fimc_is_ois_get_module_version(&ois_minfo);
+       fimc_is_ois_get_phone_version(&ois_pinfo);
+
+       if (checksum != 0x00) {
+               return sprintf(buf, "%s %s\n", "NG_FW2", "NULL");
+       } else if (caldata != 0x00) {
+               return sprintf(buf, "%s %s\n", "NG_CD2", ois_pinfo->header_ver);
+       } else {
+               return sprintf(buf, "%s %s\n", ois_minfo->header_ver, ois_pinfo->header_ver);
+       }
+}
+
+static ssize_t camera_ois_diff_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       int result = 0;
+       int x_diff = 0, y_diff = 0;
+
+       result = fimc_is_ois_diff_test(sysfs_core, &x_diff, &y_diff);
+
+       return sprintf(buf, "%d,%d,%d\n", result == true ? 0 : 1, x_diff, y_diff);
+}
+
+static ssize_t camera_ois_fw_update_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+#ifdef CONFIG_OIS_FW_UPDATE_THREAD_USE
+       fimc_is_ois_init_thread(sysfs_core);
+#else
+       fimc_is_ois_gpio_on(sysfs_core->companion);
+       msleep(150);
+
+       fimc_is_ois_fw_update(sysfs_core);
+       fimc_is_ois_gpio_off(sysfs_core->companion);
+#endif
+
+       return sprintf(buf, "%s\n", "Ois update done.");
+}
+
+static ssize_t camera_ois_exif_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct fimc_is_ois_info *ois_minfo = NULL;
+       struct fimc_is_ois_info *ois_pinfo = NULL;
+       struct fimc_is_ois_info *ois_uinfo = NULL;
+       struct fimc_is_ois_exif *ois_exif = NULL;
+
+       fimc_is_ois_get_module_version(&ois_minfo);
+       fimc_is_ois_get_phone_version(&ois_pinfo);
+       fimc_is_ois_get_user_version(&ois_uinfo);
+       fimc_is_ois_get_exif_data(&ois_exif);
+
+       return sprintf(buf, "%s %s %s %d %d", ois_minfo->header_ver, ois_pinfo->header_ver,
+               ois_uinfo->header_ver, ois_exif->error_data, ois_exif->status_data);
+}
+#endif
+
+static DEVICE_ATTR(rear_camtype, S_IRUGO,
+               camera_rear_camtype_show, NULL);
+static DEVICE_ATTR(rear_camfw, S_IRUGO,
+               camera_rear_camfw_show, camera_rear_camfw_write);
+static DEVICE_ATTR(rear_camfw_full, S_IRUGO,
+               camera_rear_camfw_full_show, NULL);
+#ifdef CONFIG_COMPANION_USE
+static DEVICE_ATTR(rear_companionfw, S_IRUGO,
+               camera_rear_companionfw_show, NULL);
+static DEVICE_ATTR(rear_companionfw_full, S_IRUGO,
+               camera_rear_companionfw_full_show, NULL);
+#endif
+static DEVICE_ATTR(rear_calcheck, S_IRUGO,
+               camera_rear_calcheck_show, NULL);
+static DEVICE_ATTR(rear_checkfw_user, S_IRUGO,
+               camera_rear_checkfw_user_show, NULL);
+static DEVICE_ATTR(rear_checkfw_factory, S_IRUGO,
+               camera_rear_checkfw_factory_show, NULL);
+#ifdef CONFIG_COMPANION_USE
+static DEVICE_ATTR(isp_core, S_IRUGO,
+               camera_isp_core_show, NULL);
+#endif
+#ifdef CONFIG_OIS_USE
+static DEVICE_ATTR(selftest, S_IRUGO,
+               camera_ois_selftest_show, NULL);
+static DEVICE_ATTR(ois_power, S_IWUSR,
+               NULL, camera_ois_power_store);
+static DEVICE_ATTR(ois_rawdata, S_IRUGO,
+               camera_ois_rawdata_show, NULL);
+static DEVICE_ATTR(oisfw, S_IRUGO,
+               camera_ois_version_show, NULL);
+static DEVICE_ATTR(ois_diff, S_IRUGO,
+               camera_ois_diff_show, NULL);
+static DEVICE_ATTR(fw_update, S_IRUGO,
+               camera_ois_fw_update_show, NULL);
+static DEVICE_ATTR(ois_exif, S_IRUGO,
+               camera_ois_exif_show, NULL);
+#endif
+#endif /* CONFIG_USE_VENDER_FEATURE */
+
+static int fimc_is_suspend(struct device *dev)
+{
+       pr_debug("FIMC_IS Suspend\n");
+       return 0;
+}
+
+static int fimc_is_resume(struct device *dev)
+{
+       pr_debug("FIMC_IS Resume\n");
+       return 0;
+}
+
+#ifdef USE_OWN_FAULT_HANDLER
+static void fimc_is_print_minfo(struct fimc_is_minfo *minfo)
+{
+       if (minfo) {
+               err("dvaddr : 0x%08x, size : %d", minfo->dvaddr, minfo->size);
+               err("dvaddr_debug  : 0x%08x, dvaddr_region : 0x%08x", minfo->dvaddr_debug, minfo->dvaddr_region);
+               err("dvaddr_shared : 0x%08x, dvaddr_odc    : 0x%08x", minfo->dvaddr_shared, minfo->dvaddr_odc);
+               err("dvaddr_dis    : 0x%08x, dvaddr_3dnr   : 0x%08x", minfo->dvaddr_dis, minfo->dvaddr_3dnr);
+       } else {
+               err("core->minfo is NULL");
+       }
+}
+
+static void __fimc_is_fault_handler(struct device *dev)
+{
+       u32 i, j, k;
+       struct fimc_is_core *core;
+       struct fimc_is_device_sensor *sensor;
+       struct fimc_is_device_ischain *ischain;
+       struct fimc_is_framemgr *framemgr;
+
+       core = dev_get_drvdata(dev);
+       if (core) {
+
+               fimc_is_print_minfo(&core->minfo);
+               fimc_is_hw_logdump(&core->interface);
+               /* dump FW page table 1nd(~16KB), 2nd(16KB~32KB) */
+               fimc_is_hw_memdump(&core->interface,
+                       core->minfo.kvaddr + 0x010F8000 /* TTB_BASE ~ 32KB */,
+                       core->minfo.kvaddr + 0x010F8000 + 0x8000);
+
+               /* REAR SENSOR */
+               sensor = &core->sensor[0];
+               if (test_bit(FIMC_IS_SENSOR_OPEN, &sensor->state)) {
+                       framemgr = &sensor->vctx->q_dst->framemgr;
+                       for (i = 0; i < FRAMEMGR_MAX_REQUEST; ++i) {
+                               pr_err("LITE0 BUF[%d][0] = %X, 0x%08X, 0x%08X\n", i,
+                                       (u32)framemgr->frame[i].memory,
+                                       framemgr->frame[i].dvaddr_buffer[0],
+                                       framemgr->frame[i].kvaddr_buffer[0]);
+                       }
+               }
+
+               /* FRONT SENSOR */
+               sensor = &core->sensor[1];
+               if (test_bit(FIMC_IS_SENSOR_OPEN, &sensor->state)) {
+                       framemgr = &sensor->vctx->q_dst->framemgr;
+                       for (i = 0; i < FRAMEMGR_MAX_REQUEST; ++i) {
+                               pr_err("LITE1 BUF[%d][0] = %X, 0x%08X. 0x%08X\n", i,
+                                       (u32)framemgr->frame[i].memory,
+                                       framemgr->frame[i].dvaddr_buffer[0],
+                                       framemgr->frame[i].kvaddr_buffer[0]);
+                       }
+               }
+
+               /* ISCHAIN */
+               for (i = 0; i < FIMC_IS_MAX_NODES; i++) {
+                       if (test_bit(FIMC_IS_ISCHAIN_OPEN, &(core->ischain[i].state))) {
+                               ischain = &core->ischain[i];
+                               /* 3AA */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->group_3aa.leader.state)) {
+                                       framemgr = &ischain->group_3aa.leader.vctx->q_src->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[3AA:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* 3AAC */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->taac.state)) {
+                                       framemgr = &ischain->taac.leader->vctx->q_dst->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[3AAC:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* 3AAP */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->taap.state)) {
+                                       framemgr = &ischain->taap.leader->vctx->q_dst->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[3AAP:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* ISP */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->group_isp.leader.state)) {
+                                       framemgr = &ischain->group_isp.leader.vctx->q_src->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[ISP:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* SCC */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->scc.state)) {
+                                       framemgr = &ischain->scc.vctx->q_dst->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[SCC:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* VDC */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->dis.state)) {
+                                       framemgr = &ischain->dis.vctx->q_dst->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[VDC:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* VDO */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->group_dis.leader.state)) {
+                                       framemgr = &ischain->group_dis.leader.vctx->q_src->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[VDO:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                               /* SCP */
+                               if (test_bit(FIMC_IS_SUBDEV_START, &ischain->scp.state)) {
+                                       framemgr = &ischain->scp.vctx->q_dst->framemgr;
+                                       for (j = 0; j < framemgr->frame_cnt; ++j) {
+                                               for (k = 0; k < framemgr->frame[j].planes; k++) {
+                                                       pr_err("[SCP:%d] BUF[%d][%d] = %X, 0x%08X, 0x%08X\n",
+                                                               i, j, k,
+                                                               (u32)framemgr->frame[j].memory,
+                                                               framemgr->frame[j].dvaddr_buffer[k],
+                                                               framemgr->frame[j].kvaddr_buffer[k]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       } else {
+               pr_err("failed to get core\n");
+       }
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+#define SECT_ORDER 20
+#define LPAGE_ORDER 16
+#define SPAGE_ORDER 12
+
+#define lv1ent_page(sent) ((*(sent) & 3) == 1)
+
+#define lv1ent_offset(iova) ((iova) >> SECT_ORDER)
+#define lv2ent_offset(iova) (((iova) & 0xFF000) >> SPAGE_ORDER)
+#define lv2table_base(sent) (*(sent) & 0xFFFFFC00)
+
+static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
+{
+       return pgtable + lv1ent_offset(iova);
+}
+
+static unsigned long *page_entry(unsigned long *sent, unsigned long iova)
+{
+       return (unsigned long *)__va(lv2table_base(sent)) + lv2ent_offset(iova);
+}
+
+static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
+       "PAGE FAULT",
+       "AR MULTI-HIT FAULT",
+       "AW MULTI-HIT FAULT",
+       "BUS ERROR",
+       "AR SECURITY PROTECTION FAULT",
+       "AR ACCESS PROTECTION FAULT",
+       "AW SECURITY PROTECTION FAULT",
+       "AW ACCESS PROTECTION FAULT",
+       "UNKNOWN FAULT"
+};
+
+static int fimc_is_fault_handler(struct device *dev, const char *mmuname,
+                                       enum exynos_sysmmu_inttype itype,
+                                       unsigned long pgtable_base,
+                                       unsigned long fault_addr)
+{
+       unsigned long *ent;
+
+       if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT))
+               itype = SYSMMU_FAULT_UNKNOWN;
+
+       pr_err("%s occured at 0x%lx by '%s'(Page table base: 0x%lx)\n",
+               sysmmu_fault_name[itype], fault_addr, mmuname, pgtable_base);
+
+       ent = section_entry(__va(pgtable_base), fault_addr);
+       pr_err("\tLv1 entry: 0x%lx\n", *ent);
+
+       if (lv1ent_page(ent)) {
+               ent = page_entry(ent, fault_addr);
+               pr_err("\t Lv2 entry: 0x%lx\n", *ent);
+       }
+
+       __fimc_is_fault_handler(dev);
+
+       pr_err("Generating Kernel OOPS... because it is unrecoverable.\n");
+
+       BUG();
+
+       return 0;
+}
+#else
+static int fimc_is_fault_handler(struct iommu_domain *domain,
+       struct device *dev,
+       unsigned long fault_addr,
+       int fault_flag,
+       void *token)
+{
+       pr_err("<FIMC-IS FAULT HANDLER>\n");
+       pr_err("Device virtual(0x%X) is invalid access\n", (u32)fault_addr);
+
+       __fimc_is_fault_handler(dev);
+
+       return -EINVAL;
+}
+#endif
+#endif /* USE_OWN_FAULT_HANDLER */
+
+static ssize_t show_clk_gate_mode(struct device *dev, struct device_attribute *attr,
+                                 char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", sysfs_debug.clk_gate_mode);
+}
+
+static ssize_t store_clk_gate_mode(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+#ifdef HAS_FW_CLOCK_GATE
+       switch (buf[0]) {
+       case '0':
+               sysfs_debug.clk_gate_mode = CLOCK_GATE_MODE_HOST;
+               break;
+       case '1':
+               sysfs_debug.clk_gate_mode = CLOCK_GATE_MODE_FW;
+               break;
+       default:
+               pr_debug("%s: %c\n", __func__, buf[0]);
+               break;
+       }
+#endif
+       return count;
+}
+
+static ssize_t show_en_clk_gate(struct device *dev, struct device_attribute *attr,
+                                 char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", sysfs_debug.en_clk_gate);
+}
+
+static ssize_t store_en_clk_gate(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+#ifdef ENABLE_CLOCK_GATE
+       switch (buf[0]) {
+       case '0':
+               sysfs_debug.en_clk_gate = false;
+               sysfs_debug.clk_gate_mode = CLOCK_GATE_MODE_HOST;
+               break;
+       case '1':
+               sysfs_debug.en_clk_gate = true;
+               sysfs_debug.clk_gate_mode = CLOCK_GATE_MODE_HOST;
+               break;
+       default:
+               pr_debug("%s: %c\n", __func__, buf[0]);
+               break;
+       }
+#endif
+       return count;
+}
+
+static ssize_t show_en_dvfs(struct device *dev, struct device_attribute *attr,
+                                 char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", sysfs_debug.en_dvfs);
+}
+
+static ssize_t store_en_dvfs(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+#ifdef ENABLE_DVFS
+       struct fimc_is_core *core =
+               (struct fimc_is_core *)platform_get_drvdata(to_platform_device(dev));
+       struct fimc_is_resourcemgr *resourcemgr;
+       int i;
+
+       BUG_ON(!core);
+
+       resourcemgr = &core->resourcemgr;
+
+       switch (buf[0]) {
+       case '0':
+               sysfs_debug.en_dvfs = false;
+               /* update dvfs lever to max */
+               mutex_lock(&resourcemgr->dvfs_ctrl.lock);
+               for (i = 0; i < FIMC_IS_MAX_NODES; i++) {
+                       if (test_bit(FIMC_IS_ISCHAIN_OPEN, &((core->ischain[i]).state)))
+                               fimc_is_set_dvfs(&(core->ischain[i]), FIMC_IS_SN_MAX);
+               }
+               fimc_is_dvfs_init(resourcemgr);
+               resourcemgr->dvfs_ctrl.static_ctrl->cur_scenario_id = FIMC_IS_SN_MAX;
+               mutex_unlock(&resourcemgr->dvfs_ctrl.lock);
+               break;
+       case '1':
+               /* It can not re-define static scenario */
+               sysfs_debug.en_dvfs = true;
+               break;
+       default:
+               pr_debug("%s: %c\n", __func__, buf[0]);
+               break;
+       }
+#endif
+       return count;
+}
+
+static DEVICE_ATTR(en_clk_gate, 0644, show_en_clk_gate, store_en_clk_gate);
+static DEVICE_ATTR(clk_gate_mode, 0644, show_clk_gate_mode, store_clk_gate_mode);
+static DEVICE_ATTR(en_dvfs, 0644, show_en_dvfs, store_en_dvfs);
+
+static struct attribute *fimc_is_debug_entries[] = {
+       &dev_attr_en_clk_gate.attr,
+       &dev_attr_clk_gate_mode.attr,
+       &dev_attr_en_dvfs.attr,
+       NULL,
+};
+static struct attribute_group fimc_is_debug_attr_group = {
+       .name   = "debug",
+       .attrs  = fimc_is_debug_entries,
+};
+
+static int fimc_is_probe(struct platform_device *pdev)
+{
+       struct exynos_platform_fimc_is *pdata;
+       struct resource *mem_res;
+       struct resource *regs_res;
+       struct fimc_is_core *core;
+       int ret = -ENODEV;
+
+       info("%s:start\n", __func__);
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+#ifdef CONFIG_OF
+               pdata = fimc_is_parse_dt(&pdev->dev);
+               if (IS_ERR(pdata))
+#endif
+                       return PTR_ERR(pdata);
+       }
+
+       core = kzalloc(sizeof(struct fimc_is_core), GFP_KERNEL);
+       if (!core) {
+               err("core is NULL");
+               return -ENOMEM;
+       }
+
+       fimc_is_dev = &pdev->dev;
+       ret = dev_set_drvdata(fimc_is_dev, core);
+       if (ret) {
+               err("dev_set_drvdata is fail(%d)", ret);
+               kfree(core);
+               return ret;
+       }
+
+#ifdef CONFIG_COMPANION_USE
+       core->companion_spi_channel = pdata->companion_spi_channel;
+       core->use_two_spi_line = pdata->use_two_spi_line;
+#endif
+#ifdef CONFIG_USE_VENDER_FEATURE
+       core->use_sensor_dynamic_voltage_mode = pdata->use_sensor_dynamic_voltage_mode;
+#ifdef CONFIG_OIS_USE
+       core->use_ois = pdata->use_ois;
+#endif /* CONFIG_OIS_USE */
+       core->use_ois_hsi2c = pdata->use_ois_hsi2c;
+       core->use_module_check = pdata->use_module_check;
+#endif
+
+#ifdef USE_ION_ALLOC
+       core->fimc_ion_client = ion_client_create(ion_exynos, "fimc-is");
+#endif
+       core->pdev = pdev;
+       core->pdata = pdata;
+       core->id = pdev->id;
+       core->debug_cnt = 0;
+       core->running_rear_camera = false;
+       core->running_front_camera = false;
+
+       device_init_wakeup(&pdev->dev, true);
+
+       /* init mutex for spi read */
+       mutex_init(&core->spi_lock);
+
+       /* for mideaserver force down */
+       atomic_set(&core->rsccount, 0);
+       clear_bit(FIMC_IS_ISCHAIN_POWER_ON, &core->state);
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem_res) {
+               dev_err(&pdev->dev, "Failed to get io memory region\n");
+               goto p_err1;
+       }
+
+       regs_res = request_mem_region(mem_res->start, resource_size(mem_res),
+                                       pdev->name);
+       if (!regs_res) {
+               dev_err(&pdev->dev, "Failed to request io memory region\n");
+               goto p_err1;
+       }
+
+       core->regs_res = regs_res;
+       core->regs =  ioremap_nocache(mem_res->start, resource_size(mem_res));
+       if (!core->regs) {
+               dev_err(&pdev->dev, "Failed to remap io region\n");
+               goto p_err2;
+       }
+
+       core->irq = platform_get_irq(pdev, 0);
+       if (core->irq < 0) {
+               dev_err(&pdev->dev, "Failed to get irq\n");
+               goto p_err3;
+       }
+
+       ret = fimc_is_mem_probe(&core->mem, core->pdev);
+       if (ret) {
+               err("fimc_is_mem_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+
+       fimc_is_interface_probe(&core->interface,
+               (u32)core->regs,
+               core->irq,
+               core);
+
+       fimc_is_resource_probe(&core->resourcemgr, core);
+
+       /* group initialization */
+       fimc_is_groupmgr_probe(&core->groupmgr);
+
+#if defined(CONFIG_CAMERA_SENSOR_6B2_OBJ)
+       ret = sensor_6b2_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_6b2_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_8B1_OBJ)
+       ret = sensor_8b1_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_8b1_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_6D1_OBJ)
+       ret = sensor_6d1_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_6d1_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_6A3_OBJ)
+       ret = sensor_6a3_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_6a3_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_IMX134_OBJ)
+       ret = sensor_imx134_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_imx134_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_IMX135_OBJ)
+       ret = sensor_imx135_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_imx135_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_3L2_OBJ)
+       ret = sensor_3l2_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_3l2_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_2P2_OBJ)
+       ret = sensor_2p2_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_2p2_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_2P2_12M_OBJ)
+       ret = sensor_2p2_12m_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_2p2_12m_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_2P3_OBJ)
+       ret = sensor_2p3_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_2p3_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_3H5_OBJ)
+       ret = sensor_3h5_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_3h5_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_3H7_OBJ)
+       ret = sensor_3h7_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_3h7_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_3H7_SUNNY_OBJ)
+       ret = sensor_3h7_sunny_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_3h7_sunny_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_4E5_OBJ)
+       ret = sensor_4e5_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_4e5_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_IMX175_OBJ)
+       ret = sensor_imx175_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_imx175_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_IMX240_OBJ)
+       ret = sensor_imx240_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_imx175_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_IMX219_OBJ)
+       ret = sensor_imx219_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_imx219_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_SENSOR_4H5_OBJ)
+       ret = sensor_4h5_probe(NULL, NULL);
+       if (ret) {
+               err("sensor_4h5_probe is fail(%d)", ret);
+               goto p_err3;
+       }
+#endif
+
+       /* device entity - ischain0 */
+       fimc_is_ischain_probe(&core->ischain[0],
+               &core->interface,
+               &core->resourcemgr,
+               &core->groupmgr,
+               &core->mem,
+               core->pdev,
+               0,
+               (u32)core->regs);
+
+       /* device entity - ischain1 */
+       fimc_is_ischain_probe(&core->ischain[1],
+               &core->interface,
+               &core->resourcemgr,
+               &core->groupmgr,
+               &core->mem,
+               core->pdev,
+               1,
+               (u32)core->regs);
+
+       /* device entity - ischain2 */
+       fimc_is_ischain_probe(&core->ischain[2],
+               &core->interface,
+               &core->resourcemgr,
+               &core->groupmgr,
+               &core->mem,
+               core->pdev,
+               2,
+               (u32)core->regs);
+
+       ret = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register fimc-is v4l2 device\n");
+               goto p_err4;
+       }
+
+       /* video entity - 3a0 */
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, 3a0))
+               fimc_is_3a0_video_probe(core);
+
+       /* video entity - 3a0 capture */
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, 3a0))
+               fimc_is_3a0c_video_probe(core);
+
+       /* video entity - 3a1 */
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, 3a1))
+               fimc_is_3a1_video_probe(core);
+
+       /* video entity - 3a1 capture */
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, 3a1))
+               fimc_is_3a1c_video_probe(core);
+
+       /* video entity - isp */
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, isp))
+               fimc_is_isp_video_probe(core);
+
+       /*front video entity - scalerC */
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, scc))
+               fimc_is_scc_video_probe(core);
+
+       /* back video entity - scalerP*/
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, scp))
+               fimc_is_scp_video_probe(core);
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP(core, dis)) {
+               /* vdis video entity - vdis capture*/
+               fimc_is_vdc_video_probe(core);
+               /* vdis video entity - vdis output*/
+               fimc_is_vdo_video_probe(core);
+       }
+
+       platform_set_drvdata(pdev, core);
+
+       ret = fimc_is_ishcain_initmem(core);
+       if (ret) {
+               err("fimc_is_ishcain_initmem is fail(%d)", ret);
+               goto p_err4;
+       }
+
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (core->mem.alloc_ctx)
+               vb2_ion_attach_iommu(core->mem.alloc_ctx);
+#endif
+#endif
+       EXYNOS_MIF_ADD_NOTIFIER(&exynos_fimc_is_mif_throttling_nb);
+
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_enable(&pdev->dev);
+#endif
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+       if (camera_class == NULL) {
+               camera_class = class_create(THIS_MODULE, "camera");
+               if (IS_ERR(camera_class)) {
+                       pr_err("Failed to create class(camera)!\n");
+                       ret = PTR_ERR(camera_class);
+                       goto p_err5;
+               }
+       }
+
+       camera_front_dev = device_create(camera_class, NULL, 0, NULL, "front");
+       if (IS_ERR(camera_front_dev)) {
+               printk(KERN_ERR "failed to create front device!\n");
+       } else {
+               if (device_create_file(camera_front_dev,
+                               &dev_attr_front_sensorid) < 0) {
+                       printk(KERN_ERR "failed to create front device file, %s\n",
+                                       dev_attr_front_sensorid.attr.name);
+               }
+
+               if (device_create_file(camera_front_dev,
+                                       &dev_attr_front_camtype)
+                               < 0) {
+                       printk(KERN_ERR
+                               "failed to create front device file, %s\n",
+                               dev_attr_front_camtype.attr.name);
+               }
+               if (device_create_file(camera_front_dev,
+                                       &dev_attr_front_camfw) < 0) {
+                       printk(KERN_ERR
+                               "failed to create front device file, %s\n",
+                               dev_attr_front_camfw.attr.name);
+               }
+       }
+       camera_rear_dev = device_create(camera_class, NULL, 1, NULL, "rear");
+       if (IS_ERR(camera_rear_dev)) {
+               printk(KERN_ERR "failed to create rear device!\n");
+       } else {
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_sensorid) < 0) {
+                       printk(KERN_ERR "failed to create rear device file, %s\n",
+                                       dev_attr_rear_sensorid.attr.name);
+               }
+
+               if (device_create_file(camera_rear_dev, &dev_attr_rear_camtype)
+                               < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_camtype.attr.name);
+               }
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_camfw) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_camfw.attr.name);
+               }
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_camfw_full) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_camfw_full.attr.name);
+               }
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_checkfw_user) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_checkfw_user.attr.name);
+               }
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_checkfw_factory) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_checkfw_factory.attr.name);
+               }
+#ifdef CONFIG_COMPANION_USE
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_companionfw) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_companionfw.attr.name);
+               }
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_companionfw_full) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_companionfw_full.attr.name);
+               }
+#endif
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_rear_calcheck) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_rear_calcheck.attr.name);
+               }
+#ifdef CONFIG_COMPANION_USE
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_isp_core) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_isp_core.attr.name);
+               }
+#endif
+#ifdef CONFIG_OIS_USE
+               if (device_create_file(camera_rear_dev,
+                                       &dev_attr_fw_update) < 0) {
+                       printk(KERN_ERR
+                               "failed to create rear device file, %s\n",
+                               dev_attr_fw_update.attr.name);
+               }
+#endif
+       }
+
+#ifdef CONFIG_OIS_USE
+       camera_ois_dev = device_create(camera_class, NULL, 2, NULL, "ois");
+       if (IS_ERR(camera_ois_dev)) {
+               printk(KERN_ERR "failed to create ois device!\n");
+       } else {
+               if (device_create_file(camera_ois_dev,
+                                       &dev_attr_selftest) < 0) {
+                       printk(KERN_ERR
+                               "failed to create ois device file, %s\n",
+                               dev_attr_selftest.attr.name);
+               }
+               if (device_create_file(camera_ois_dev,
+                                       &dev_attr_ois_power) < 0) {
+                       printk(KERN_ERR
+                               "failed to create ois device file, %s\n",
+                               dev_attr_ois_power.attr.name);
+               }
+               if (device_create_file(camera_ois_dev,
+                                       &dev_attr_ois_rawdata) < 0) {
+                       printk(KERN_ERR
+                               "failed to create ois device file, %s\n",
+                               dev_attr_ois_rawdata.attr.name);
+               }
+               if (device_create_file(camera_ois_dev,
+                                       &dev_attr_oisfw) < 0) {
+                       printk(KERN_ERR
+                               "failed to create ois device file, %s\n",
+                               dev_attr_oisfw.attr.name);
+               }
+               if (device_create_file(camera_ois_dev,
+                                       &dev_attr_ois_diff) < 0) {
+                       printk(KERN_ERR
+                               "failed to create ois device file, %s\n",
+                               dev_attr_ois_diff.attr.name);
+               }
+               if (device_create_file(camera_ois_dev,
+                                       &dev_attr_ois_exif) < 0) {
+                       printk(KERN_ERR
+                               "failed to create ois device file, %s\n",
+                               dev_attr_ois_exif.attr.name);
+               }
+       }
+#endif
+
+       sysfs_core = core;
+#endif
+
+#ifdef USE_OWN_FAULT_HANDLER
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+       exynos_sysmmu_set_fault_handler(fimc_is_dev, fimc_is_fault_handler);
+#else
+       iovmm_set_fault_handler(fimc_is_dev, fimc_is_fault_handler, NULL);
+#endif
+#endif
+
+       dbg("%s : fimc_is_front_%d probe success\n", __func__, pdev->id);
+
+       /* set sysfs for debuging */
+       sysfs_debug.en_clk_gate = 0;
+       sysfs_debug.en_dvfs = 1;
+#ifdef ENABLE_CLOCK_GATE
+       sysfs_debug.en_clk_gate = 1;
+#ifdef HAS_FW_CLOCK_GATE
+       sysfs_debug.clk_gate_mode = CLOCK_GATE_MODE_FW;
+#else
+       sysfs_debug.clk_gate_mode = CLOCK_GATE_MODE_HOST;
+#endif
+#endif
+       ret = sysfs_create_group(&core->pdev->dev.kobj, &fimc_is_debug_attr_group);
+
+#ifdef ENABLE_DVFS
+       {
+               struct fimc_is_resourcemgr *resourcemgr;
+               resourcemgr = &core->resourcemgr;
+               /* dvfs controller init */
+               ret = fimc_is_dvfs_init(resourcemgr);
+               if (ret)
+                       err("%s: fimc_is_dvfs_init failed!\n", __func__);
+       }
+#endif
+
+       info("%s:end\n", __func__);
+       return 0;
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+p_err5:
+#if defined(CONFIG_PM_RUNTIME)
+       __pm_runtime_disable(&pdev->dev, false);
+#endif
+#endif /* CONFIG_USE_VENDER_FEATURE */
+p_err4:
+       v4l2_device_unregister(&core->v4l2_dev);
+p_err3:
+       iounmap(core->regs);
+p_err2:
+       release_mem_region(regs_res->start, resource_size(regs_res));
+p_err1:
+       kfree(core);
+       return ret;
+}
+
+static int fimc_is_remove(struct platform_device *pdev)
+{
+       dbg("%s\n", __func__);
+
+       if (camera_front_dev) {
+               device_remove_file(camera_front_dev, &dev_attr_front_sensorid);
+               device_remove_file(camera_front_dev, &dev_attr_front_camtype);
+               device_remove_file(camera_front_dev, &dev_attr_front_camfw);
+       }
+
+       if (camera_rear_dev) {
+               device_remove_file(camera_rear_dev, &dev_attr_rear_sensorid);
+               device_remove_file(camera_rear_dev, &dev_attr_rear_camtype);
+               device_remove_file(camera_rear_dev, &dev_attr_rear_camfw);
+               device_remove_file(camera_rear_dev, &dev_attr_rear_camfw_full);
+               device_remove_file(camera_rear_dev, &dev_attr_rear_checkfw_user);
+               device_remove_file(camera_rear_dev, &dev_attr_rear_checkfw_factory);
+#ifdef CONFIG_COMPANION_USE
+               device_remove_file(camera_rear_dev, &dev_attr_rear_companionfw);
+               device_remove_file(camera_rear_dev, &dev_attr_rear_companionfw_full);
+#endif
+               device_remove_file(camera_rear_dev, &dev_attr_rear_calcheck);
+#ifdef CONFIG_COMPANION_USE
+               device_remove_file(camera_rear_dev, &dev_attr_isp_core);
+#endif
+#ifdef CONFIG_OIS_USE
+               device_remove_file(camera_ois_dev, &dev_attr_fw_update);
+#endif
+       }
+
+#ifdef CONFIG_OIS_USE
+       if (camera_ois_dev) {
+               device_remove_file(camera_ois_dev, &dev_attr_selftest);
+               device_remove_file(camera_ois_dev, &dev_attr_ois_power);
+               device_remove_file(camera_ois_dev, &dev_attr_ois_rawdata);
+               device_remove_file(camera_ois_dev, &dev_attr_oisfw);
+               device_remove_file(camera_ois_dev, &dev_attr_ois_diff);
+               device_remove_file(camera_ois_dev, &dev_attr_ois_exif);
+       }
+#endif
+
+       if (camera_class) {
+               if (camera_front_dev)
+                       device_destroy(camera_class, camera_front_dev->devt);
+
+               if (camera_rear_dev)
+                       device_destroy(camera_class, camera_rear_dev->devt);
+
+#ifdef CONFIG_OIS_USE
+               if (camera_ois_dev)
+                       device_destroy(camera_class, camera_ois_dev->devt);
+#endif
+       }
+
+       class_destroy(camera_class);
+
+       return 0;
+}
+
+static const struct dev_pm_ops fimc_is_pm_ops = {
+       .suspend                = fimc_is_suspend,
+       .resume                 = fimc_is_resume,
+       .runtime_suspend        = fimc_is_runtime_suspend,
+       .runtime_resume         = fimc_is_runtime_resume,
+};
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+#if defined(CONFIG_COMPANION_USE)
+static int fimc_is_i2c0_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct fimc_is_core *core;
+       static bool probe_retried = false;
+
+       if (!fimc_is_dev)
+               goto probe_defer;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core)
+               goto probe_defer;
+
+       core->client0 = client;
+
+       pr_info("%s %s: fimc_is_i2c0 driver probed!\n",
+               dev_driver_string(&client->dev), dev_name(&client->dev));
+
+       return 0;
+
+probe_defer:
+       if (probe_retried) {
+               err("probe has already been retried!!");
+               BUG();
+       }
+
+       probe_retried = true;
+       err("core device is not yet probed");
+       return -EPROBE_DEFER;
+}
+
+static int fimc_is_i2c0_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id fimc_is_i2c0_dt_ids[] = {
+       { .compatible = "samsung,fimc_is_i2c0",},
+       {},
+};
+MODULE_DEVICE_TABLE(of, fimc_is_i2c0_dt_ids);
+#endif
+
+static const struct i2c_device_id fimc_is_i2c0_id[] = {
+       {"fimc_is_i2c0", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, fimc_is_i2c0_id);
+
+static struct i2c_driver fimc_is_i2c0_driver = {
+       .driver = {
+               .name = "fimc_is_i2c0",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = fimc_is_i2c0_dt_ids,
+#endif
+       },
+       .probe = fimc_is_i2c0_probe,
+       .remove = fimc_is_i2c0_remove,
+       .id_table = fimc_is_i2c0_id,
+};
+module_i2c_driver(fimc_is_i2c0_driver);
+#endif
+
+#if defined(CONFIG_OF) && defined(CONFIG_COMPANION_USE)
+static int of_fimc_is_spi_dt(struct device *dev, struct fimc_is_spi_gpio *spi_gpio, struct fimc_is_core *core)
+{
+       struct device_node *np;
+       int ret;
+
+       np = of_find_compatible_node(NULL,NULL,"samsung,fimc_is_spi1");
+       if(np == NULL) {
+               pr_err("compatible: fail to read, spi_parse_dt\n");
+               return -ENODEV;
+       }
+
+       ret = of_property_read_string(np, "fimc_is_spi_sclk", (const char **) &spi_gpio->spi_sclk);
+       if (ret) {
+               pr_err("spi gpio: fail to read, spi_parse_dt\n");
+               return -ENODEV;
+       }
+
+       ret = of_property_read_string(np, "fimc_is_spi_ssn",(const char **) &spi_gpio->spi_ssn);
+       if (ret) {
+               pr_err("spi gpio: fail to read, spi_parse_dt\n");
+               return -ENODEV;
+       }
+
+       ret = of_property_read_string(np, "fimc_is_spi_miso",(const char **) &spi_gpio->spi_miso);
+       if (ret) {
+               pr_err("spi gpio: fail to read, spi_parse_dt\n");
+               return -ENODEV;
+       }
+
+       ret = of_property_read_string(np, "fimc_is_spi_mois",(const char **) &spi_gpio->spi_mois);
+       if (ret) {
+               pr_err("spi gpio: fail to read, spi_parse_dt\n");
+               return -ENODEV;
+       }
+
+       pr_info("sclk = %s, ssn = %s, miso = %s, mois = %s spi_channel:(%d)\n", spi_gpio->spi_sclk, spi_gpio->spi_ssn, spi_gpio->spi_miso, spi_gpio->spi_mois,core->companion_spi_channel);
+
+       return 0;
+}
+#endif
+#endif
+
+#ifdef CONFIG_OF
+static int fimc_is_spi_probe(struct spi_device *spi)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+
+       BUG_ON(!fimc_is_dev);
+
+       dbg_core("%s\n", __func__);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+       spi->mode = SPI_MODE_0;
+
+       /* spi->bits_per_word = 16; */
+       if (spi_setup(spi)) {
+               pr_err("failed to setup spi for fimc_is_spi\n");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       if (!strncmp(spi->modalias, "fimc_is_spi0", 12))
+               core->spi0 = spi;
+
+       if (!strncmp(spi->modalias, "fimc_is_spi1", 12)) {
+               core->spi1 = spi;
+#ifdef CONFIG_COMPANION_USE
+               ret = of_fimc_is_spi_dt(&spi->dev,&core->spi_gpio, core);
+               if (ret) {
+                       pr_err("[%s] of_fimc_is_spi_dt parse dt failed\n", __func__);
+                       return ret;
+               }
+#endif
+       }
+
+exit:
+       return ret;
+}
+
+static int fimc_is_spi_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+#if defined(CONFIG_USE_VENDER_FEATURE) && defined(CONFIG_COMPANION_USE)
+static int fimc_is_fan53555_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct fimc_is_core *core;
+       int ret = 0;
+#ifdef CONFIG_SOC_EXYNOS5422
+       struct regulator *regulator = NULL;
+       const char power_name[] = "CAM_IO_1.8V_AP";
+#endif
+       struct device_node *np;
+       int gpio_comp_en;
+
+       BUG_ON(!fimc_is_dev);
+
+       pr_info("%s start\n",__func__);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       np = of_find_compatible_node(NULL, NULL, "samsung,fimc_is_fan53555");
+       if(np == NULL) {
+               pr_err("compatible: fail to read, fan_parse_dt\n");
+               return -ENODEV;
+       }
+
+       gpio_comp_en = of_get_named_gpio(np, "comp_en", 0);
+       if (!gpio_is_valid(gpio_comp_en))
+               pr_err("failed to get comp en gpio\n");
+
+       ret = gpio_request(gpio_comp_en,"COMP_EN");
+       if (ret < 0 )
+               pr_err("gpio_request_error(%d)\n",ret);
+
+       gpio_direction_output(gpio_comp_en,1);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               pr_err("%s: SMBUS Byte Data not Supported\n", __func__);
+               ret = -EIO;
+               goto err;
+       }
+
+       core->companion_dcdc.client = client;
+       core->companion_dcdc.type = DCDC_VENDOR_FAN53555;
+       core->companion_dcdc.get_vout_val = fan53555_get_vout_val;
+       core->companion_dcdc.get_vout_str = fan53555_get_vout_str;
+       core->companion_dcdc.set_vout = fan53555_set_vsel0_vout;
+
+#ifdef CONFIG_SOC_EXYNOS5422
+       regulator = regulator_get(NULL, power_name);
+       if (IS_ERR(regulator)) {
+               pr_err("%s : regulator_get(%s) fail\n", __func__, power_name);
+               return PTR_ERR(regulator);
+       }
+
+       if (regulator_is_enabled(regulator)) {
+               pr_info("%s regulator is already enabled\n", power_name);
+       } else {
+               ret = regulator_enable(regulator);
+               if (unlikely(ret)) {
+                       pr_err("%s : regulator_enable(%s) fail\n", __func__, power_name);
+                       goto err;
+               }
+       }
+       usleep_range(1000, 1000);
+#endif
+
+       ret = i2c_smbus_write_byte_data(client, REG_VSEL0, VSEL0_INIT_VAL);
+       if (ret < 0) {
+               pr_err("%s: write error = %d , try again\n", __func__, ret);
+               ret = i2c_smbus_write_byte_data(client, REG_VSEL0, VSEL0_INIT_VAL);
+               if (ret < 0)
+                       pr_err("%s: write 2nd error = %d\n", __func__, ret);
+       }
+
+       ret = i2c_smbus_read_byte_data(client, REG_VSEL0);
+       if (ret < 0) {
+               pr_err("%s: read error = %d , try again\n", __func__, ret);
+               ret = i2c_smbus_read_byte_data(client, REG_VSEL0);
+               if (ret < 0)
+                       pr_err("%s: read 2nd error = %d\n", __func__, ret);
+       }
+       pr_err("[%s::%d]fan53555 [Read :: %x ,%x]\n\n", __func__, __LINE__, ret,VSEL0_INIT_VAL);
+
+#ifdef CONFIG_SOC_EXYNOS5422
+       ret = regulator_disable(regulator);
+       if (unlikely(ret)) {
+               pr_err("%s: regulator_disable(%s) fail\n", __func__, power_name);
+               goto err;
+       }
+       regulator_put(regulator);
+#endif
+       gpio_direction_output(gpio_comp_en,0);
+       gpio_free(gpio_comp_en);
+
+       pr_info(" %s end\n",__func__);
+
+       return 0;
+
+err:
+       gpio_direction_output(gpio_comp_en, 0);
+       gpio_free(gpio_comp_en);
+
+#ifdef CONFIG_SOC_EXYNOS5422
+       if (!IS_ERR_OR_NULL(regulator)) {
+               ret = regulator_disable(regulator);
+               if (unlikely(ret)) {
+                       pr_err("%s: regulator_disable(%s) fail\n", __func__, power_name);
+               }
+               regulator_put(regulator);
+       }
+#endif
+        return ret;
+}
+
+static int fimc_is_fan53555_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+static int fimc_is_ncp6335b_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct fimc_is_core *core;
+       int ret = 0;
+
+       struct device_node *np;
+       int gpio_comp_en;
+
+       BUG_ON(!fimc_is_dev);
+
+       pr_info("%s start\n",__func__);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               pr_err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       np = of_find_compatible_node(NULL, NULL, "samsung,fimc_is_ncp6335b");
+       if(np == NULL) {
+               pr_err("compatible: fail to read, fan_parse_dt\n");
+               return -ENODEV;
+       }
+
+       gpio_comp_en = of_get_named_gpio(np, "comp_en", 0);
+       if (!gpio_is_valid(gpio_comp_en))
+               pr_err("failed to get comp en gpio\n");
+
+       ret = gpio_request(gpio_comp_en,"COMP_EN");
+       if (ret < 0 )
+               pr_err("gpio_request_error(%d)\n",ret);
+
+       gpio_direction_output(gpio_comp_en,1);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               pr_err("%s: SMBUS Byte Data not Supported\n", __func__);
+               ret = -EIO;
+               goto err;
+       }
+
+       core->companion_dcdc.client = client;
+       core->companion_dcdc.type = DCDC_VENDOR_NCP6335B;
+       core->companion_dcdc.get_vout_val = ncp6335b_get_vout_val;
+       core->companion_dcdc.get_vout_str = ncp6335b_get_vout_str;
+       core->companion_dcdc.set_vout = ncp6335b_set_voltage;
+
+       ret = ncp6335b_set_voltage(client, 0xC0);
+       if (ret < 0) {
+               pr_err("%s: error, fail to set voltage\n", __func__);
+               goto err;
+       }
+
+       ret = ncp6335b_read_voltage(client);
+       if (ret < 0) {
+               pr_err("%s: error, fail to read voltage\n", __func__);
+               goto err;
+       }
+
+       pr_info("%s %s: ncp6335b probed\n",
+               dev_driver_string(&client->dev), dev_name(&client->dev));
+
+err:
+       gpio_direction_output(gpio_comp_en,0);
+       gpio_free(gpio_comp_en);
+
+       return ret;
+}
+
+static int fimc_is_ncp6335b_remove(struct i2c_client *client)
+{
+       return 0;
+}
+#endif
+
+static const struct of_device_id exynos_fimc_is_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is",
+       },
+       {
+               .compatible = "samsung,fimc_is_spi0",
+       },
+       {
+               .compatible = "samsung,fimc_is_spi1",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_fimc_is_match);
+
+static struct spi_driver fimc_is_spi0_driver = {
+       .driver = {
+               .name = "fimc_is_spi0",
+               .bus = &spi_bus_type,
+               .owner = THIS_MODULE,
+               .of_match_table = exynos_fimc_is_match,
+       },
+       .probe  = fimc_is_spi_probe,
+       .remove = fimc_is_spi_remove,
+};
+
+module_spi_driver(fimc_is_spi0_driver);
+
+static struct spi_driver fimc_is_spi1_driver = {
+       .driver = {
+               .name = "fimc_is_spi1",
+               .bus = &spi_bus_type,
+               .owner = THIS_MODULE,
+               .of_match_table = exynos_fimc_is_match,
+       },
+       .probe  = fimc_is_spi_probe,
+       .remove = fimc_is_spi_remove,
+};
+
+module_spi_driver(fimc_is_spi1_driver);
+
+#ifdef CONFIG_COMPANION_USE
+static struct of_device_id fan53555_dt_ids[] = {
+        { .compatible = "samsung,fimc_is_fan53555",},
+        {},
+};
+MODULE_DEVICE_TABLE(of, fan53555_dt_ids);
+
+static const struct i2c_device_id fan53555_id[] = {
+        {"fimc_is_fan53555", 0},
+        {}
+};
+MODULE_DEVICE_TABLE(i2c, fan53555_id);
+
+static struct i2c_driver fan53555_driver = {
+        .driver = {
+                .name = "fimc_is_fan53555",
+                .owner  = THIS_MODULE,
+                .of_match_table = fan53555_dt_ids,
+        },
+        .probe = fimc_is_fan53555_probe,
+        .remove = fimc_is_fan53555_remove,
+        .id_table = fan53555_id,
+};
+module_i2c_driver(fan53555_driver);
+
+static struct of_device_id ncp6335b_dt_ids[] = {
+        { .compatible = "samsung,fimc_is_ncp6335b",},
+        {},
+};
+MODULE_DEVICE_TABLE(of, ncp6335b_dt_ids);
+
+static const struct i2c_device_id ncp6335b_id[] = {
+        {"fimc_is_ncp6335b", 0},
+        {}
+};
+MODULE_DEVICE_TABLE(i2c, ncp6335b_id);
+
+static struct i2c_driver ncp6335b_driver = {
+        .driver = {
+                .name = "fimc_is_ncp6335b",
+                .owner  = THIS_MODULE,
+                .of_match_table = ncp6335b_dt_ids,
+        },
+        .probe = fimc_is_ncp6335b_probe,
+        .remove = fimc_is_ncp6335b_remove,
+        .id_table = ncp6335b_id,
+};
+module_i2c_driver(ncp6335b_driver);
+#endif
+
+static struct platform_driver fimc_is_driver = {
+       .probe          = fimc_is_probe,
+       .remove         = fimc_is_remove,
+       .driver = {
+               .name   = FIMC_IS_DRV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &fimc_is_pm_ops,
+               .of_match_table = exynos_fimc_is_match,
+       }
+};
+
+module_platform_driver(fimc_is_driver);
+#else
+static struct platform_driver fimc_is_driver = {
+       .probe          = fimc_is_probe,
+       .remove = __devexit_p(fimc_is_remove),
+       .driver = {
+               .name   = FIMC_IS_DRV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &fimc_is_pm_ops,
+       }
+};
+
+static int __init fimc_is_init(void)
+{
+       int ret = platform_driver_register(&fimc_is_driver);
+       if (ret)
+               err("platform_driver_register failed: %d\n", ret);
+       return ret;
+}
+
+static void __exit fimc_is_exit(void)
+{
+       platform_driver_unregister(&fimc_is_driver);
+}
+module_init(fimc_is_init);
+module_exit(fimc_is_exit);
+#endif
+
+MODULE_AUTHOR("Jiyoung Shin<idon.shin@samsung.com>");
+MODULE_DESCRIPTION("Exynos FIMC_IS2 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-core.h b/drivers/media/platform/exynos/fimc-is/fimc-is-core.h
new file mode 100644 (file)
index 0000000..9f22844
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_CORE_H
+#define FIMC_IS_CORE_H
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+#include <linux/sched/rt.h>
+#endif
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <mach/exynos-fimc-is.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#if defined(CONFIG_VIDEOBUF2_CMA_PHYS)
+#include <media/videobuf2-cma-phys.h>
+#elif defined(CONFIG_VIDEOBUF2_ION)
+#include <media/videobuf2-ion.h>
+#endif
+#ifdef CONFIG_COMPANION_USE
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "fimc-is-companion.h"
+#ifdef CONFIG_SOC_EXYNOS5422
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#endif
+#endif
+
+#include "fimc-is-param.h"
+#include "fimc-is-interface.h"
+#include "fimc-is-framemgr.h"
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-device-ischain.h"
+#include "fimc-is-device-companion.h"
+
+#include "fimc-is-video.h"
+#include "fimc-is-mem.h"
+
+#define FIMC_IS_DRV_NAME                       "exynos-fimc-is"
+
+#define FIMC_IS_COMMAND_TIMEOUT                        (3*HZ)
+#define FIMC_IS_STARTUP_TIMEOUT                        (3*HZ)
+#define FIMC_IS_COMPANION_TIMEOUT              (1*HZ)
+
+#define FIMC_IS_SHUTDOWN_TIMEOUT               (10*HZ)
+#define FIMC_IS_FLITE_STOP_TIMEOUT             (3*HZ)
+
+#define FIMC_IS_SENSOR_MAX_ENTITIES            (1)
+#define FIMC_IS_SENSOR_PAD_SOURCE_FRONT                (0)
+#define FIMC_IS_SENSOR_PADS_NUM                        (1)
+
+#define FIMC_IS_FRONT_MAX_ENTITIES             (1)
+#define FIMC_IS_FRONT_PAD_SINK                 (0)
+#define FIMC_IS_FRONT_PAD_SOURCE_BACK          (1)
+#define FIMC_IS_FRONT_PAD_SOURCE_BAYER         (2)
+#define FIMC_IS_FRONT_PAD_SOURCE_SCALERC       (3)
+#define FIMC_IS_FRONT_PADS_NUM                 (4)
+
+#define FIMC_IS_BACK_MAX_ENTITIES              (1)
+#define FIMC_IS_BACK_PAD_SINK                  (0)
+#define FIMC_IS_BACK_PAD_SOURCE_3DNR           (1)
+#define FIMC_IS_BACK_PAD_SOURCE_SCALERP                (2)
+#define FIMC_IS_BACK_PADS_NUM                  (3)
+
+#define FIMC_IS_MAX_SENSOR_NAME_LEN            (16)
+
+#define FIMC_IS_A5_MEM_SIZE            (0x01400000)
+#define FIMC_IS_REGION_SIZE            (0x00005000)
+#define FIMC_IS_SETFILE_SIZE           (0x00140000)
+#define FIMC_IS_DEBUG_REGION_ADDR      (0x01340000)
+#define FIMC_IS_SHARED_REGION_ADDR     (0x013C0000)
+
+#define FIMC_IS_FW_BASE_MASK           ((1 << 26) - 1)
+
+#define FW_SHARED_OFFSET               FIMC_IS_SHARED_REGION_ADDR
+#define DEBUG_CNT                      (0x0007D000) /* 500KB */
+#define DEBUG_OFFSET                   FIMC_IS_DEBUG_REGION_ADDR
+#define DEBUGCTL_OFFSET                        (DEBUG_OFFSET + DEBUG_CNT)
+
+#define MAX_ODC_INTERNAL_BUF_WIDTH     (2560)  /* 4808 in HW */
+#define MAX_ODC_INTERNAL_BUF_HEIGHT    (1920)  /* 3356 in HW */
+#define SIZE_ODC_INTERNAL_BUF \
+       (MAX_ODC_INTERNAL_BUF_WIDTH * MAX_ODC_INTERNAL_BUF_HEIGHT * 3)
+
+#define MAX_DIS_INTERNAL_BUF_WIDTH     (2400)
+#define MAX_DIS_INTERNAL_BUF_HEIGHT    (1360)
+#define SIZE_DIS_INTERNAL_BUF \
+       (MAX_DIS_INTERNAL_BUF_WIDTH * MAX_DIS_INTERNAL_BUF_HEIGHT * 2)
+
+#define MAX_3DNR_INTERNAL_BUF_WIDTH    (1920)
+#define MAX_3DNR_INTERNAL_BUF_HEIGHT   (1088)
+#define SIZE_DNR_INTERNAL_BUF \
+       (MAX_3DNR_INTERNAL_BUF_WIDTH * MAX_3DNR_INTERNAL_BUF_HEIGHT * 2)
+
+#define NUM_ODC_INTERNAL_BUF           (2)
+#define NUM_DIS_INTERNAL_BUF           (1)
+#define NUM_DNR_INTERNAL_BUF           (2)
+
+#define GATE_IP_ISP                    (0)
+#define GATE_IP_DRC                    (1)
+#define GATE_IP_FD                     (2)
+#define GATE_IP_SCC                    (3)
+#define GATE_IP_SCP                    (4)
+#define GATE_IP_ODC                    (0)
+#define GATE_IP_DIS                    (1)
+#define GATE_IP_DNR                    (2)
+#if defined(CONFIG_SOC_EXYNOS5422)
+#define DVFS_L0                                (600000)
+#define DVFS_L1                                (500000)
+#define DVFS_L1_1                      (480000)
+#define DVFS_L1_2                      (460000)
+#define DVFS_L1_3                      (440000)
+
+#define DVFS_MIF_L0                    (825000)
+#define DVFS_MIF_L1                    (728000)
+#define DVFS_MIF_L2                    (633000)
+#define DVFS_MIF_L3                    (543000)
+#define DVFS_MIF_L4                    (413000)
+#define DVFS_MIF_L5                    (275000)
+
+#define I2C_L0                         (108000000)
+#define I2C_L1                         (36000000)
+#define I2C_L1_1                       (54000000)
+#define I2C_L2                         (21600000)
+#define DVFS_SKIP_FRAME_NUM            (5)
+#elif defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+#define DVFS_L0                                (600000)
+#define DVFS_L1                                (500000)
+#define DVFS_L1_1                      (480000)
+#define DVFS_L1_2                      (460000)
+#define DVFS_L1_3                      (440000)
+
+#define DVFS_MIF_L0                    (800000)
+#define DVFS_MIF_L1                    (733000)
+#define DVFS_MIF_L2                    (667000)
+#define DVFS_MIF_L3                    (533000)
+#define DVFS_MIF_L4                    (400000)
+#define DVFS_MIF_L5                    (266000)
+
+#define I2C_L0                         (83000000)
+#define I2C_L1                         (36000000)
+#define I2C_L1_1                       (54000000)
+#define I2C_L2                         (21600000)
+#define DVFS_SKIP_FRAME_NUM            (5)
+#elif defined(CONFIG_SOC_EXYNOS3470) || defined(CONFIG_SOC_EXYNOS3472) ||defined(CONFIG_SOC_EXYNOS5260) || defined(CONFIG_SOC_EXYNOS4415)
+#define DVFS_L0                                (266000)
+#define DVFS_MIF_L0                    (400000)
+#define I2C_L0                         (108000000)
+#define I2C_L1                         (36000000)
+#define I2C_L1_1                       (54000000)
+#define I2C_L2                         (21600000)
+#endif
+
+#define I2C_RETRY_COUNT         5
+
+#define GET_FIMC_IS_NUM_OF_SUBIP(core, subip) \
+       (core->pdata->subip_info->_ ## subip.valid)
+#define GET_FIMC_IS_NUM_OF_SUBIP2(device, subip) \
+       (((struct fimc_is_core *)device->interface->core)->pdata->subip_info->_ ## subip.valid)
+#define GET_FIMC_IS_VER_OF_SUBIP(core, subip) \
+       ((core)->pdata->subip_info->_##subip.version)
+#define GET_FIMC_IS_VER_OF_SUBIP2(device, subip) \
+       (((struct fimc_is_core *)device->interface->core)->pdata->subip_info->_ ## subip.version)
+#define GET_FIMC_IS_ADDR_OF_SUBIP(core, subip) \
+       ((core)->pdata->subip_info->_##subip.base_addr)
+#define GET_FIMC_IS_ADDR_OF_SUBIP2(device, subip) \
+       (((struct fimc_is_core *)device->interface->core)->pdata->subip_info->_ ## subip.base_addr)
+
+enum fimc_is_debug_device {
+       FIMC_IS_DEBUG_MAIN = 0,
+       FIMC_IS_DEBUG_EC,
+       FIMC_IS_DEBUG_SENSOR,
+       FIMC_IS_DEBUG_ISP,
+       FIMC_IS_DEBUG_DRC,
+       FIMC_IS_DEBUG_FD,
+       FIMC_IS_DEBUG_SDK,
+       FIMC_IS_DEBUG_SCALERC,
+       FIMC_IS_DEBUG_ODC,
+       FIMC_IS_DEBUG_DIS,
+       FIMC_IS_DEBUG_TDNR,
+       FIMC_IS_DEBUG_SCALERP
+};
+
+enum fimc_is_debug_target {
+       FIMC_IS_DEBUG_UART = 0,
+       FIMC_IS_DEBUG_MEMORY,
+       FIMC_IS_DEBUG_DCC3
+};
+
+enum fimc_is_front_input_entity {
+       FIMC_IS_FRONT_INPUT_NONE = 0,
+       FIMC_IS_FRONT_INPUT_SENSOR,
+};
+
+enum fimc_is_front_output_entity {
+       FIMC_IS_FRONT_OUTPUT_NONE = 0,
+       FIMC_IS_FRONT_OUTPUT_BACK,
+       FIMC_IS_FRONT_OUTPUT_BAYER,
+       FIMC_IS_FRONT_OUTPUT_SCALERC,
+};
+
+enum fimc_is_back_input_entity {
+       FIMC_IS_BACK_INPUT_NONE = 0,
+       FIMC_IS_BACK_INPUT_FRONT,
+};
+
+enum fimc_is_back_output_entity {
+       FIMC_IS_BACK_OUTPUT_NONE = 0,
+       FIMC_IS_BACK_OUTPUT_3DNR,
+       FIMC_IS_BACK_OUTPUT_SCALERP,
+};
+
+enum fimc_is_front_state {
+       FIMC_IS_FRONT_ST_POWERED = 0,
+       FIMC_IS_FRONT_ST_STREAMING,
+       FIMC_IS_FRONT_ST_SUSPENDED,
+};
+
+enum fimc_is_clck_gate_mode {
+       CLOCK_GATE_MODE_HOST = 0,
+       CLOCK_GATE_MODE_FW,
+};
+
+struct fimc_is_sysfs_debug {
+       unsigned int en_dvfs;
+       unsigned int en_clk_gate;
+       unsigned int clk_gate_mode;
+};
+
+#ifdef CONFIG_COMPANION_USE
+struct fimc_is_spi_gpio {
+        char *spi_sclk;
+        char *spi_ssn;
+        char *spi_miso;
+        char *spi_mois;
+};
+#endif
+
+struct fimc_is_core {
+       struct platform_device                  *pdev;
+       struct resource                         *regs_res;
+       void __iomem                            *regs;
+       int                                     irq;
+       u32                                     id;
+       u32                                     debug_cnt;
+       atomic_t                                rsccount;
+       unsigned long                           state;
+
+       /* depended on isp */
+       struct exynos_platform_fimc_is          *pdata;
+
+       struct fimc_is_resourcemgr              resourcemgr;
+       struct fimc_is_groupmgr                 groupmgr;
+
+       struct fimc_is_minfo                    minfo;
+       struct fimc_is_mem                      mem;
+       struct fimc_is_interface                interface;
+
+       struct fimc_is_device_sensor            sensor[FIMC_IS_MAX_NODES];
+       struct fimc_is_device_ischain           ischain[FIMC_IS_MAX_NODES];
+       struct fimc_is_device_companion         *companion;
+
+       struct v4l2_device                      v4l2_dev;
+
+       /* 0-bayer, 1-scalerC, 2-3DNR, 3-scalerP */
+       struct fimc_is_video                    video_3a0;
+       struct fimc_is_video                    video_3a1;
+       struct fimc_is_video                    video_isp;
+       struct fimc_is_video                    video_scc;
+       struct fimc_is_video                    video_scp;
+       struct fimc_is_video                    video_vdc;
+       struct fimc_is_video                    video_vdo;
+       struct fimc_is_video                    video_3a0c;
+       struct fimc_is_video                    video_3a1c;
+
+       /* spi */
+       struct spi_device                       *spi0;
+       struct spi_device                       *spi1;
+
+#if defined(CONFIG_COMPANION_USE)
+       struct i2c_client                       *client0;
+#endif
+#if defined(CONFIG_OIS_USE)
+       struct i2c_client                       *client1;
+#endif
+#ifdef CONFIG_AF_HOST_CONTROL
+       struct i2c_client                       *client2;
+#endif
+       struct i2c_client                       *eeprom_client0;
+       struct i2c_client                       *eeprom_client1;
+
+#ifdef CONFIG_COMPANION_USE
+       struct dcdc_power                       companion_dcdc;
+       struct fimc_is_spi_gpio                 spi_gpio;
+       u32                                     companion_spi_channel;
+       bool                                    use_two_spi_line;
+#endif
+       u32                                     use_sensor_dynamic_voltage_mode;
+       struct mutex                            spi_lock;
+#ifdef CONFIG_OIS_USE
+       bool                                    use_ois;
+       int                                     pin_ois_en;
+       bool                                    ois_ver_read;
+#endif /* CONFIG_OIS_USE */
+       bool                                    use_ois_hsi2c;
+       bool                                    use_module_check;
+#ifdef USE_ION_ALLOC
+       struct ion_client    *fimc_ion_client;
+#endif
+       bool                                    running_rear_camera;
+       bool                                    running_front_camera;
+};
+
+#if defined(CONFIG_VIDEOBUF2_CMA_PHYS)
+extern const struct fimc_is_vb2 fimc_is_vb2_cma;
+#elif defined(CONFIG_VIDEOBUF2_ION)
+extern const struct fimc_is_vb2 fimc_is_vb2_ion;
+#endif
+
+extern struct device *fimc_is_dev;
+
+void fimc_is_mem_suspend(void *alloc_ctxes);
+void fimc_is_mem_resume(void *alloc_ctxes);
+void fimc_is_mem_cache_clean(const void *start_addr, unsigned long size);
+void fimc_is_mem_cache_inv(const void *start_addr, unsigned long size);
+int fimc_is_init_set(struct fimc_is_core *dev , u32 val);
+int fimc_is_load_fw(struct fimc_is_core *dev);
+int fimc_is_load_setfile(struct fimc_is_core *dev);
+int fimc_is_otf_close(struct fimc_is_device_ischain *ischain);
+int fimc_is_spi_reset(void *buf, u32 rx_addr, size_t size);
+int fimc_is_spi_read(void *buf, u32 rx_addr, size_t size);
+int fimc_is_runtime_suspend(struct device *dev);
+int fimc_is_runtime_resume(struct device *dev);
+
+#define CALL_POPS(s, op, args...) (((s)->pdata->op) ? ((s)->pdata->op(args)) : -EPERM)
+
+#endif /* FIMC_IS_CORE_H_ */
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-af.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-af.c
new file mode 100644 (file)
index 0000000..91ed4b9
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#include <mach/pinctrl-samsung.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-interface.h"
+//#include "fimc-is-sec-define.h"
+#include "fimc-is-device-ischain.h"
+#include "fimc-is-dt.h"
+#include "fimc-is-device-af.h"
+
+#define FIMC_IS_AF_DEV_NAME "exynos-fimc-is-af"
+static int af_noise_count;
+
+static struct remove_af_noise af_sensor_interface = {
+       .af_pdata = NULL,
+       .af_func = NULL,
+};
+
+static void fimc_is_af_i2c_config(struct i2c_client *client, bool onoff)
+{
+       struct device *i2c_dev = client->dev.parent->parent;
+       struct pinctrl *pinctrl_i2c = NULL;
+
+       info("(%s):onoff(%d)\n", __func__, onoff);
+       if (onoff) {
+               /* ON */
+               pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, 0));
+               pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, 0));
+
+               pinctrl_i2c = devm_pinctrl_get_select(i2c_dev, "on_i2c");
+               if (IS_ERR_OR_NULL(pinctrl_i2c)) {
+                       printk(KERN_ERR "%s: Failed to configure i2c pin\n", __func__);
+               } else {
+                       devm_pinctrl_put(pinctrl_i2c);
+               }
+       } else {
+               /* OFF */
+               pinctrl_i2c = devm_pinctrl_get_select(i2c_dev, "off_i2c");
+               if (IS_ERR_OR_NULL(pinctrl_i2c)) {
+                       printk(KERN_ERR "%s: Failed to configure i2c pin\n", __func__);
+               } else {
+                       devm_pinctrl_put(pinctrl_i2c);
+               }
+
+               pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+               pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+    }
+}
+
+int fimc_is_af_i2c_read(struct i2c_client *client, u16 addr, u16 *data)
+{
+       int err;
+       u8 rxbuf[2], txbuf[2];
+       struct i2c_msg msg[2];
+
+       txbuf[0] = (addr & 0xff00) >> 8;
+       txbuf[1] = (addr & 0xff);
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = txbuf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 2;
+       msg[1].buf = rxbuf;
+
+       err = i2c_transfer(client->adapter, msg, 2);
+       if (unlikely(err != 2)) {
+               err("%s: register read fail err = %d\n", __func__, err);
+               return -EIO;
+       }
+
+       *data = ((rxbuf[0] << 8) | rxbuf[1]);
+       return 0;
+}
+
+int fimc_is_af_i2c_write(struct i2c_client *client ,u16 addr, u16 data)
+{
+        int retries = I2C_RETRY_COUNT;
+        int ret = 0, err = 0;
+        u8 buf[4] = {0,};
+        struct i2c_msg msg = {
+                .addr   = client->addr,
+                .flags  = 0,
+                .len    = 4,
+                .buf    = buf,
+        };
+
+        buf[0] = addr >> 8;
+        buf[1] = addr;
+        buf[2] = data >> 8;
+        buf[3] = data & 0xff;
+
+#if 0
+        pr_info("%s : W(0x%02X%02X%02X%02X)\n",__func__, buf[0], buf[1], buf[2], buf[3]);
+#endif
+
+        do {
+                ret = i2c_transfer(client->adapter, &msg, 1);
+                if (likely(ret == 1))
+                        break;
+
+                usleep_range(10000,11000);
+                err = ret;
+        } while (--retries > 0);
+
+        /* Retry occured */
+        if (unlikely(retries < I2C_RETRY_COUNT)) {
+                err("i2c_write: error %d, write (%04X, %04X), retry %d\n",
+                        err, addr, data, I2C_RETRY_COUNT - retries);
+        }
+
+        if (unlikely(ret != 1)) {
+                err("I2C does not work\n\n");
+                return -EIO;
+        }
+
+        return 0;
+}
+
+int fimc_is_af_ldo_enable(char *name, bool on)
+{
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       struct regulator *regulator = NULL;
+       struct platform_device *pdev = NULL;
+       int ret = 0;
+
+       BUG_ON(!core);
+       BUG_ON(!core->pdev);
+
+       pdev = core->pdev;
+
+       regulator = regulator_get(&pdev->dev, name);
+       if (IS_ERR_OR_NULL(regulator)) {
+               err("%s : regulator_get(%s) fail\n", __func__, name);
+               return -EINVAL;
+       }
+
+       if (on) {
+               if (regulator_is_enabled(regulator)) {
+                       pr_info("%s: regulator is already enabled\n", name);
+                       ret = 0;
+               } else {
+                       ret = regulator_enable(regulator);
+                       if (ret) {
+                               err("%s : regulator_enable(%s) fail\n", __func__, name);
+                               ret = -EINVAL;
+                       }
+               }
+       } else {
+               if (!regulator_is_enabled(regulator)) {
+                       pr_info("%s: regulator is already disabled\n", name);
+                       ret = 0;
+               } else {
+                       ret = regulator_disable(regulator);
+                       if (ret) {
+                               err("%s : regulator_disable(%s) fail\n", __func__, name);
+                               ret = -EINVAL;
+                       }
+               }
+       }
+
+       regulator_put(regulator);
+
+       return ret;
+}
+
+int fimc_is_af_power(struct fimc_is_device_af *af_device, bool onoff)
+{
+       int ret = 0;
+#ifdef CONFIG_OIS_USE
+       int pin_ois_en = af_device->core->pin_ois_en;
+#endif
+
+       /*CAM_AF_2.8V_AP*/
+       ret = fimc_is_af_ldo_enable("CAM_AF_2.8V_AP", onoff);
+       if (ret) {
+               err("failed to power control CAM_AF_2.8V_AP, onoff = %d", onoff);
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_OIS_USE
+       /* OIS_VDD_2.8V */
+       if (gpio_is_valid(pin_ois_en)) {
+               if (onoff) {
+                       gpio_request_one(pin_ois_en, GPIOF_OUT_INIT_HIGH, "CAM_GPIO_OUTPUT_HIGH");
+               } else {
+                       gpio_request_one(pin_ois_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               }
+               gpio_free(pin_ois_en);
+       }
+
+       /* OIS_VM_2.8V */
+       ret = fimc_is_af_ldo_enable("OIS_VM_2.8V", onoff);
+       if (ret) {
+               err("failed to power control OIS_VM_2.8V, onoff = %d", onoff);
+               return -EINVAL;
+       }
+#endif
+
+       /*CAM_IO_1.8V_AP*/
+       ret = fimc_is_af_ldo_enable("CAM_IO_1.8V_AP", onoff);
+       if (ret) {
+               err("failed to power control CAM_IO_1.8V_AP, onoff = %d", onoff);
+               return -EINVAL;
+       }
+
+       usleep_range(5000,5000);
+       return ret;
+}
+
+bool fimc_is_check_regulator_status(char *name)
+{
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       struct regulator *regulator = NULL;
+       struct platform_device *pdev = NULL;
+       int ret = 0;
+
+       BUG_ON(!core);
+       BUG_ON(!core->pdev);
+
+       pdev = core->pdev;
+
+       regulator = regulator_get(&pdev->dev, name);
+       if (IS_ERR_OR_NULL(regulator)) {
+               err("%s : regulator_get(%s) fail\n", __func__, name);
+               return false;
+       }
+       if (regulator_is_enabled(regulator)) {
+               ret = true;
+       } else {
+               ret = false;
+       }
+
+       regulator_put(regulator);
+       return ret;
+}
+
+int16_t fimc_is_af_enable(void *device, bool onoff)
+{
+       int ret = 0;
+       struct fimc_is_device_af *af_device = (struct fimc_is_device_af *)device;
+       struct fimc_is_core *core;
+       bool af_regulator = false, io_regulator = false;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -ENODEV;
+       }
+
+       pr_info("af_noise : running_rear_camera = %d, onoff = %d\n", core->running_rear_camera, onoff);
+       if (!core->running_rear_camera) {
+               if (core->use_ois_hsi2c) {
+                       fimc_is_af_i2c_config(af_device->client, true);
+               }
+
+               if (onoff) {
+                       fimc_is_af_power(af_device, true);
+                       ret = fimc_is_af_i2c_write(af_device->client, 0x02, 0x00);
+                       if (ret) {
+                               err("i2c write fail\n");
+                               goto power_off;
+                       }
+
+                       ret = fimc_is_af_i2c_write(af_device->client, 0x00, 0x00);
+                       if (ret) {
+                               err("i2c write fail\n");
+                               goto power_off;
+                       }
+
+                       ret = fimc_is_af_i2c_write(af_device->client, 0x01, 0x00);
+                       if (ret) {
+                               err("i2c write fail\n");
+                               goto power_off;
+                       }
+                       af_noise_count++;
+                       pr_info("af_noise : count = %d\n", af_noise_count);
+               } else {
+                       /* Check the Power Pins */
+                       af_regulator = fimc_is_check_regulator_status("CAM_AF_2.8V_AP");
+                       io_regulator = fimc_is_check_regulator_status("CAM_IO_1.8V_AP");
+
+                       if (af_regulator && io_regulator) {
+                               ret = fimc_is_af_i2c_write(af_device->client, 0x02, 0x40);
+                               if (ret) {
+                                       err("i2c write fail\n");
+                               }
+                               fimc_is_af_power(af_device, false);
+                       } else {
+                               pr_info("already power off.(%d)\n", __LINE__);
+                       }
+               }
+
+               if (core->use_ois_hsi2c) {
+                       fimc_is_af_i2c_config(af_device->client, false);
+               }
+       }
+
+       return ret;
+
+power_off:
+       if (!core->running_rear_camera) {
+               if (core->use_ois_hsi2c) {
+                       fimc_is_af_i2c_config(af_device->client, false);
+               }
+
+               af_regulator = fimc_is_check_regulator_status("CAM_AF_2.8V_AP");
+               io_regulator = fimc_is_check_regulator_status("CAM_IO_1.8V_AP");
+               if (af_regulator && io_regulator) {
+                       fimc_is_af_power(af_device, false);
+               } else {
+                       pr_info("already power off.(%d)\n", __LINE__);
+               }
+       }
+       return ret;
+}
+
+int16_t fimc_is_af_move_lens(struct fimc_is_core *core)
+{
+       int ret = 0;
+       struct i2c_client *client = core->client2;
+
+       pr_info("fimc_is_af_move_lens : running_rear_camera = %d\n", core->running_rear_camera);
+       if (!core->running_rear_camera) {
+               ret = fimc_is_af_i2c_write(client, 0x00, 0x80);
+               if (ret) {
+                       err("i2c write fail\n");
+               }
+
+               ret = fimc_is_af_i2c_write(client, 0x01, 0x00);
+               if (ret) {
+                       err("i2c write fail\n");
+               }
+
+               ret = fimc_is_af_i2c_write(client, 0x02, 0x00);
+               if (ret) {
+                       err("i2c write fail\n");
+               }
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_SENSORS_SSP_BBD
+extern int remove_af_noise_register(struct remove_af_noise *af_cam);
+extern void remove_af_noise_unregister(struct remove_af_noise *af_cam);
+#endif
+static int fimc_is_af_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct fimc_is_device_af *device;
+       struct fimc_is_core *core;
+#ifdef CONFIG_SENSORS_SSP_BBD
+       int ret;
+#endif
+
+       if (fimc_is_dev == NULL) {
+               warn("fimc_is_dev is not yet probed");
+               client->dev.init_name = FIMC_IS_AF_DEV_NAME;
+               return -EPROBE_DEFER;
+       }
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core)
+               return -EINVAL;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               err("No I2C functionality found\n");
+               return -ENODEV;
+       }
+
+       device = kzalloc(sizeof(struct fimc_is_device_af), GFP_KERNEL);
+       if (!device) {
+               err("fimc_is_device_companion is NULL");
+               return -ENOMEM;
+       }
+
+       core->client2 = client;
+       device->client = client;
+       device->core = core;
+       af_noise_count = 0;
+
+       af_sensor_interface.af_pdata = device;
+       af_sensor_interface.af_func = &fimc_is_af_enable;
+#ifdef CONFIG_SENSORS_SSP_BBD
+       ret = remove_af_noise_register(&af_sensor_interface);
+       if (ret)
+               err("reduce_af_noise_register failed: %d\n", ret);
+#endif
+       i2c_set_clientdata(client, device);
+
+       return 0;
+}
+
+static int fimc_is_af_remove(struct i2c_client *client)
+{
+#ifdef CONFIG_SENSORS_SSP_BBD
+       remove_af_noise_unregister(&af_sensor_interface);
+#endif
+       return 0;
+}
+
+static const struct i2c_device_id af_id[] = {
+       {FIMC_IS_AF_DEV_NAME, 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, af_id);
+
+#ifdef CONFIG_OF
+static struct of_device_id af_dt_ids[] = {
+       { .compatible = "samsung,af",},
+       {},
+};
+#endif
+
+static struct i2c_driver af_i2c_driver = {
+       .driver = {
+                  .name = FIMC_IS_AF_DEV_NAME,
+                  .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+                  .of_match_table = af_dt_ids,
+#endif
+       },
+       .probe = fimc_is_af_probe,
+       .remove = fimc_is_af_remove,
+       .id_table = af_id,
+};
+
+module_i2c_driver(af_i2c_driver);
+
+MODULE_DESCRIPTION("AF driver for remove noise");
+MODULE_AUTHOR("kyoungho yun <kyoungho.yun@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-af.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-af.h
new file mode 100644 (file)
index 0000000..9cd2e17
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS AF driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+struct fimc_is_device_af {
+       struct v4l2_device                              v4l2_dev;
+       struct platform_device                          *pdev;
+       unsigned long                                   state;
+       struct exynos_platform_fimc_is_sensor           *pdata;
+       struct i2c_client                       *client;
+       struct fimc_is_core             *core;
+};
+
+struct remove_af_noise {
+       void     *af_pdata;
+       int16_t (*af_func)(void *, bool);
+};
+
+int fimc_is_af_i2c_read(struct i2c_client *client, u16 addr, u16 *data);
+int fimc_is_af_i2c_write(struct i2c_client *client ,u16 addr, u16 data);
+int16_t fimc_is_af_enable(void *device, bool onoff);
+int16_t fimc_is_af_move_lens(struct fimc_is_core *core);
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-companion.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-companion.c
new file mode 100644 (file)
index 0000000..eeac2eb
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+#include <linux/i2c.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/pinctrl-samsung.h>
+
+#include "fimc-is-video.h"
+#include "fimc-is-dt.h"
+#include "fimc-is-device-companion.h"
+#include "fimc-is-sec-define.h"
+#if defined(CONFIG_OIS_USE)
+#include "fimc-is-device-ois.h"
+#endif
+#ifdef CONFIG_COMPANION_USE
+#include "fimc-is-companion-dt.h"
+#endif
+extern int fimc_is_comp_video_probe(void *data);
+
+int fimc_is_companion_wait(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+
+       ret = wait_event_timeout(device->init_wait_queue,
+               (device->companion_status == FIMC_IS_COMPANION_OPENDONE),
+               FIMC_IS_COMPANION_TIMEOUT);
+       if (ret) {
+               ret = 0;
+       } else {
+               err("timeout");
+               device->companion_status = FIMC_IS_COMPANION_IDLE;
+               ret = -ETIME;
+       }
+
+       return ret;
+}
+
+static void fimc_is_companion_wakeup(struct fimc_is_device_companion *device)
+{
+       wake_up(&device->init_wait_queue);
+}
+
+static int fimc_is_companion_mclk_on(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct platform_device *pdev;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdev = device->pdev;
+       pdata = device->pdata;
+
+       if (test_bit(FIMC_IS_COMPANION_MCLK_ON, &device->state)) {
+               err("%s : already clk on", __func__);
+               goto p_err;
+       }
+
+       if (!pdata->mclk_on) {
+               err("mclk_on is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->mclk_on(pdev, pdata->scenario, pdata->mclk_ch);
+       if (ret) {
+               err("mclk_on is fail(%d)", ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_COMPANION_MCLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_companion_mclk_off(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct platform_device *pdev;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdev = device->pdev;
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_COMPANION_MCLK_ON, &device->state)) {
+               err("%s : already clk off", __func__);
+               goto p_err;
+       }
+
+       if (!pdata->mclk_off) {
+               err("mclk_off is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->mclk_off(pdev, pdata->scenario, pdata->mclk_ch);
+       if (ret) {
+               err("mclk_off is fail(%d)", ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_COMPANION_MCLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_companion_iclk_on(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct platform_device *pdev;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdev = device->pdev;
+       pdata = device->pdata;
+
+       if (test_bit(FIMC_IS_COMPANION_ICLK_ON, &device->state)) {
+               err("%s : already clk on", __func__);
+               goto p_err;
+       }
+
+       if (!pdata->iclk_cfg) {
+               err("iclk_cfg is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!pdata->iclk_on) {
+               err("iclk_on is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->iclk_cfg(pdev, pdata->scenario, 0);
+       if (ret) {
+               err("iclk_cfg is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = pdata->iclk_on(pdev, pdata->scenario, 0);
+       if (ret) {
+               err("iclk_on is fail(%d)", ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_COMPANION_ICLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_companion_iclk_off(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct platform_device *pdev;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdev = device->pdev;
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_COMPANION_ICLK_ON, &device->state)) {
+               err("%s : already clk off", __func__);
+               goto p_err;
+       }
+
+       if (!pdata->iclk_off) {
+               err("iclk_off is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->iclk_off(pdev, pdata->scenario, 0);
+       if (ret) {
+               err("iclk_off is fail(%d)", ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_COMPANION_ICLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_companion_gpio_on(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       struct fimc_is_from_info *sysfs_finfo;
+       struct exynos_sensor_pin (*pin_ctrls)[2][GPIO_CTRL_MAX];
+#endif
+       struct fimc_is_core *core;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       pin_ctrls = pdata->pin_ctrls;
+#endif
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+
+       if (test_bit(FIMC_IS_COMPANION_GPIO_ON, &device->state)) {
+               err("%s : already gpio on", __func__);
+               goto p_err;
+       }
+
+       if (!pdata->gpio_cfg) {
+               err("gpio_cfg is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       core->running_rear_camera = true;
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       if(core->use_sensor_dynamic_voltage_mode) {
+               fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+               if (pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][0].name != NULL &&
+                       !strcmp(pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][0].name, "CAM_SEN_A2.8V_AP")) {
+                       if (sysfs_finfo->header_ver[1] == '1' && sysfs_finfo->header_ver[2] == '6' && sysfs_finfo->header_ver[4] == 'L') {
+                               pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][0].voltage = 2950000;
+                               info("LSI Sensor EVT2.4 voltage(%d)\n", pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][0].voltage);
+                       } else {
+                               pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][0].voltage = 2800000;
+                       }
+               }
+
+#if defined(CONFIG_SOC_EXYNOS5433)
+               if (pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][1].name != NULL &&
+                       !strcmp(pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][1].name, "CAM_SEN_CORE_1.2V_AP")) {
+                       if (sysfs_finfo->header_ver[1] == '1' && sysfs_finfo->header_ver[2] == '6' && sysfs_finfo->header_ver[4] == 'S') {
+                               pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][1].voltage = 1050000;
+                               info("SONY Sensor  voltage(%d)\n", pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][1].voltage);
+                       } else {
+                               pin_ctrls[pdata->scenario][GPIO_SCENARIO_ON][1].voltage = 1200000;
+                       }
+               }
+#endif
+       }
+#endif
+
+       ret = pdata->gpio_cfg(device->pdev, pdata->scenario, GPIO_SCENARIO_ON);
+       if (ret) {
+               err("gpio_cfg is fail(%d)", ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_COMPANION_GPIO_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_companion_gpio_off(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_COMPANION_GPIO_ON, &device->state)) {
+               err("%s : already gpio off", __func__);
+               goto p_err;
+       }
+
+       if (!pdata->gpio_cfg) {
+               err("gpio_cfg is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->gpio_cfg(device->pdev, pdata->scenario, GPIO_SCENARIO_OFF);
+       if (ret) {
+               err("gpio_cfg is fail(%d)", ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_COMPANION_GPIO_ON, &device->state);
+
+p_err:
+       core->running_rear_camera = false;
+
+       return ret;
+}
+
+
+int fimc_is_companion_open(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       /* Workaround for Host to use ISP-SPI. Will be removed later.*/
+       struct fimc_is_spi_gpio *spi_gpio;
+       static char companion_fw_name[100];
+       static char master_setf_name[100];
+       static char mode_setf_name[100];
+#if !defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+       static char fw_name[100];
+       static char setf_name[100];
+#endif
+
+       BUG_ON(!device);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       spi_gpio = &core->spi_gpio;
+
+       if (test_bit(FIMC_IS_COMPANION_OPEN, &device->state)) {
+               err("already open");
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       device->companion_status = FIMC_IS_COMPANION_OPENNING;
+       core->running_rear_camera = true;
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_get_sync(&device->pdev->dev);
+#else
+       fimc_is_companion_runtime_resume(&device->pdev->dev);
+#endif
+#if !defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+       ret = fimc_is_sec_fw_sel(core, &device->pdev->dev, fw_name, setf_name, false);
+       if (ret < 0) {
+               err("failed to select firmware (%d)", ret);
+               goto p_err_pm;
+       }
+#endif
+       ret = fimc_is_sec_concord_fw_sel(core, &device->pdev->dev, companion_fw_name, master_setf_name, mode_setf_name);
+
+       /* TODO: loading firmware */
+       fimc_is_s_int_comb_isp(core, false, INTMR2_INTMCIS22);
+
+       // Workaround for Host to use ISP-SPI. Will be removed later.
+       /* set pin output for Host to use SPI*/
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+               PINCFG_PACK(PINCFG_TYPE_FUNC, FUNC_OUTPUT));
+
+       fimc_is_set_spi_config(spi_gpio, FIMC_IS_SPI_FUNC, false);
+
+       if (fimc_is_comp_is_valid(core) == 0) {
+               ret = fimc_is_comp_loadfirm(core);
+               if (ret) {
+                       err("fimc_is_comp_loadfirm() fail");
+                       goto p_err_pm;
+                }
+               ret = fimc_is_comp_loadcal(core);
+               if (ret) {
+                       err("fimc_is_comp_loadcal() fail");
+               }
+
+               fimc_is_power_binning(core);
+
+               ret = fimc_is_comp_loadsetf(core);
+               if (ret) {
+                       err("fimc_is_comp_loadsetf() fail");
+                       goto p_err_pm;
+               }
+       }
+
+       // Workaround for Host to use ISP-SPI. Will be removed later.
+       /* Set SPI pins to low before changing pin function */
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_sclk,
+               PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+               PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_miso,
+               PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_mois,
+               PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+
+       /* Set pin function for A5 to use SPI */
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+               PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+
+       set_bit(FIMC_IS_COMPANION_OPEN, &device->state);
+       device->companion_status = FIMC_IS_COMPANION_OPENDONE;
+       fimc_is_companion_wakeup(device);
+
+#if defined(CONFIG_OIS_USE)
+       if(core->use_ois) {
+               if (!core->use_ois_hsi2c) {
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 1));
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 1));
+               }
+
+               if (!core->ois_ver_read) {
+                       fimc_is_ois_check_fw(core);
+               }
+
+               fimc_is_ois_exif_data(core);
+
+               if (!core->use_ois_hsi2c) {
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+               }
+       }
+#endif
+
+       info("[COMP:D] %s(%d)status(%d)\n", __func__, ret, device->companion_status);
+       return ret;
+
+p_err_pm:
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_put_sync(&device->pdev->dev);
+#else
+       fimc_is_companion_runtime_suspend(&device->pdev->dev);
+#endif
+
+p_err:
+       err("[COMP:D] open fail(%d)status(%d)", ret, device->companion_status);
+       return ret;
+}
+
+int fimc_is_companion_close(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       u32 timeout;
+#endif
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -EINVAL;
+       }
+
+       BUG_ON(!device);
+
+       if (!test_bit(FIMC_IS_COMPANION_OPEN, &device->state)) {
+               err("already close");
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_put_sync(&device->pdev->dev);
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       if (core != NULL && !test_bit(FIMC_IS_ISCHAIN_POWER_ON, &core->state)) {
+               warn("only companion device closing after open..");
+               timeout = 2000;
+               while ((readl(PMUREG_CAM1_STATUS) & 0x1) && timeout) {
+                       timeout--;
+                       usleep_range(1000, 1000);
+                       if (!(timeout % 100))
+                               warn("wait for CAM1 power down..(%d)", timeout);
+               }
+               if (timeout == 0)
+                       err("CAM1 power down failed(CAM1:0x%08x, A5:0x%08x)\n",
+                                       readl(PMUREG_CAM1_STATUS), readl(PMUREG_ISP_ARM_STATUS));
+       }
+#endif
+#else
+       fimc_is_companion_runtime_suspend(&device->pdev->dev);
+#endif /* CONFIG_PM_RUNTIME */
+
+       clear_bit(FIMC_IS_COMPANION_OPEN, &device->state);
+
+p_err:
+       core->running_rear_camera = false;
+       device->companion_status = FIMC_IS_COMPANION_IDLE;
+       info("[COMP:D] %s(%d)\n", __func__, ret);
+       return ret;
+}
+
+static int fimc_is_companion_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_device_companion *device;
+       void *pdata;
+
+       BUG_ON(!pdev);
+
+       if (fimc_is_dev == NULL) {
+               warn("fimc_is_dev is not yet probed");
+               pdev->dev.init_name = FIMC_IS_COMPANION_DEV_NAME;
+               return -EPROBE_DEFER;
+       }
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -EINVAL;
+       }
+
+
+       device = kzalloc(sizeof(struct fimc_is_device_companion), GFP_KERNEL);
+       if (!device) {
+               err("fimc_is_device_companion is NULL");
+               return -ENOMEM;
+       }
+
+       init_waitqueue_head(&device->init_wait_queue);
+
+       device->companion_status = FIMC_IS_COMPANION_IDLE;
+
+#ifdef CONFIG_OF
+       ret = fimc_is_companion_parse_dt(pdev);
+       if (ret) {
+               err("parsing device tree is fail(%d)", ret);
+               goto p_err;
+       }
+#endif
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+               err("pdata is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device->pdev = pdev;
+       device->private_data = core;
+       device->regs = core->regs;
+       device->pdata = pdata;
+       platform_set_drvdata(pdev, device);
+       device_init_wakeup(&pdev->dev, true);
+       core->companion = device;
+#ifdef CONFIG_OIS_USE
+       core->pin_ois_en = device->pdata->pin_ois_en;
+#endif
+
+       /* init state */
+       clear_bit(FIMC_IS_COMPANION_OPEN, &device->state);
+       clear_bit(FIMC_IS_COMPANION_MCLK_ON, &device->state);
+       clear_bit(FIMC_IS_COMPANION_ICLK_ON, &device->state);
+       clear_bit(FIMC_IS_COMPANION_GPIO_ON, &device->state);
+
+       ret = v4l2_device_register(&pdev->dev, &device->v4l2_dev);
+       if (ret) {
+               err("v4l2_device_register is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_comp_video_probe(device);
+       if (ret) {
+               err("fimc_is_companion_video_probe is fail(%d)", ret);
+               goto p_err;
+       }
+
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_enable(&pdev->dev);
+#endif
+
+       info("[COMP:D] %s(%d)\n", __func__, ret);
+
+       return ret;
+
+p_err:
+       kfree(device);
+       return ret;
+}
+
+static int fimc_is_companion_remove(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       info("%s\n", __func__);
+
+       return ret;
+}
+
+static int fimc_is_companion_suspend(struct device *dev)
+{
+       int ret = 0;
+
+       info("%s\n", __func__);
+
+       return ret;
+}
+
+static int fimc_is_companion_resume(struct device *dev)
+{
+       int ret = 0;
+
+       info("%s\n", __func__);
+
+       return ret;
+}
+
+int fimc_is_companion_runtime_suspend(struct device *dev)
+{
+       int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_device_companion *device;
+#ifdef CONFIG_AF_HOST_CONTROL
+       struct fimc_is_core *core;
+#endif
+
+       info("%s\n", __func__);
+
+#ifdef CONFIG_AF_HOST_CONTROL
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -EINVAL;
+       }
+#endif
+       device = (struct fimc_is_device_companion *)platform_get_drvdata(pdev);
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto err_dev_null;
+       }
+
+       /* gpio uninit */
+       ret = fimc_is_companion_gpio_off(device);
+       if (ret) {
+               err("fimc_is_companion_gpio_off is fail(%d)", ret);
+               goto p_err;
+       }
+
+       /* periperal internal clock off */
+       ret = fimc_is_companion_iclk_off(device);
+       if (ret) {
+               err("fimc_is_companion_iclk_off is fail(%d)", ret);
+               goto p_err;
+       }
+
+       /* companion clock off */
+       ret = fimc_is_companion_mclk_off(device);
+       if (ret) {
+               err("fimc_is_companion_mclk_off is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       info("[COMP:D] %s(%d)\n", __func__, ret);
+err_dev_null:
+       return ret;
+}
+
+int fimc_is_companion_runtime_resume(struct device *dev)
+{
+       int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_device_companion *device;
+#ifdef CONFIG_AF_HOST_CONTROL
+       struct fimc_is_core *core;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -EINVAL;
+       }
+#endif
+       device = (struct fimc_is_device_companion *)platform_get_drvdata(pdev);
+       if (!device) {
+               err("device is NULL");
+               return -EINVAL;
+       }
+
+       /* Sensor clock on */
+       ret = fimc_is_companion_mclk_on(device);
+       if (ret) {
+               err("fimc_is_companion_mclk_on is fail(%d)", ret);
+               goto p_err;
+       }
+
+       /* gpio init */
+       ret = fimc_is_companion_gpio_on(device);
+       if (ret) {
+               err("fimc_is_companion_gpio_on is fail(%d)", ret);
+               goto p_err;
+       }
+
+       /* periperal internal clock on */
+       ret = fimc_is_companion_iclk_on(device);
+       if (ret) {
+               err("fimc_is_companion_iclk_on is fail(%d)", ret);
+               goto p_err;
+       }
+p_err:
+       info("[COMP:D] %s(%d)\n", __func__, ret);
+       return ret;
+}
+
+static const struct dev_pm_ops fimc_is_companion_pm_ops = {
+       .suspend                = fimc_is_companion_suspend,
+       .resume                 = fimc_is_companion_resume,
+       .runtime_suspend        = fimc_is_companion_runtime_suspend,
+       .runtime_resume         = fimc_is_companion_runtime_resume,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_companion_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-companion",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_fimc_is_companion_match);
+
+static struct platform_driver fimc_is_companion_driver = {
+       .probe  = fimc_is_companion_probe,
+       .remove = fimc_is_companion_remove,
+       .driver = {
+               .name   = FIMC_IS_COMPANION_DEV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &fimc_is_companion_pm_ops,
+               .of_match_table = exynos_fimc_is_companion_match,
+       }
+};
+
+module_platform_driver(fimc_is_companion_driver);
+#else
+static struct platform_device_id fimc_is_companion_driver_ids[] = {
+       {
+               .name           = FIMC_IS_COMPANION_DEV_NAME,
+               .driver_data    = 0,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, fimc_is_companion_driver_ids);
+
+static struct platform_driver fimc_is_companion_driver = {
+       .probe    = fimc_is_companion_probe,
+       .remove   = __devexit_p(fimc_is_companion_remove),
+       .id_table = fimc_is_companion_driver_ids,
+       .driver   = {
+               .name   = FIMC_IS_COMPANION_DEV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &fimc_is_companion_pm_ops,
+       }
+};
+
+static int __init fimc_is_companion_init(void)
+{
+       int ret = 0;
+
+       ret = platform_driver_register(&fimc_is_companion_driver);
+       if (ret)
+               err("platform_driver_register failed: %d\n", ret);
+
+       return ret;
+}
+
+static void __exit fimc_is_companion_exit(void)
+{
+       platform_driver_unregister(&fimc_is_companion_driver);
+}
+module_init(fimc_is_companion_init);
+module_exit(fimc_is_companion_exit);
+#endif
+
+MODULE_AUTHOR("Wooki Min<wooki.min@samsung.com>");
+MODULE_DESCRIPTION("Exynos FIMC_IS_COMPANION driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-companion.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-companion.h
new file mode 100644 (file)
index 0000000..ee20321
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef fimc_is_device_companion_H
+#define fimc_is_device_companion_H
+
+#include <mach/exynos-fimc-is-sensor.h>
+#include <linux/interrupt.h>
+#include "fimc-is-video.h"
+
+struct fimc_is_video_ctx;
+
+#define FIMC_IS_COMPANION_DEV_NAME "exynos-fimc-is-companion"
+
+enum fimc_is_companion_state {
+       FIMC_IS_COMPANION_OPEN,
+       FIMC_IS_COMPANION_MCLK_ON,
+       FIMC_IS_COMPANION_ICLK_ON,
+       FIMC_IS_COMPANION_GPIO_ON,
+};
+
+enum fimc_is_companion_status {
+       FIMC_IS_COMPANION_IDLE,
+       FIMC_IS_COMPANION_OPENNING,
+       FIMC_IS_COMPANION_OPENDONE,
+};
+
+struct fimc_is_device_companion {
+       struct v4l2_device                              v4l2_dev;
+       struct platform_device                          *pdev;
+       void __iomem                                    *regs;
+       struct fimc_is_mem                              mem;
+
+       struct fimc_is_video_ctx                        *vctx;
+       struct fimc_is_video                            video;
+
+       unsigned long                                   state;
+
+       struct exynos_platform_fimc_is_sensor           *pdata;
+       void                                            *private_data;
+       wait_queue_head_t                               init_wait_queue;
+       int                                             companion_status;
+};
+
+int fimc_is_companion_open(struct fimc_is_device_companion *device);
+int fimc_is_companion_close(struct fimc_is_device_companion *device);
+int fimc_is_companion_wait(struct fimc_is_device_companion *device);
+int fimc_is_companion_runtime_suspend(struct device *dev);
+int fimc_is_companion_runtime_resume(struct device *dev);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-csi.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-csi.c
new file mode 100644 (file)
index 0000000..1bbbbfe
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is/mipi-csi functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos5-mipiphy.h>
+
+#include "fimc-is-config.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-hw.h"
+#include "fimc-is-device-csi.h"
+#include "fimc-is-device-sensor.h"
+
+#if (FIMC_IS_CSI_VERSION == CSI_VERSION_0000_0000)
+extern void s5pcsis_enable_interrupts(unsigned long __iomem *base_reg, struct fimc_is_image *image, bool on);
+extern void s5pcsis_set_hsync_settle(unsigned long __iomem *base_reg, int settle);
+extern void s5pcsis_set_params(unsigned long __iomem *base_reg, struct fimc_is_image *image, u32 lanes);
+extern void s5pcsis_reset(unsigned long __iomem *base_reg);
+extern void s5pcsis_system_enable(unsigned long __iomem *base_reg, int on, u32 lanes);
+#endif
+
+static u32 get_hsync_settle(struct fimc_is_sensor_cfg *cfg,
+       const u32 cfgs, u32 width, u32 height, u32 framerate)
+{
+       u32 settle;
+       u32 max_settle;
+       u32 proximity_framerate, proximity_settle;
+       u32 i;
+
+       settle = 0;
+       max_settle = 0;
+       proximity_framerate = 0;
+       proximity_settle = 0;
+
+       for (i = 0; i < cfgs; i++) {
+               if ((cfg[i].width == width) &&
+                   (cfg[i].height == height) &&
+                   (cfg[i].framerate == framerate)) {
+                       settle = cfg[i].settle;
+                       break;
+               }
+
+               if ((cfg[i].width == width) &&
+                   (cfg[i].height == height) &&
+                   (cfg[i].framerate > proximity_framerate)) {
+                       proximity_settle = cfg[i].settle;
+                       proximity_framerate = cfg[i].framerate;
+               }
+
+               if (cfg[i].settle > max_settle)
+                       max_settle = cfg[i].settle;
+       }
+
+       if (!settle) {
+               if (proximity_settle) {
+                       settle = proximity_settle;
+               } else {
+                       /*
+                        * return a max settle time value in above table
+                        * as a default depending on the channel
+                        */
+                       settle = max_settle;
+
+                       warn("could not find proper settle time: %dx%d@%dfps",
+                               width, height, framerate);
+               }
+       }
+
+       return settle;
+}
+
+#if (FIMC_IS_CSI_VERSION == CSI_VERSION_0310_0100)
+static u32 get_vci_channel(struct fimc_is_vci *vci,
+       const u32 vcis, u32 pixelformat)
+{
+       u32 i;
+       u32 index = vcis;
+
+       BUG_ON(!vci);
+
+       for (i = 0; i < vcis; i++) {
+               if (vci[i].pixelformat == pixelformat) {
+                       index = i;
+                       break;
+               }
+       }
+
+       if (index == vcis) {
+               err("invalid vc setting(foramt : %d)", pixelformat);
+               BUG();
+       }
+
+       return index;
+}
+#endif
+
+int fimc_is_csi_open(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_device_csi *csi;
+
+       BUG_ON(!subdev);
+
+       csi = v4l2_get_subdevdata(subdev);
+       if (!csi) {
+               err("csi is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       csi->sensor_cfgs = 0;
+       csi->sensor_cfg = NULL;
+       memset(&csi->image, 0, sizeof(struct fimc_is_image));
+
+p_err:
+       return ret;
+}
+
+int fimc_is_csi_close(struct v4l2_subdev *subdev)
+{
+       return 0;
+}
+
+/* value : module enum */
+static int csi_init(struct v4l2_subdev *subdev, u32 value)
+{
+       int ret = 0;
+       struct fimc_is_device_csi *csi;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+       BUG_ON(!value);
+
+       csi = v4l2_get_subdevdata(subdev);
+       if (!csi) {
+               err("csi is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       module = (struct fimc_is_module_enum *)value;
+       csi->sensor_cfgs = module->cfgs;
+       csi->sensor_cfg = module->cfg;
+       csi->vcis = module->vcis;
+       csi->vci = module->vci;
+       csi->image.framerate = SENSOR_DEFAULT_FRAMERATE; /* default frame rate */
+       csi->mode = module->mode;
+       csi->lanes = module->lanes;
+
+p_err:
+       return ret;
+}
+
+static int csi_s_power(struct v4l2_subdev *subdev,
+       int on)
+{
+       int ret = 0;
+       struct fimc_is_device_csi *csi;
+
+       BUG_ON(!subdev);
+
+       csi = (struct fimc_is_device_csi *)v4l2_get_subdevdata(subdev);
+       if (!csi) {
+               err("csi is NULL");
+               return -EINVAL;
+       }
+
+       /* HACK: CSI #1 phy should be enabled when CSI #2 phy is eanbled. */
+       if (csi->instance == CSI_ID_C) {
+               ret = exynos5_csis_phy_enable(CSI_ID_B, on);
+       }
+
+       ret = exynos5_csis_phy_enable(csi->instance, on);
+       if (ret) {
+               err("fail to csi%d power on", csi->instance);
+               goto p_err;
+       }
+
+p_err:
+       mdbgd_front("%s(%d, %d)\n", csi, __func__, on, ret);
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = csi_init,
+       .s_power = csi_s_power
+};
+
+static int csi_stream_on(struct fimc_is_device_csi *csi)
+{
+       int ret = 0;
+       u32 settle;
+       unsigned long __iomem *base_reg;
+
+       BUG_ON(!csi);
+       BUG_ON(!csi->sensor_cfg);
+
+       base_reg = csi->base_reg;
+
+       settle = get_hsync_settle(
+               csi->sensor_cfg,
+               csi->sensor_cfgs,
+               csi->image.window.width,
+               csi->image.window.height,
+               csi->image.framerate);
+
+       minfo("[CSI:D] settle(%dx%d@%d) = %d, lane idx(%d)\n",
+               csi,
+               csi->image.window.width,
+               csi->image.window.height,
+               csi->image.framerate,
+               settle,
+               csi->lanes);
+
+#if (FIMC_IS_CSI_VERSION == CSI_VERSION_0000_0000)
+       s5pcsis_reset(base_reg);
+       s5pcsis_set_hsync_settle(base_reg, settle);
+       s5pcsis_set_params(base_reg, &csi->image, csi->lanes);
+       /* lane total count = csi->lanes + 1 (CSI_DATA_LANES_1 is 0) */
+       s5pcsis_system_enable(base_reg, true, (csi->lanes + 1));
+       s5pcsis_enable_interrupts(base_reg, &csi->image, true);
+#else
+       csi_hw_reset(base_reg);
+       csi_hw_s_settle(base_reg, settle);
+       csi_hw_s_control(base_reg, csi->image.format.pixelformat, csi->mode, csi->lanes);
+       if (csi->mode == CSI_MODE_CH0_ONLY) {
+               csi_hw_s_config(base_reg,
+                       CSI_VIRTUAL_CH_0,
+                       CSI_VIRTUAL_CH_0,
+                       csi->image.format.pixelformat,
+                       csi->image.window.width,
+                       csi->image.window.height);
+       } else {
+               u32 index = get_vci_channel(csi->vci, csi->vcis, csi->image.format.pixelformat);
+               csi_hw_s_config(base_reg,
+                       CSI_VIRTUAL_CH_0,
+                       csi->vci[index].vc_map[CSI_VIRTUAL_CH_0],
+                       csi->image.format.pixelformat,
+                       csi->image.window.width,
+                       csi->image.window.height);
+               csi_hw_s_config(base_reg,
+                       CSI_VIRTUAL_CH_1,
+                       csi->vci[index].vc_map[CSI_VIRTUAL_CH_1],
+                       csi->image.format.pixelformat,
+                       csi->image.window.width,
+                       csi->image.window.height);
+               csi_hw_s_config(base_reg,
+                       CSI_VIRTUAL_CH_2,
+                       csi->vci[index].vc_map[CSI_VIRTUAL_CH_2],
+                       csi->image.format.pixelformat,
+                       csi->image.window.width,
+                       csi->image.window.height);
+       }
+
+       csi_hw_s_interrupt(base_reg, true);
+       csi_hw_enable(base_reg);
+#endif
+
+       return ret;
+}
+
+static int csi_stream_off(struct fimc_is_device_csi *csi)
+{
+       int ret = 0;
+       unsigned long __iomem *base_reg;
+
+       BUG_ON(!csi);
+
+       base_reg = csi->base_reg;
+
+#if (FIMC_IS_CSI_VERSION == CSI_VERSION_0000_0000)
+       s5pcsis_enable_interrupts(base_reg, &csi->image, false);
+       /* lane total count = csi->lanes + 1 (CSI_DATA_LANES_1 is 0) */
+       s5pcsis_system_enable(base_reg, false, (csi->lanes + 1));
+#else
+       csi_hw_s_interrupt(base_reg, false);
+       csi_hw_disable(base_reg);
+#endif
+
+       return ret;
+}
+
+static int csi_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       int ret = 0;
+       struct fimc_is_device_csi *csi;
+
+       BUG_ON(!subdev);
+
+       csi = (struct fimc_is_device_csi *)v4l2_get_subdevdata(subdev);
+       if (!csi) {
+               err("csi is NULL");
+               return -EINVAL;
+       }
+
+       if (enable) {
+               ret = csi_stream_on(csi);
+               if (ret) {
+                       err("csi_stream_on is fail(%d)", ret);
+                       goto p_err;
+               }
+       } else {
+               ret = csi_stream_off(csi);
+               if (ret) {
+                       err("csi_stream_off is fail(%d)", ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return 0;
+}
+
+static int csi_s_param(struct v4l2_subdev *subdev, struct v4l2_streamparm *param)
+{
+       int ret = 0;
+       struct fimc_is_device_csi *csi;
+       struct v4l2_captureparm *cp;
+       struct v4l2_fract *tpf;
+
+       BUG_ON(!subdev);
+       BUG_ON(!param);
+
+       cp = &param->parm.capture;
+       tpf = &cp->timeperframe;
+
+       csi = (struct fimc_is_device_csi *)v4l2_get_subdevdata(subdev);
+       if (!csi) {
+               err("csi is NULL");
+               return -EINVAL;
+       }
+
+       csi->image.framerate = tpf->denominator / tpf->numerator;
+
+       mdbgd_front("%s(%d, %d)\n", csi, __func__, csi->image.framerate, ret);
+       return ret;
+}
+
+static int csi_s_format(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *fmt)
+{
+       int ret = 0;
+       struct fimc_is_device_csi *csi;
+
+       BUG_ON(!subdev);
+       BUG_ON(!fmt);
+
+       csi = (struct fimc_is_device_csi *)v4l2_get_subdevdata(subdev);
+       if (!csi) {
+               err("csi is NULL");
+               return -EINVAL;
+       }
+
+       csi->image.window.offs_h = 0;
+       csi->image.window.offs_v = 0;
+       csi->image.window.width = fmt->width;
+       csi->image.window.height = fmt->height;
+       csi->image.window.o_width = fmt->width;
+       csi->image.window.o_height = fmt->height;
+       csi->image.format.pixelformat = fmt->code;
+       csi->image.format.field = fmt->field;
+
+       mdbgd_front("%s(%dx%d, %X)\n", csi, __func__, fmt->width, fmt->height, fmt->code);
+       return ret;
+}
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = csi_s_stream,
+       .s_parm = csi_s_param,
+       .s_mbus_fmt = csi_s_format
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops
+};
+
+#ifdef DBG_CSIISR
+static irqreturn_t fimc_is_csi_isr(int irq, void *data)
+{
+       u32 status;
+       struct fimc_is_device_csi *csi;
+
+       csi = data;
+
+       status = csi_hw_g_interrupt(csi->base_reg);
+       info("CSI%d : irq%d(%X)\n",csi->instance, irq, status);
+
+       return IRQ_HANDLED;
+}
+#endif
+
+int fimc_is_csi_probe(void *parent, u32 instance)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_csi;
+       struct fimc_is_device_csi *csi;
+       struct fimc_is_device_sensor *device = parent;
+
+       BUG_ON(!device);
+
+       subdev_csi = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_csi) {
+               merr("subdev_csi is NULL", device);
+               ret = -ENOMEM;
+               goto p_err;
+       }
+       device->subdev_csi = subdev_csi;
+
+       csi = kzalloc(sizeof(struct fimc_is_device_csi), GFP_KERNEL);
+       if (!csi) {
+               merr("csi is NULL", device);
+               ret = -ENOMEM;
+               goto p_err_free1;
+       }
+
+       csi->instance = instance;
+       switch(instance) {
+       case CSI_ID_A:
+               csi->base_reg = (unsigned long *)MIPICSI0_REG_BASE;
+#ifdef DBG_CSIISR
+               ret = request_irq(IRQ_MIPICSI0,
+                       fimc_is_csi_isr,
+                       IRQF_SHARED,
+                       "mipi-csi0",
+                       csi);
+               if (ret) {
+                       err("request_irq(IRQ_MIPICSI0) is fail(%d)", ret);
+                       goto p_err_free2;
+               }
+#endif
+               break;
+       case CSI_ID_B:
+               csi->base_reg = (unsigned long *)MIPICSI1_REG_BASE;
+#ifdef DBG_CSIISR
+               ret = request_irq(IRQ_MIPICSI1,
+                       fimc_is_csi_isr,
+                       IRQF_SHARED,
+                       "mipi-csi1",
+                       csi);
+               if (ret) {
+                       err("request_irq(IRQ_MIPICSI1) is fail(%d)", ret);
+                       goto p_err_free2;
+               }
+#endif
+               break;
+       case CSI_ID_C:
+               csi->base_reg = (unsigned long *)MIPICSI2_REG_BASE;
+               break;
+       default:
+               err("instance is invalid(%d)", instance);
+               ret = -EINVAL;
+               goto p_err_free2;
+       }
+
+       v4l2_subdev_init(subdev_csi, &subdev_ops);
+       v4l2_set_subdevdata(subdev_csi, csi);
+       v4l2_set_subdev_hostdata(subdev_csi, device);
+       snprintf(subdev_csi->name, V4L2_SUBDEV_NAME_SIZE, "csi-subdev.%d", instance);
+       ret = v4l2_device_register_subdev(&device->v4l2_dev, subdev_csi);
+       if (ret) {
+               merr("v4l2_device_register_subdev is fail(%d)", device, ret);
+               goto p_err_free2;
+       }
+
+       info("[%d][FRT:D] %s(%d)\n", instance, __func__, ret);
+       return 0;
+
+p_err_free2:
+       kfree(csi);
+
+p_err_free1:
+       kfree(subdev_csi);
+       device->subdev_csi = NULL;
+
+p_err:
+       err("[%d][FRT:D] %s(%d)\n", instance, __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-csi.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-csi.h
new file mode 100644 (file)
index 0000000..dcae741
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef FIMC_IS_DEVICE_CSI_H
+#define FIMC_IS_DEVICE_CSI_H
+
+#include <media/v4l2-device.h>
+#include "fimc-is-type.h"
+
+struct fimc_is_device_csi {
+       /* channel information */
+       u32                             instance;
+       unsigned long __iomem           *base_reg;
+
+       /* for settle time */
+       u32                             sensor_cfgs;
+       struct fimc_is_sensor_cfg       *sensor_cfg;
+
+       /* for vci setting */
+       u32                             vcis;
+       struct fimc_is_vci              *vci;
+
+       /* image configuration */
+       u32                             mode;
+       u32                             lanes;
+       struct fimc_is_image            image;
+};
+
+int __must_check fimc_is_csi_probe(void *parent, u32 instance);
+int __must_check fimc_is_csi_open(struct v4l2_subdev *subdev);
+int __must_check fimc_is_csi_close(struct v4l2_subdev *subdev);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-eeprom.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-eeprom.c
new file mode 100644 (file)
index 0000000..368a84d
--- /dev/null
@@ -0,0 +1,138 @@
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+#include "fimc-is-core.h"
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-hw.h"
+
+#define DRIVER_NAME "fimc_is_eeprom_i2c"
+#define DRIVER_NAME_REAR "rear-eeprom-i2c"
+#define DRIVER_NAME_FRONT "front-eeprom-i2c"
+#define REAR_DATA 0
+#define FRONT_DATA 1
+
+
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+int sensor_eeprom_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct fimc_is_core *core;
+       static bool probe_retried = false;
+
+       if (!fimc_is_dev)
+               goto probe_defer;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core)
+               goto probe_defer;
+
+       if (id->driver_data == REAR_DATA) {
+               core->eeprom_client0 = client;
+       } else if (id->driver_data == FRONT_DATA) {
+               core->eeprom_client1 = client;
+       } else {
+               err("rear eeprom device is failed!");
+       }
+
+       pr_info("%s %s[%ld]: fimc_is_sensor_eeprom probed!\n",
+               dev_driver_string(&client->dev), dev_name(&client->dev), id->driver_data);
+
+       return 0;
+
+probe_defer:
+       if (probe_retried) {
+               err("probe has already been retried!!");
+       }
+
+       probe_retried = true;
+       err("core device is not yet probed");
+       return -EPROBE_DEFER;
+
+}
+
+static int sensor_eeprom_remove(struct i2c_client *client)
+{
+       int ret = 0;
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_sensor_eeprom_match[] = {
+       {
+               .compatible = "samsung,rear-eeprom-i2c", .data = (void *)REAR_DATA
+       },
+       {
+               .compatible = "samsung,front-eeprom-i2c", .data = (void *)FRONT_DATA
+       },
+       {},
+};
+#endif
+
+static const struct i2c_device_id sensor_eeprom_idt[] = {
+       { DRIVER_NAME_REAR, REAR_DATA },
+       { DRIVER_NAME_FRONT, FRONT_DATA },
+};
+
+static struct i2c_driver sensor_eeprom_driver = {
+       .driver = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = exynos_fimc_is_sensor_eeprom_match
+#endif
+       },
+       .probe  = sensor_eeprom_probe,
+       .remove = sensor_eeprom_remove,
+       .id_table = sensor_eeprom_idt
+};
+
+static int __init sensor_eeprom_load(void)
+{
+        return i2c_add_driver(&sensor_eeprom_driver);
+}
+
+static void __exit sensor_eeprom_unload(void)
+{
+        i2c_del_driver(&sensor_eeprom_driver);
+}
+
+module_init(sensor_eeprom_load);
+module_exit(sensor_eeprom_unload);
+
+MODULE_AUTHOR("Kyoungho Yun");
+MODULE_DESCRIPTION("Camera eeprom driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-flite.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-flite.c
new file mode 100644 (file)
index 0000000..7ed2d16
--- /dev/null
@@ -0,0 +1,2016 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/irqs.h>
+
+#include "fimc-is-time.h"
+#include "fimc-is-core.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-hw.h"
+#include "fimc-is-interface.h"
+#include "fimc-is-device-flite.h"
+
+#define FLITE_MAX_RESET_READY_TIME     (20) /* 100ms */
+#define FLITE_MAX_WIDTH_SIZE           (8192)
+#define FLITE_MAX_HEIGHT_SIZE          (8192)
+/* #define COLORBAR_MODE */
+
+/*FIMCLite*/
+/* Camera Source size */
+#define FLITE_REG_CISRCSIZE                            (0x00)
+#define FLITE_REG_CISRCSIZE_SIZE_H(x)                  ((x) << 16)
+#define FLITE_REG_CISRCSIZE_SIZE_V(x)                  ((x) << 0)
+#define FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR         (0 << 14)
+#define FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB         (1 << 14)
+#define FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY         (2 << 14)
+#define FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY         (3 << 14)
+
+/* Global control */
+#define FLITE_REG_CIGCTRL                              0x04
+#define FLITE_REG_CIGCTRL_YUV422_1P                    (0x1E << 24)
+#define FLITE_REG_CIGCTRL_RAW8                         (0x2A << 24)
+#define FLITE_REG_CIGCTRL_RAW10                                (0x2B << 24)
+#define FLITE_REG_CIGCTRL_RAW12                                (0x2C << 24)
+#define FLITE_REG_CIGCTRL_RAW14                                (0x2D << 24)
+
+/* User defined formats. x = 0...0xF. */
+#define FLITE_REG_CIGCTRL_USER(x)                      (0x30 + x - 1)
+#define FLITE_REG_CIGCTRL_OLOCAL_DISABLE               (1 << 22)
+#define FLITE_REG_CIGCTRL_SHADOWMASK_DISABLE           (1 << 21)
+#define FLITE_REG_CIGCTRL_ODMA_DISABLE                 (1 << 20)
+#define FLITE_REG_CIGCTRL_SWRST_REQ                    (1 << 19)
+#define FLITE_REG_CIGCTRL_SWRST_RDY                    (1 << 18)
+#define FLITE_REG_CIGCTRL_SWRST                                (1 << 17)
+#define FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR                (1 << 15)
+#define FLITE_REG_CIGCTRL_INVPOLPCLK                   (1 << 14)
+#define FLITE_REG_CIGCTRL_INVPOLVSYNC                  (1 << 13)
+#define FLITE_REG_CIGCTRL_INVPOLHREF                   (1 << 12)
+#define FLITE_REG_CIGCTRL_IRQ_LASTEN0_ENABLE           (0 << 8)
+#define FLITE_REG_CIGCTRL_IRQ_LASTEN0_DISABLE          (1 << 8)
+#define FLITE_REG_CIGCTRL_IRQ_ENDEN0_ENABLE            (0 << 7)
+#define FLITE_REG_CIGCTRL_IRQ_ENDEN0_DISABLE           (1 << 7)
+#define FLITE_REG_CIGCTRL_IRQ_STARTEN0_ENABLE          (0 << 6)
+#define FLITE_REG_CIGCTRL_IRQ_STARTEN0_DISABLE         (1 << 6)
+#define FLITE_REG_CIGCTRL_IRQ_OVFEN0_ENABLE            (0 << 5)
+#define FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE           (1 << 5)
+#define FLITE_REG_CIGCTRL_SELCAM_MIPI                  (1 << 3)
+
+/* Image Capture Enable */
+#define FLITE_REG_CIIMGCPT                             (0x08)
+#define FLITE_REG_CIIMGCPT_IMGCPTEN                    (1 << 31)
+#define FLITE_REG_CIIMGCPT_CPT_FREN                    (1 << 25)
+#define FLITE_REG_CIIMGCPT_CPT_FRPTR(x)                        ((x) << 19)
+#define FLITE_REG_CIIMGCPT_CPT_MOD_FRCNT               (1 << 18)
+#define FLITE_REG_CIIMGCPT_CPT_MOD_FREN                        (0 << 18)
+#define FLITE_REG_CIIMGCPT_CPT_FRCNT(x)                        ((x) << 10)
+
+/* Capture Sequence */
+#define FLITE_REG_CICPTSEQ                             (0x0C)
+#define FLITE_REG_CPT_FRSEQ(x)                         ((x) << 0)
+
+/* Camera Window Offset */
+#define FLITE_REG_CIWDOFST                             (0x10)
+#define FLITE_REG_CIWDOFST_WINOFSEN                    (1 << 31)
+#define FLITE_REG_CIWDOFST_CLROVIY                     (1 << 31)
+#define FLITE_REG_CIWDOFST_WINHOROFST(x)               ((x) << 16)
+#define FLITE_REG_CIWDOFST_HOROFF_MASK                 (0x1fff << 16)
+#define FLITE_REG_CIWDOFST_CLROVFICB                   (1 << 15)
+#define FLITE_REG_CIWDOFST_CLROVFICR                   (1 << 14)
+#define FLITE_REG_CIWDOFST_WINVEROFST(x)               ((x) << 0)
+#define FLITE_REG_CIWDOFST_VEROFF_MASK                 (0x1fff << 0)
+
+/* Cmaera Window Offset2 */
+#define FLITE_REG_CIWDOFST2                            (0x14)
+#define FLITE_REG_CIWDOFST2_WINHOROFST2(x)             ((x) << 16)
+#define FLITE_REG_CIWDOFST2_WINVEROFST2(x)             ((x) << 0)
+
+/* Camera Output DMA Format */
+#define FLITE_REG_CIODMAFMT                            (0x18)
+#define FLITE_REG_CIODMAFMT_1D_DMA                     (1 << 15)
+#define FLITE_REG_CIODMAFMT_2D_DMA                     (0 << 15)
+#define FLITE_REG_CIODMAFMT_PACK12                     (1 << 14)
+#define FLITE_REG_CIODMAFMT_NORMAL                     (0 << 14)
+#define FLITE_REG_CIODMAFMT_CRYCBY                     (0 << 4)
+#define FLITE_REG_CIODMAFMT_CBYCRY                     (1 << 4)
+#define FLITE_REG_CIODMAFMT_YCRYCB                     (2 << 4)
+#define FLITE_REG_CIODMAFMT_YCBYCR                     (3 << 4)
+
+/* Camera Output Canvas */
+#define FLITE_REG_CIOCAN                               (0x20)
+#define FLITE_REG_CIOCAN_OCAN_V(x)                     ((x) << 16)
+#define FLITE_REG_CIOCAN_OCAN_H(x)                     ((x) << 0)
+
+/* Camera Output DMA Offset */
+#define FLITE_REG_CIOOFF                               (0x24)
+#define FLITE_REG_CIOOFF_OOFF_V(x)                     ((x) << 16)
+#define FLITE_REG_CIOOFF_OOFF_H(x)                     ((x) << 0)
+
+/* Camera Output DMA Address */
+#define FLITE_REG_CIOSA                                        (0x30)
+#define FLITE_REG_CIOSA_OSA(x)                         ((x) << 0)
+
+/* Camera Status */
+#define FLITE_REG_CISTATUS                             (0x40)
+#define FLITE_REG_CISTATUS_MIPI_VVALID                 (1 << 22)
+#define FLITE_REG_CISTATUS_MIPI_HVALID                 (1 << 21)
+#define FLITE_REG_CISTATUS_MIPI_DVALID                 (1 << 20)
+#define FLITE_REG_CISTATUS_ITU_VSYNC                   (1 << 14)
+#define FLITE_REG_CISTATUS_ITU_HREFF                   (1 << 13)
+#define FLITE_REG_CISTATUS_OVFIY                       (1 << 10)
+#define FLITE_REG_CISTATUS_OVFICB                      (1 << 9)
+#define FLITE_REG_CISTATUS_OVFICR                      (1 << 8)
+#define FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW            (1 << 7)
+#define FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND          (1 << 6)
+#define FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART            (1 << 5)
+#define FLITE_REG_CISTATUS_IRQ_SRC_FRMEND              (1 << 4)
+#define FLITE_REG_CISTATUS_IRQ_CAM                     (1 << 0)
+#define FLITE_REG_CISTATUS_IRQ_MASK                    (0xf << 4)
+
+/* Camera Status2 */
+#define FLITE_REG_CISTATUS2                            (0x44)
+#define FLITE_REG_CISTATUS2_LASTCAPEND                 (1 << 1)
+#define FLITE_REG_CISTATUS2_FRMEND                     (1 << 0)
+
+/* Camera Status3 */
+#define FLITE_REG_CISTATUS3                            0x48
+#define FLITE_REG_CISTATUS3_PRESENT_MASK               (0x3F)
+
+/* Qos Threshold */
+#define FLITE_REG_CITHOLD                              (0xF0)
+#define FLITE_REG_CITHOLD_W_QOS_EN                     (1 << 30)
+#define FLITE_REG_CITHOLD_WTH_QOS(x)                   ((x) << 0)
+
+/* Camera General Purpose */
+#define FLITE_REG_CIGENERAL                            (0xFC)
+#define FLITE_REG_CIGENERAL_CAM_A                      (0)
+#define FLITE_REG_CIGENERAL_CAM_B                      (1)
+#define FLITE_REG_CIGENERAL_CAM_C                      (2)
+#define FLITE_REG_CIGENERAL_CAM_D                      (3)
+#define FLITE_REG_CIGENERAL_3AA1_CAM_A                 (0 << 14)
+#define FLITE_REG_CIGENERAL_3AA1_CAM_B                 (1 << 14)
+#define FLITE_REG_CIGENERAL_3AA1_CAM_C                 (2 << 14)
+#define FLITE_REG_CIGENERAL_3AA1_CAM_D                 (3 << 14)
+
+#define FLITE_REG_CIFCNTSEQ                            0x100
+
+/* BNS */
+#define FLITE_REG_BINNINGON                            (0x120)
+#define FLITE_REG_BINNINGON_CLKGATE_ON(x)              (~(x) << 1)
+#define FLITE_REG_BINNINGON_EN(x)                      ((x) << 0)
+
+#define FLITE_REG_BINNINGCTRL                          (0x124)
+#define FLITE_REG_BINNINGCTRL_FACTOR_Y(x)              ((x) << 22)
+#define FLITE_REG_BINNINGCTRL_FACTOR_X(x)              ((x) << 17)
+#define FLITE_REG_BINNINGCTRL_SHIFT_UP_Y(x)            ((x) << 15)
+#define FLITE_REG_BINNINGCTRL_SHIFT_UP_X(x)            ((x) << 13)
+#define FLITE_REG_BINNINGCTRL_PRECISION_BITS(x)                ((x) << 10)
+#define FLITE_REG_BINNINGCTRL_BITTAGE(x)               ((x) << 5)
+#define FLITE_REG_BINNINGCTRL_UNITY_SIZE(x)            ((x) << 0)
+
+#define FLITE_REG_PEDESTAL                             (0x128)
+#define FLITE_REG_PEDESTAL_OUT(x)                      ((x) << 12)
+#define FLITE_REG_PEDESTAL_IN(x)                       ((x) << 0)
+
+#define FLITE_REG_BINNINGTOTAL                         (0x12C)
+#define FLITE_REG_BINNINGTOTAL_HEIGHT(x)               ((x) << 16)
+#define FLITE_REG_BINNINGTOTAL_WIDTH(x)                        ((x) << 0)
+
+#define FLITE_REG_BINNINGINPUT                         (0x130)
+#define FLITE_REG_BINNINGINPUT_HEIGHT(x)               ((x) << 16)
+#define FLITE_REG_BINNINGINPUT_WIDTH(x)                        ((x) << 0)
+
+#define FLITE_REG_BINNINGMARGIN                                (0x134)
+#define FLITE_REG_BINNINGMARGIN_TOP(x)                 ((x) << 16)
+#define FLITE_REG_BINNINGMARGIN_LEFT(x)                        ((x) << 0)
+
+#define FLITE_REG_BINNINGOUTPUT                                (0x138)
+#define FLITE_REG_BINNINGOUTPUT_HEIGHT(x)              ((x) << 16)
+#define FLITE_REG_BINNINGOUTPUT_WIDTH(x)               ((x) << 0)
+
+#define FLITE_REG_WEIGHTX01                            (0x13C)
+#define FLITE_REG_WEIGHTX01_1(x)                       ((x) << 16)
+#define FLITE_REG_WEIGHTX01_0(x)                       ((x) << 0)
+
+#define FLITE_REG_WEIGHTX23                            (0x140)
+#define FLITE_REG_WEIGHTX23_1(x)                       ((x) << 16)
+#define FLITE_REG_WEIGHTX23_0(x)                       ((x) << 0)
+
+#define FLITE_REG_WEIGHTY01                            (0x15C)
+#define FLITE_REG_WEIGHTY01_1(x)                       ((x) << 16)
+#define FLITE_REG_WEIGHTY01_0(x)                       ((x) << 0)
+
+#define FLITE_REG_WEIGHTY23                            (0x160)
+#define FLITE_REG_WEIGHTY23_1(x)                       ((x) << 16)
+#define FLITE_REG_WEIGHTY23_0(x)                       ((x) << 0)
+
+static void flite_hw_enable_bns(unsigned long __iomem *base_reg, bool enable)
+{
+       u32 cfg = 0;
+
+       /* enable */
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGON));
+       cfg |= FLITE_REG_BINNINGON_CLKGATE_ON(enable);
+       cfg |= FLITE_REG_BINNINGON_EN(enable);
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGON));
+}
+
+static void flite_hw_s_coeff_bns(unsigned long __iomem *base_reg,
+       u32 factor_x, u32 factor_y)
+{
+       u32 cfg = 0;
+       u32 factor = 0;
+
+       factor = factor_x * factor_y;
+       if (factor_x != factor_y)
+               err("x y factor is not the same (%d, %d)", factor_x, factor_y);
+
+       /* control */
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGCTRL));
+       cfg |= FLITE_REG_BINNINGCTRL_FACTOR_Y(factor_y);
+       cfg |= FLITE_REG_BINNINGCTRL_FACTOR_X(factor_x);
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGCTRL));
+
+       switch (factor) {
+       case 9:
+               /* coefficient */
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX01));
+               cfg |= FLITE_REG_WEIGHTX01_1(0x20);
+               cfg |= FLITE_REG_WEIGHTX01_0(0xE0);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX01));
+
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX23));
+               cfg |= FLITE_REG_WEIGHTX23_1(0xA0);
+               cfg |= FLITE_REG_WEIGHTX23_0(0x60);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX23));
+
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY01));
+               cfg |= FLITE_REG_WEIGHTY01_1(0x20);
+               cfg |= FLITE_REG_WEIGHTY01_0(0xE0);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY01));
+
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY23));
+               cfg |= FLITE_REG_WEIGHTY23_1(0xA0);
+               cfg |= FLITE_REG_WEIGHTY23_0(0x60);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY23));
+               break;
+       case 16:
+               /* coefficient */
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX01));
+               cfg |= FLITE_REG_WEIGHTX01_1(0x40);
+               cfg |= FLITE_REG_WEIGHTX01_0(0xC0);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX01));
+
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY01));
+               cfg |= FLITE_REG_WEIGHTY01_1(0x40);
+               cfg |= FLITE_REG_WEIGHTY01_0(0xC0);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY01));
+               break;
+       default:
+               err("unknown factor!! (%d, %d)", factor_x, factor_y);
+               break;
+       }
+}
+
+static void flite_hw_s_size_bns(unsigned long __iomem *base_reg,
+       u32 width, u32 height, u32 otf_width, u32 otf_height)
+{
+       u32 cfg = 0;
+
+       /* size */
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGTOTAL));
+       cfg |= FLITE_REG_BINNINGTOTAL_HEIGHT(height);
+       cfg |= FLITE_REG_BINNINGTOTAL_WIDTH(width);
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGTOTAL));
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGINPUT));
+       cfg |= FLITE_REG_BINNINGINPUT_HEIGHT(height);
+       cfg |= FLITE_REG_BINNINGINPUT_WIDTH(width);
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGINPUT));
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGMARGIN));
+       cfg |= FLITE_REG_BINNINGMARGIN_TOP(0);
+       cfg |= FLITE_REG_BINNINGMARGIN_LEFT(0);
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGMARGIN));
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGOUTPUT));
+       cfg |= FLITE_REG_BINNINGOUTPUT_HEIGHT(otf_height);
+       cfg |= FLITE_REG_BINNINGOUTPUT_WIDTH(otf_width);
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGOUTPUT));
+}
+
+static int flite_hw_set_bns(unsigned long __iomem *base_reg,
+        struct fimc_is_image *image)
+{
+       int ret = 0;
+       u32 width, height;
+       u32 otf_width, otf_height;
+       u32 factor_x, factor_y;
+
+       BUG_ON(!image);
+
+       width = image->window.width;
+       height = image->window.height;
+       otf_width = image->window.otf_width;
+       otf_height = image->window.otf_height;
+
+       if (otf_width == width && otf_height == height) {
+               info("input & output sizes are same(%d, %d)\n", otf_width, otf_height);
+               goto exit;
+       }
+
+       if (otf_width == 0 || otf_height == 0) {
+               warn("bns size is zero. s_ctrl(V4L2_CID_IS_S_BNS) first\n");
+               goto exit;
+       }
+
+       factor_x = 2 * width / otf_width;
+       factor_y = 2 * height / otf_height;
+
+       flite_hw_s_size_bns(base_reg, width, height, otf_width, otf_height);
+
+       flite_hw_s_coeff_bns(base_reg, factor_x, factor_y);
+
+       flite_hw_enable_bns(base_reg, true);
+
+       info("BNS in(%d, %d), BNS out(%d, %d), ratio(%d, %d)\n",
+       width, height, otf_width, otf_height, factor_x, factor_y);
+exit:
+       return ret;
+}
+
+static void flite_hw_set_cam_source_size(unsigned long __iomem *base_reg,
+       struct fimc_is_image *image)
+{
+       u32 cfg = 0;
+
+       BUG_ON(!image);
+
+#ifdef COLORBAR_MODE
+       cfg |= FLITE_REG_CISRCSIZE_SIZE_H(640);
+       cfg |= FLITE_REG_CISRCSIZE_SIZE_V(480);
+#else
+       cfg |= FLITE_REG_CISRCSIZE_SIZE_H(image->window.o_width);
+       cfg |= FLITE_REG_CISRCSIZE_SIZE_V(image->window.o_height);
+#endif
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CISRCSIZE));
+}
+
+static void flite_hw_set_dma_offset(unsigned long __iomem *base_reg,
+       struct fimc_is_image *image)
+{
+       u32 cfg = 0;
+
+       BUG_ON(!image);
+
+       /* HACK */
+       if (image->format.pixelformat == V4L2_PIX_FMT_SBGGR10 || image->format.pixelformat == V4L2_PIX_FMT_SBGGR12)
+               cfg |= FLITE_REG_CIOCAN_OCAN_H(roundup(image->window.o_width, 10));
+       else
+               cfg |= FLITE_REG_CIOCAN_OCAN_H(image->window.o_width);
+
+       cfg |= FLITE_REG_CIOCAN_OCAN_V(image->window.o_height);
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIOCAN));
+}
+
+static void flite_hw_set_cam_channel(unsigned long __iomem *base_reg,
+       u32 otf_setting)
+{
+       u32 cfg = 0;
+
+       cfg |= otf_setting;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGENERAL));
+}
+
+static void flite_hw_set_capture_start(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT));
+       cfg |= FLITE_REG_CIIMGCPT_IMGCPTEN;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT));
+}
+
+static void flite_hw_set_capture_stop(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT));
+       cfg &= ~FLITE_REG_CIIMGCPT_IMGCPTEN;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT));
+}
+
+static int flite_hw_set_source_format(unsigned long __iomem *base_reg, struct fimc_is_image *image)
+{
+       int ret = 0;
+       u32 pixelformat, format, cfg;
+
+       BUG_ON(!image);
+
+       pixelformat = image->format.pixelformat;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               format = HW_FORMAT_RAW8;
+               break;
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+               format = HW_FORMAT_RAW10;
+               break;
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+               format = HW_FORMAT_RAW10;
+               /*
+                * HACK : hal send RAW10 for RAW12
+                * formt = HW_FORMAT_RAW12 << 24;
+                */
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               format = HW_FORMAT_YUV422_8BIT;
+               break;
+       case V4L2_PIX_FMT_JPEG:
+               format = HW_FORMAT_USER;
+               break;
+       default:
+               err("unsupported format(%X)", pixelformat);
+               format = HW_FORMAT_RAW10;
+               ret = -EINVAL;
+               break;
+       }
+
+#ifdef COLORBAR_MODE
+       cfg |= (HW_FORMAT_YUV422_8BIT << 24);
+#else
+       cfg |= (format << 24);
+#endif
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       return ret;
+}
+
+static void flite_hw_set_dma_fmt(unsigned long __iomem *base_reg,
+       u32 pixelformat)
+{
+       u32 cfg = 0;
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIODMAFMT));
+
+       if (pixelformat == V4L2_PIX_FMT_SBGGR10 || pixelformat == V4L2_PIX_FMT_SBGGR12)
+               cfg |= FLITE_REG_CIODMAFMT_PACK12;
+       else
+               cfg |= FLITE_REG_CIODMAFMT_NORMAL;
+
+       if (pixelformat == V4L2_PIX_FMT_SGRBG8)
+               cfg |= FLITE_REG_CIODMAFMT_1D_DMA;
+       else
+               cfg |= FLITE_REG_CIODMAFMT_2D_DMA;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIODMAFMT));
+}
+
+static void flite_hw_set_output_dma(unsigned long __iomem *base_reg, bool enable,
+       u32 pixelformat)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       if (enable) {
+               cfg &= ~FLITE_REG_CIGCTRL_ODMA_DISABLE;
+               flite_hw_set_dma_fmt(base_reg, pixelformat);
+       } else {
+               cfg |= FLITE_REG_CIGCTRL_ODMA_DISABLE;
+       }
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static void flite_hw_set_output_local(unsigned long __iomem *base_reg, bool enable)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       if (enable)
+               cfg &= ~FLITE_REG_CIGCTRL_OLOCAL_DISABLE;
+       else
+               cfg |= FLITE_REG_CIGCTRL_OLOCAL_DISABLE;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+#ifdef COLORBAR_MODE
+static void flite_hw_set_test_pattern_enable(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+
+       /* will use for pattern generation testing */
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+       cfg |= FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+#endif
+
+static void flite_hw_set_interrupt_source(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* for checking stop complete */
+       cfg &= ~FLITE_REG_CIGCTRL_IRQ_LASTEN0_DISABLE;
+
+       /* for checking frame start */
+       cfg &= ~FLITE_REG_CIGCTRL_IRQ_STARTEN0_DISABLE;
+
+       /* for checking frame end */
+       cfg &= ~FLITE_REG_CIGCTRL_IRQ_ENDEN0_DISABLE;
+
+       /* for checking overflow */
+       cfg &= ~FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static void flite_hw_clr_interrupt_source(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* for checking stop complete */
+       cfg |= FLITE_REG_CIGCTRL_IRQ_LASTEN0_DISABLE;
+
+       /* for checking frame start */
+       cfg |= FLITE_REG_CIGCTRL_IRQ_STARTEN0_DISABLE;
+
+       /* for checking frame end */
+       cfg |= FLITE_REG_CIGCTRL_IRQ_ENDEN0_DISABLE;
+
+       /* for checking overflow */
+       cfg |= FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static void flite_hw_set_ovf_interrupt_source(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* for checking overflow */
+       cfg &= ~FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static void flite_hw_clr_ovf_interrupt_source(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* for checking overflow */
+       cfg |= FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static int flite_hw_check_ovf_interrupt_source(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* for checking overflow */
+       if (cfg & FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE)
+               return true;
+
+       return false;
+}
+
+static void flite_hw_force_reset(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0, retry = 100;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* request sw reset */
+       cfg |= FLITE_REG_CIGCTRL_SWRST_REQ;
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       /* checking reset ready */
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+       while (retry-- && !(cfg & FLITE_REG_CIGCTRL_SWRST_RDY))
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       if (!(cfg & FLITE_REG_CIGCTRL_SWRST_RDY))
+               warn("[CamIF] sw reset is not read but forcelly");
+
+       /* sw reset */
+       cfg |= FLITE_REG_CIGCTRL_SWRST;
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+       warn("[CamIF] sw reset");
+}
+
+static void flite_hw_set_inverse_polarity(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+       cfg &= ~(FLITE_REG_CIGCTRL_INVPOLPCLK | FLITE_REG_CIGCTRL_INVPOLVSYNC
+                       | FLITE_REG_CIGCTRL_INVPOLHREF);
+
+       /* cfg |= (FLITE_REG_CIGCTRL_INVPOLPCLK | FLITE_REG_CIGCTRL_INVPOLVSYNC); */
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static void flite_hw_set_camera_type(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+
+       cfg |= FLITE_REG_CIGCTRL_SELCAM_MIPI;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
+}
+
+static void flite_hw_set_window_offset(unsigned long __iomem *base_reg,
+        struct fimc_is_image *image)
+{
+       u32 cfg = 0;
+       u32 hoff2, voff2;
+
+       BUG_ON(!image);
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST));
+       cfg &= ~(FLITE_REG_CIWDOFST_HOROFF_MASK |
+               FLITE_REG_CIWDOFST_VEROFF_MASK);
+       cfg |= FLITE_REG_CIWDOFST_WINOFSEN |
+               FLITE_REG_CIWDOFST_WINHOROFST(image->window.offs_h) |
+               FLITE_REG_CIWDOFST_WINVEROFST(image->window.offs_v);
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST));
+
+       hoff2 = image->window.o_width - image->window.width - image->window.offs_h;
+       voff2 = image->window.o_height - image->window.height - image->window.offs_v;
+       cfg = FLITE_REG_CIWDOFST2_WINHOROFST2(hoff2) |
+               FLITE_REG_CIWDOFST2_WINVEROFST2(voff2);
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST2));
+}
+
+static void flite_hw_set_last_capture_end_clear(unsigned long __iomem *base_reg)
+{
+       u32 cfg = 0;
+
+       cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2));
+       cfg &= ~FLITE_REG_CISTATUS2_LASTCAPEND;
+
+       writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2));
+}
+
+int flite_hw_get_present_frame_buffer(unsigned long __iomem *base_reg)
+{
+       u32 status = 0;
+
+       status = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS3));
+       status &= FLITE_REG_CISTATUS3_PRESENT_MASK;
+
+       return status;
+}
+
+int flite_hw_get_status2(unsigned long __iomem *base_reg)
+{
+       u32 status = 0;
+
+       status = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2));
+
+       return status;
+}
+
+void flite_hw_set_status1(unsigned long __iomem *base_reg, u32 val)
+{
+       writel(val, base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS));
+}
+
+int flite_hw_get_status1(unsigned long __iomem *base_reg)
+{
+       u32 status = 0;
+
+       status = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS));
+
+       return status;
+}
+
+int flite_hw_getnclr_status1(unsigned long __iomem *base_reg)
+{
+       u32 status = 0;
+
+       status = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS));
+       writel(0, base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS));
+
+       return status;
+}
+
+void flite_hw_set_status2(unsigned long __iomem *base_reg, u32 val)
+{
+       writel(val, base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2));
+}
+
+void flite_hw_set_start_addr(unsigned long __iomem *base_reg, u32 number, u32 addr)
+{
+       unsigned long __iomem *target_reg;
+
+       if (number == 0) {
+               target_reg = base_reg + TO_WORD_OFFSET(0x30);
+       } else {
+               number--;
+               target_reg = base_reg + TO_WORD_OFFSET(0x200 + (0x4*number));
+       }
+
+       writel(addr, target_reg);
+}
+
+void flite_hw_set_use_buffer(unsigned long __iomem *base_reg, u32 number)
+{
+       u32 buffer;
+       buffer = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIFCNTSEQ));
+       buffer |= 1<<number;
+       writel(buffer, base_reg + TO_WORD_OFFSET(FLITE_REG_CIFCNTSEQ));
+}
+
+void flite_hw_set_unuse_buffer(unsigned long __iomem *base_reg, u32 number)
+{
+       u32 buffer;
+       buffer = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIFCNTSEQ));
+       buffer &= ~(1<<number);
+       writel(buffer, base_reg + TO_WORD_OFFSET(FLITE_REG_CIFCNTSEQ));
+}
+
+u32 flite_hw_get_buffer_seq(unsigned long __iomem *base_reg)
+{
+       return readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIFCNTSEQ));
+}
+
+void flite_hw_set_mux(unsigned long __iomem *base_reg, u32 csi_ch, u32 flite_ch)
+{
+       u32 cfg;
+       if ((csi_ch == 0) && (flite_ch == 1)) {
+               info("[CSI:D] mux setting : CSI0 <-> FLITE1\n");
+               cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGENERAL));
+               cfg |= (1 << 12);
+               writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGENERAL));
+       }
+}
+
+int init_fimc_lite(unsigned long __iomem *base_reg)
+{
+       int i;
+
+       writel(0, base_reg + TO_WORD_OFFSET(FLITE_REG_CIFCNTSEQ));
+
+       for (i = 0; i < 32; i++)
+               flite_hw_set_start_addr(base_reg , i, 0xffffffff);
+
+       return 0;
+}
+
+static int start_fimc_lite(unsigned long __iomem *base_reg,
+       struct fimc_is_image *image,
+       u32 otf_setting,
+       u32 bns,
+       u32 csi_ch,
+       u32 flite_ch)
+{
+       flite_hw_set_cam_channel(base_reg, otf_setting);
+       flite_hw_set_cam_source_size(base_reg, image);
+       flite_hw_set_dma_offset(base_reg, image);
+       flite_hw_set_camera_type(base_reg);
+       flite_hw_set_source_format(base_reg, image);
+       flite_hw_set_inverse_polarity(base_reg);
+       flite_hw_set_interrupt_source(base_reg);
+       flite_hw_set_window_offset(base_reg, image);
+       flite_hw_set_mux(base_reg, csi_ch, flite_ch);
+
+#ifdef COLORBAR_MODE
+       flite_hw_set_test_pattern_enable(base_reg);
+#endif
+
+       if (bns)
+               flite_hw_set_bns(base_reg, image);
+
+       flite_hw_set_last_capture_end_clear(base_reg);
+       flite_hw_set_capture_start(base_reg);
+
+       return 0;
+}
+
+static inline void stop_fimc_lite(unsigned long __iomem *base_reg)
+{
+       flite_hw_set_capture_stop(base_reg);
+}
+
+static inline void flite_s_buffer_addr(struct fimc_is_device_flite *device,
+       u32 bindex, u32 baddr)
+{
+       flite_hw_set_start_addr(device->base_reg, bindex, baddr);
+}
+
+static inline int flite_s_use_buffer(struct fimc_is_device_flite *flite,
+       u32 bindex)
+{
+       int ret = 0;
+       unsigned long target_time;
+
+       BUG_ON(!flite);
+
+       if (!atomic_read(&flite->bcount)) {
+               if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY) {
+                       target_time = jiffies +
+                               msecs_to_jiffies(flite->buf_done_wait_time);
+                       while ((target_time > jiffies) &&
+                                       (flite_hw_get_status1(flite->base_reg) && (7 << 20)))
+                               pr_debug("over vblank (early buffer done)");
+               }
+
+               if (flite_hw_get_status1(flite->base_reg) && (7 << 20)) {
+                       merr("over vblank (buf-mode : %d)", flite, flite->buf_done_mode);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               flite_hw_set_use_buffer(flite->base_reg, bindex);
+               atomic_inc(&flite->bcount);
+               flite_hw_set_output_dma(flite->base_reg, true, flite->image.format.pixelformat);
+       } else {
+               flite_hw_set_use_buffer(flite->base_reg, bindex);
+               atomic_inc(&flite->bcount);
+       }
+
+p_err:
+       return ret;
+}
+
+static inline int flite_s_unuse_buffer(struct fimc_is_device_flite *flite,
+       u32 bindex)
+{
+       int ret = 0;
+       unsigned long target_time;
+
+       BUG_ON(!flite);
+
+       if (atomic_read(&flite->bcount) == 1) {
+               if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY) {
+                       target_time = jiffies +
+                               msecs_to_jiffies(flite->buf_done_wait_time);
+                       while ((target_time > jiffies) &&
+                                       (flite_hw_get_status1(flite->base_reg) && (7 << 20)))
+                               pr_debug("over vblank (early buffer done)");
+               }
+
+               if (flite_hw_get_status1(flite->base_reg) && (7 << 20)) {
+                       merr("over vblank (buf-mode : %d)", flite, flite->buf_done_mode);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               flite_hw_set_output_dma(flite->base_reg, false, flite->image.format.pixelformat);
+               flite_hw_set_unuse_buffer(flite->base_reg, bindex);
+               atomic_dec(&flite->bcount);
+       } else {
+               flite_hw_set_unuse_buffer(flite->base_reg, bindex);
+               atomic_dec(&flite->bcount);
+       }
+
+p_err:
+       return ret;
+}
+
+static inline void flite_set_ovf_stop(struct fimc_is_device_flite *flite)
+{
+       struct fimc_is_device_sensor *device;
+
+       device = container_of(flite->subdev, struct fimc_is_device_sensor, subdev_flite);
+
+       if (test_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state))
+               return;
+
+       /* set dtp */
+       set_bit(FIMC_IS_FLITE_OVERFLOW_STOP, &device->force_stop);
+
+       return;
+}
+
+static u32 g_print_cnt;
+#define LOG_INTERVAL_OF_DROPS 30
+static void tasklet_flite_str0(unsigned long data)
+{
+       struct v4l2_subdev *subdev;
+       struct fimc_is_device_flite *flite;
+       struct fimc_is_device_sensor *device;
+       struct fimc_is_device_ischain *ischain;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group_3aa, *group_isp;
+       u32 bstart, fcount, present;
+
+       subdev = (struct v4l2_subdev *)data;
+       flite = v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               BUG();
+       }
+
+       device = v4l2_get_subdev_hostdata(subdev);
+       if (!device) {
+               err("device is NULL");
+               BUG();
+       }
+
+       present = flite_hw_get_present_frame_buffer(flite->base_reg) - 1;
+       bstart = flite->tasklet_param_str;
+       fcount = atomic_read(&flite->fcount);
+       ischain = device->ischain;
+
+#ifdef TASKLET_MSG
+       info("S%d %d\n", bstart, fcount);
+#endif
+
+       /* comparing sw state and hw state */
+       if (atomic_read(&flite->bcount) == 2) {
+               if ((bstart == FLITE_A_SLOT_VALID) &&
+                       (present != FLITE_A_SLOT_VALID)) {
+                       mwarn("wrong SW buffer slot A(sw:%d != hw:%d)", flite, bstart, present);
+                       flite->sw_trigger = bstart = FLITE_B_SLOT_VALID;
+               }
+
+               if ((bstart == FLITE_B_SLOT_VALID) &&
+                       (present != FLITE_B_SLOT_VALID)) {
+                       mwarn("wrong SW buffer slot B(sw:%d != hw:%d)", flite, bstart, present);
+                       flite->sw_trigger = bstart = FLITE_A_SLOT_VALID;
+               }
+       }
+
+       groupmgr = ischain->groupmgr;
+       group_3aa = &ischain->group_3aa;
+       group_isp = &ischain->group_isp;
+       if (unlikely(list_empty(&group_3aa->smp_trigger.wait_list))) {
+               atomic_set(&group_3aa->sensor_fcount, fcount + group_3aa->async_shots);
+
+               /*
+                * pcount : program count
+                * current program count(location) in kthread
+                */
+               if (((g_print_cnt % LOG_INTERVAL_OF_DROPS) == 0) ||
+                       (g_print_cnt < LOG_INTERVAL_OF_DROPS)) {
+                       info("grp1(res %d, rcnt %d, scnt %d), "
+                               "grp2(res %d, rcnt %d, scnt %d), "
+                               "fcount %d(%d, %d) pcount %d\n",
+                               groupmgr->group_smp_res[group_3aa->id].count,
+                               atomic_read(&group_3aa->rcount),
+                               atomic_read(&group_3aa->scount),
+                               groupmgr->group_smp_res[group_isp->id].count,
+                               atomic_read(&group_isp->rcount),
+                               atomic_read(&group_isp->scount),
+                               fcount + group_3aa->async_shots,
+                               *last_fcount0, *last_fcount1, group_3aa->pcount);
+               }
+               g_print_cnt++;
+       } else {
+               g_print_cnt = 0;
+               atomic_set(&group_3aa->sensor_fcount, fcount + group_3aa->async_shots);
+               up(&group_3aa->smp_trigger);
+       }
+
+       v4l2_subdev_notify(subdev, FLITE_NOTIFY_FSTART, &fcount);
+}
+
+static void tasklet_flite_str1(unsigned long data)
+{
+       struct v4l2_subdev *subdev;
+       struct fimc_is_device_flite *flite;
+       u32 bstart, fcount, present;
+
+       subdev = (struct v4l2_subdev *)data;
+       flite = v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               BUG();
+       }
+
+       present = flite_hw_get_present_frame_buffer(flite->base_reg) - 1;
+       bstart = flite->tasklet_param_str;
+       fcount = atomic_read(&flite->fcount);
+
+#ifdef TASKLET_MSG
+       info("S%d %d\n", bstart, fcount);
+#endif
+
+       /* comparing sw state and hw state */
+       if (atomic_read(&flite->bcount) == 2) {
+               if ((bstart == FLITE_A_SLOT_VALID) &&
+                       (present != FLITE_A_SLOT_VALID)) {
+                       mwarn("wrong SW buffer slot A(sw:%d != hw:%d)", flite, bstart, present);
+                       flite->sw_trigger = bstart = FLITE_B_SLOT_VALID;
+               }
+
+               if ((bstart == FLITE_B_SLOT_VALID) &&
+                       (present != FLITE_B_SLOT_VALID)) {
+                       mwarn("wrong SW buffer slot B(sw:%d != hw:%d)", flite, bstart, present);
+                       flite->sw_trigger = bstart = FLITE_A_SLOT_VALID;
+               }
+       }
+
+       if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY) {
+               flite->early_work_called = false;
+               if (flite->early_work_skip == true) {
+                       info("flite early work skip");
+                       flite->early_work_skip = false;
+               } else {
+                       queue_delayed_work(flite->early_workqueue, &flite->early_work_wq,
+                                       msecs_to_jiffies(flite->buf_done_wait_time));
+               }
+       }
+
+       v4l2_subdev_notify(subdev, FLITE_NOTIFY_FSTART, &fcount);
+}
+
+static void tasklet_flite_end(unsigned long data)
+{
+       struct fimc_is_device_flite *flite;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       struct fimc_is_frame *frame_done;
+       struct v4l2_subdev *subdev;
+       u32 bdone;
+
+       frame_done = NULL;
+       subdev = (struct v4l2_subdev *)data;
+       flite = v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               BUG();
+       }
+
+       if ((flite->buf_done_mode == FLITE_BUF_DONE_EARLY) &&
+               test_bit(FLITE_LAST_CAPTURE, &flite->state)) {
+               info("Skip due to Last Frame Capture\n");
+               return;
+       }
+
+#ifdef ENABLE_FLITE_OVERFLOW_STOP
+       if (unlikely(flite->overflow_cnt)) {
+               flite_set_ovf_stop(flite);
+               goto ovf_exit;
+       }
+#endif
+
+       framemgr = flite->framemgr;
+       bdone = flite->tasklet_param_end;
+
+#ifdef TASKLET_MSG
+       info("E%d %d\n", bdone, atomic_read(&flite->fcount));
+#endif
+
+       if (flite_hw_check_ovf_interrupt_source(flite->base_reg))
+               flite_hw_set_ovf_interrupt_source(flite->base_reg);
+
+       framemgr_e_barrier(framemgr, FMGR_IDX_1 + bdone);
+
+       if (test_bit(bdone, &flite->state)) {
+               fimc_is_frame_process_head(framemgr, &frame);
+               if (frame) {
+#ifdef MEASURE_TIME
+#ifdef EXTERNAL_TIME
+                       do_gettimeofday(&frame->tzone[TM_FLITE_END]);
+#endif
+#endif
+                       /* 1. current frame transition to completion */
+                       frame_done = frame;
+
+                       /* 2. next frame ready */
+                       fimc_is_frame_request_head(framemgr, &frame);
+                       if (frame) {
+                               flite_s_buffer_addr(flite, bdone,
+                                       frame->dvaddr_buffer[0]);
+                               set_bit(bdone, &flite->state);
+                               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+                       } else {
+                               if (!flite_s_unuse_buffer(flite, bdone)) {
+                                       clear_bit(bdone, &flite->state);
+#ifdef TASKLET_MSG
+                                       merr("[SEN] request is empty0(%d slot)", flite, bdone);
+#endif
+                               } else {
+                                       frame_done = NULL;
+                               }
+                       }
+
+                       if (frame_done)
+                               fimc_is_frame_trans_pro_to_com(framemgr, frame_done);
+
+               } else {
+#ifdef TASKLET_MSG
+                       merr("[SEN] process is empty(%d, %ld)", flite, bdone, flite->state);
+                       fimc_is_frame_print_all(framemgr);
+#endif
+               }
+       } else {
+               fimc_is_frame_request_head(framemgr, &frame);
+               if (frame) {
+                       flite_s_buffer_addr(flite, bdone, frame->dvaddr_buffer[0]);
+                       if (!flite_s_use_buffer(flite, bdone)) {
+                               set_bit(bdone, &flite->state);
+                               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+
+                               /* swap process queue list */
+                               fimc_is_frame_swap_process_head(framemgr);
+                       }
+               } else {
+#ifdef TASKLET_MSG
+                       merr("request is empty1(%d slot)", flite, bdone);
+                       fimc_is_frame_print_all(framemgr);
+#endif
+               }
+       }
+
+       framemgr_x_barrier(framemgr, FMGR_IDX_1 + bdone);
+
+#ifdef ENABLE_FLITE_OVERFLOW_STOP
+ovf_exit:
+#endif
+       v4l2_subdev_notify(subdev, FLITE_NOTIFY_FEND, frame_done);
+       flite->early_work_called = true;
+}
+
+static void tasklet_flite_end_chk(unsigned long data)
+{
+       struct v4l2_subdev *subdev = NULL;
+       struct fimc_is_device_flite *flite = NULL;
+       subdev = (struct v4l2_subdev *)data;
+       flite = v4l2_get_subdevdata(subdev);
+
+       if (flite->early_work_called == false) {
+               u32 fcount = atomic_read(&flite->fcount);
+               info("[CamIF%d][%08d] delayed work queue was slower than end irq",
+                       flite->instance, fcount);
+       }
+
+       return;
+}
+
+#ifdef SUPPORTED_EARLY_BUF_DONE
+static void wq_func_flite_early_work(struct work_struct *data)
+{
+       struct fimc_is_device_flite *flite = NULL;
+       struct delayed_work *early_work_wq = NULL;
+
+       early_work_wq = container_of(data, struct delayed_work,
+               work);
+       flite = container_of(early_work_wq, struct fimc_is_device_flite,
+               early_work_wq);
+
+       if (!flite) {
+               err("flite is NULL");
+               BUG();
+       }
+
+       flite->tasklet_param_end = flite->sw_trigger;
+       tasklet_schedule(&flite->tasklet_flite_early_end);
+}
+
+static void chk_early_buf_done(struct fimc_is_device_flite *flite, u32 framerate, u32 position)
+{
+       /* ms */
+       u32 margin = 0;
+       u32 duration = 0;
+
+       /* HACK: applied on 15~30fps forcely */
+       if (framerate > 15 && framerate <= 30) {
+
+               duration = 1000 / framerate;
+
+               if (position == SENSOR_POSITION_REAR)
+                       flite->early_buf_done_mode = FLITE_BUF_EARLY_30P;
+               else
+                       flite->early_buf_done_mode = FLITE_BUF_EARLY_20P;
+
+               margin = FLITE_VVALID_TIME_BASE * (flite->early_buf_done_mode * 0.1f);
+
+               if (margin >= duration) {
+                       /* normal buffer done mode */
+                       flite->buf_done_mode = FLITE_BUF_DONE_NORMAL;
+                       flite->early_buf_done_mode = FLITE_BUF_EARLY_NOTHING;
+                       flite->buf_done_wait_time = 0;
+               } else {
+                       /* early buffer done mode */
+                       flite->buf_done_mode = FLITE_BUF_DONE_EARLY;
+                       flite->buf_done_wait_time = duration - margin;
+               }
+       } else {
+               /* normal buffer done mode */
+               flite->buf_done_mode = FLITE_BUF_DONE_NORMAL;
+               flite->early_buf_done_mode = FLITE_BUF_EARLY_NOTHING;
+               flite->buf_done_wait_time = 0;
+       }
+
+       info("[CamIF%d] buffer done mode [m%d/em%d/du%d/mg%d/wt%d]", flite->instance,
+               flite->buf_done_mode, flite->early_buf_done_mode, duration, margin,
+               flite->buf_done_wait_time);
+}
+#endif
+
+static inline void notify_fcount(struct fimc_is_device_flite *flite)
+{
+       if (test_bit(FLITE_JOIN_ISCHAIN, &flite->state)) {
+               if (flite->instance== FLITE_ID_A)
+                       writel(atomic_read(&flite->fcount), notify_fcount_sen0);
+               else if (flite->instance == FLITE_ID_B)
+                       writel(atomic_read(&flite->fcount), notify_fcount_sen1);
+               else if (flite->instance == FLITE_ID_C)
+                       writel(atomic_read(&flite->fcount), notify_fcount_sen2);
+               else
+                       err("unresolved channel(%d)", flite->instance);
+       }
+}
+
+static irqreturn_t fimc_is_flite_isr(int irq, void *data)
+{
+       u32 status, status1, status2, i;
+       struct fimc_is_device_flite *flite;
+
+       flite = data;
+       status1 = flite_hw_getnclr_status1(flite->base_reg);
+       status = status1 & (3 << 4);
+
+       if (test_bit(FLITE_LAST_CAPTURE, &flite->state)) {
+               if (status1) {
+                       info("[CamIF%d] last status1 : 0x%08X\n", flite->instance, status1);
+                       goto clear_status;
+               }
+
+               err("[CamIF%d] unintended intr is occured", flite->instance);
+
+               for (i = 0; i < 278; i += 4)
+                       info("REG[%X] : 0x%08X\n", i, readl(flite->base_reg + i));
+
+               flite_hw_force_reset(flite->base_reg);
+
+               goto clear_status;
+       }
+
+       if (status) {
+               if (status == (3 << 4)) {
+#ifdef DBG_FLITEISR
+                       printk(KERN_CONT "*");
+#endif
+                       /* frame both interrupt since latency */
+                       if (flite->sw_checker) {
+#ifdef DBG_FLITEISR
+                               printk(KERN_CONT ">");
+#endif
+                               /* frame end interrupt */
+                               flite->sw_checker = EXPECT_FRAME_START;
+                               flite->tasklet_param_end = flite->sw_trigger;
+                               tasklet_schedule(&flite->tasklet_flite_end);
+#ifdef DBG_FLITEISR
+                               printk(KERN_CONT "<");
+#endif
+                               /* frame start interrupt */
+                               flite->sw_checker = EXPECT_FRAME_END;
+                               if (flite->sw_trigger)
+                                       flite->sw_trigger = FLITE_A_SLOT_VALID;
+                               else
+                                       flite->sw_trigger = FLITE_B_SLOT_VALID;
+                               flite->tasklet_param_str = flite->sw_trigger;
+                               atomic_inc(&flite->fcount);
+                               notify_fcount(flite);
+                               tasklet_schedule(&flite->tasklet_flite_str);
+                       } else {
+                               /* W/A: Skip start tasklet at interrupt lost case */
+                               warn("[CamIF%d] invalid interrupt interval",
+                                       flite->instance);
+                               goto clear_status;
+/* HACK: Disable dead code because of Prevent Issue */
+#if 0
+#ifdef DBG_FLITEISR
+                               printk(KERN_CONT "<");
+#endif
+                               /* frame start interrupt */
+                               flite->sw_checker = EXPECT_FRAME_END;
+                               if (flite->sw_trigger)
+                                       flite->sw_trigger = FLITE_A_SLOT_VALID;
+                               else
+                                       flite->sw_trigger = FLITE_B_SLOT_VALID;
+                               flite->tasklet_param_str = flite->sw_trigger;
+                               atomic_inc(&flite->fcount);
+                               notify_fcount(flite);
+                               if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY)
+                                       flite->early_work_skip = true;
+                               tasklet_schedule(&flite->tasklet_flite_str);
+#ifdef DBG_FLITEISR
+                               printk(KERN_CONT ">");
+#endif
+                               /* frame end interrupt */
+                               flite->sw_checker = EXPECT_FRAME_START;
+                               flite->tasklet_param_end = flite->sw_trigger;
+                               if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY)
+                                       tasklet_schedule(&flite->tasklet_flite_early_end);
+                               tasklet_schedule(&flite->tasklet_flite_end);
+#endif
+                       }
+               } else if (status == (2 << 4)) {
+                       /* W/A: Skip start tasklet at interrupt lost case */
+                       if (flite->sw_checker != EXPECT_FRAME_START)
+                               warn("[CamIF%d] Lost end interupt\n",
+                                       flite->instance);
+#ifdef DBG_FLITEISR
+                       printk(KERN_CONT "<");
+#endif
+                       /* frame start interrupt */
+                       flite->sw_checker = EXPECT_FRAME_END;
+                       if (flite->sw_trigger)
+                               flite->sw_trigger = FLITE_A_SLOT_VALID;
+                       else
+                               flite->sw_trigger = FLITE_B_SLOT_VALID;
+                       flite->tasklet_param_str = flite->sw_trigger;
+                       atomic_inc(&flite->fcount);
+                       notify_fcount(flite);
+                       tasklet_schedule(&flite->tasklet_flite_str);
+               } else {
+                       /* W/A: Skip end tasklet at interrupt lost case */
+                       if (flite->sw_checker != EXPECT_FRAME_END) {
+                               warn("[CamIF%d] Lost start interupt\n",
+                                       flite->instance);
+                               goto clear_status;
+                       }
+#ifdef DBG_FLITEISR
+                       printk(KERN_CONT ">");
+#endif
+                       /* frame end interrupt */
+                       flite->sw_checker = EXPECT_FRAME_START;
+                       if (flite->buf_done_mode == FLITE_BUF_DONE_NORMAL)
+                               flite->tasklet_param_end = flite->sw_trigger;
+                       tasklet_schedule(&flite->tasklet_flite_end);
+               }
+       }
+
+clear_status:
+       if (status1 & (1 << 6)) {
+               /* Last Frame Capture Interrupt */
+               info("[CamIF%d] Last Frame Capture(fcount : %d)\n",
+                       flite->instance, atomic_read(&flite->fcount));
+
+               /* Clear LastCaptureEnd bit */
+               status2 = flite_hw_get_status2(flite->base_reg);
+               status2 &= ~(0x1 << 1);
+               flite_hw_set_status2(flite->base_reg, status2);
+
+               /* Notify last capture */
+               set_bit(FLITE_LAST_CAPTURE, &flite->state);
+               wake_up(&flite->wait_queue);
+       }
+
+       if (status1 & (1 << 8)) {
+               u32 ciwdofst;
+
+               flite_hw_clr_ovf_interrupt_source(flite->base_reg);
+               flite->overflow_cnt++;
+
+               if ((flite->overflow_cnt % FLITE_OVERFLOW_COUNT == 0) ||
+                       (flite->overflow_cnt < FLITE_OVERFLOW_COUNT))
+                       pr_err("[CamIF%d] OFCR(cnt:%u)\n", flite->instance, flite->overflow_cnt);
+               ciwdofst = readl(flite->base_reg + TO_WORD_OFFSET(0x10));
+               ciwdofst  |= (0x1 << 14);
+               writel(ciwdofst, flite->base_reg + TO_WORD_OFFSET(0x10));
+               ciwdofst  &= ~(0x1 << 14);
+               writel(ciwdofst, flite->base_reg + TO_WORD_OFFSET(0x10));
+       }
+
+       if (status1 & (1 << 9)) {
+               u32 ciwdofst;
+
+               flite_hw_clr_ovf_interrupt_source(flite->base_reg);
+               flite->overflow_cnt++;
+
+               if ((flite->overflow_cnt % FLITE_OVERFLOW_COUNT == 0) ||
+                       (flite->overflow_cnt < FLITE_OVERFLOW_COUNT))
+                       pr_err("[CamIF%d] OFCB(cnt:%u)\n", flite->instance, flite->overflow_cnt);
+               ciwdofst = readl(flite->base_reg + TO_WORD_OFFSET(0x10));
+               ciwdofst  |= (0x1 << 15);
+               writel(ciwdofst, flite->base_reg + TO_WORD_OFFSET(0x10));
+               ciwdofst  &= ~(0x1 << 15);
+               writel(ciwdofst, flite->base_reg + TO_WORD_OFFSET(0x10));
+       }
+
+       if (status1 & (1 << 10)) {
+               u32 ciwdofst;
+
+               flite_hw_clr_ovf_interrupt_source(flite->base_reg);
+               flite->overflow_cnt++;
+
+               if ((flite->overflow_cnt % FLITE_OVERFLOW_COUNT == 0) ||
+                       (flite->overflow_cnt < FLITE_OVERFLOW_COUNT)) {
+                       pr_err("[CamIF%d] OFY(cnt:%u)\n", flite->instance, flite->overflow_cnt);
+#ifdef ENABLE_FLITE_OVERFLOW_STOP
+                       tasklet_schedule(&flite->tasklet_flite_end);
+#endif
+               }
+               ciwdofst = readl(flite->base_reg + TO_WORD_OFFSET(0x10));
+               ciwdofst  |= (0x1 << 30);
+               writel(ciwdofst, flite->base_reg + TO_WORD_OFFSET(0x10));
+               ciwdofst  &= ~(0x1 << 30);
+               writel(ciwdofst, flite->base_reg + TO_WORD_OFFSET(0x10));
+       }
+
+       return IRQ_HANDLED;
+}
+
+int fimc_is_flite_open(struct v4l2_subdev *subdev,
+       struct fimc_is_framemgr *framemgr)
+{
+       int ret = 0;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!subdev);
+       BUG_ON(!framemgr);
+
+       flite = v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       flite->group = 0;
+       flite->framemgr = framemgr;
+       atomic_set(&flite->fcount, 0);
+       atomic_set(&flite->bcount, 0);
+
+       clear_bit(FLITE_JOIN_ISCHAIN, &flite->state);
+       clear_bit(FLITE_OTF_WITH_3AA, &flite->state);
+       clear_bit(FLITE_LAST_CAPTURE, &flite->state);
+       clear_bit(FLITE_A_SLOT_VALID, &flite->state);
+       clear_bit(FLITE_B_SLOT_VALID, &flite->state);
+
+       switch(flite->instance) {
+       case FLITE_ID_A:
+               ret = request_irq(IRQ_FIMC_LITE0,
+                       fimc_is_flite_isr,
+                       IRQF_SHARED,
+                       "fimc-lite0",
+                       flite);
+               if (ret)
+                       err("request_irq(L0) failed\n");
+               break;
+       case FLITE_ID_B:
+               ret = request_irq(IRQ_FIMC_LITE1,
+                       fimc_is_flite_isr,
+                       IRQF_SHARED,
+                       "fimc-lite1",
+                       flite);
+               if (ret)
+                       err("request_irq(L1) failed\n");
+               break;
+#ifdef IRQ_FIMC_LITE2
+       case FLITE_ID_C:
+               ret = request_irq(IRQ_FIMC_LITE2,
+                       fimc_is_flite_isr,
+                       IRQF_SHARED,
+                       "fimc-lite2",
+                       flite);
+               if (ret)
+                       err("request_irq(L2) failed\n");
+               break;
+#endif
+       default:
+               err("instance is invalid(%d)", flite->instance);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_flite_close(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!subdev);
+
+       flite = v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       switch(flite->instance) {
+       case FLITE_ID_A:
+               free_irq(IRQ_FIMC_LITE0, flite);
+               break;
+       case FLITE_ID_B:
+               free_irq(IRQ_FIMC_LITE1, flite);
+               break;
+#ifdef IRQ_FIMC_LITE2
+       case FLITE_ID_C:
+               free_irq(IRQ_FIMC_LITE2, flite);
+               break;
+#endif
+       default:
+               err("instance is invalid(%d)", flite->instance);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+/* value : csi ch */
+static int flite_init(struct v4l2_subdev *subdev, u32 value)
+{
+       int ret = 0;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!subdev);
+
+       flite = v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       flite->csi = value;
+
+p_err:
+       return ret;
+}
+
+static int flite_stream_on(struct v4l2_subdev *subdev,
+       struct fimc_is_device_flite *flite)
+{
+       int ret = 0;
+       u32 otf_setting, bns;
+       bool buffer_ready;
+       unsigned long flags;
+       struct fimc_is_image *image;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       struct fimc_is_device_sensor *device = v4l2_get_subdev_hostdata(subdev);
+
+       BUG_ON(!flite);
+       BUG_ON(!flite->framemgr);
+       BUG_ON(!device);
+
+       otf_setting = 0;
+       buffer_ready = false;
+       framemgr = flite->framemgr;
+       image = &flite->image;
+       bns = device->pdata->is_bns;
+
+       flite->overflow_cnt = 0;
+       flite->sw_trigger = FLITE_B_SLOT_VALID;
+       flite->sw_checker = EXPECT_FRAME_START;
+       flite->tasklet_param_str = 0;
+       flite->tasklet_param_end = 0;
+       atomic_set(&flite->bcount, 0);
+       clear_bit(FLITE_LAST_CAPTURE, &flite->state);
+       clear_bit(FLITE_A_SLOT_VALID, &flite->state);
+       clear_bit(FLITE_B_SLOT_VALID, &flite->state);
+
+       /* 1. init */
+       flite_hw_force_reset(flite->base_reg);
+       init_fimc_lite(flite->base_reg);
+
+       /* 2. dma setting */
+       framemgr_e_barrier_irqs(framemgr, 0, flags);
+
+       if (framemgr->frame_req_cnt >= 1) {
+               fimc_is_frame_request_head(framemgr, &frame);
+               flite_s_use_buffer(flite, FLITE_A_SLOT_VALID);
+               flite_s_buffer_addr(flite, FLITE_A_SLOT_VALID, frame->dvaddr_buffer[0]);
+               set_bit(FLITE_A_SLOT_VALID, &flite->state);
+               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+               buffer_ready = true;
+       }
+
+       if (framemgr->frame_req_cnt >= 1) {
+               fimc_is_frame_request_head(framemgr, &frame);
+               flite_s_use_buffer(flite, FLITE_B_SLOT_VALID);
+               flite_s_buffer_addr(flite, FLITE_B_SLOT_VALID, frame->dvaddr_buffer[0]);
+               set_bit(FLITE_B_SLOT_VALID, &flite->state);
+               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+               buffer_ready = true;
+       }
+
+       framemgr_x_barrier_irqr(framemgr, 0, flags);
+
+       flite_hw_set_output_dma(flite->base_reg, buffer_ready, image->format.pixelformat);
+
+       /* 3. otf setting */
+       if (device->ischain)
+               set_bit(FLITE_JOIN_ISCHAIN, &flite->state);
+       else
+               clear_bit(FLITE_JOIN_ISCHAIN, &flite->state);
+
+       if (device->ischain && IS_ISCHAIN_OTF(device->ischain)) {
+               tasklet_init(&flite->tasklet_flite_str, tasklet_flite_str0, (unsigned long)subdev);
+               tasklet_init(&flite->tasklet_flite_end, tasklet_flite_end, (unsigned long)subdev);
+
+               if (device->ischain->group_3aa.id == GROUP_ID_3A0) {
+                       flite->group = GROUP_ID_3A0;
+               } else if (device->ischain->group_3aa.id == GROUP_ID_3A1) {
+                       flite->group = GROUP_ID_3A1;
+               } else {
+                       merr("invalid otf path(%d)", device, device->ischain->group_3aa.id);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               mdbgd_back("Enabling OTF path. target 3aa(%d)\n", flite, flite->group);
+               if (flite->instance == FLITE_ID_A) {
+                       if (flite->group == GROUP_ID_3A0)
+                               otf_setting = FLITE_REG_CIGENERAL_CAM_A;
+                       else
+                               otf_setting = FLITE_REG_CIGENERAL_3AA1_CAM_A;
+               } else if (flite->instance == FLITE_ID_B) {
+                       if (flite->group == GROUP_ID_3A0)
+                               otf_setting = FLITE_REG_CIGENERAL_CAM_B;
+                       else
+                               otf_setting = FLITE_REG_CIGENERAL_3AA1_CAM_B;
+               } else {
+                       merr("invalid FLITE channel for OTF setting", flite);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               flite_hw_set_output_local(flite->base_reg, true);
+               set_bit(FLITE_OTF_WITH_3AA, &flite->state);
+       } else {
+               switch (flite->buf_done_mode) {
+               case FLITE_BUF_DONE_NORMAL:
+                       tasklet_init(&flite->tasklet_flite_str, tasklet_flite_str1, (unsigned long)subdev);
+                       tasklet_init(&flite->tasklet_flite_end, tasklet_flite_end, (unsigned long)subdev);
+                       break;
+               case FLITE_BUF_DONE_EARLY:
+                       flite->early_work_skip = false;
+                       flite->early_work_called = false;
+                       tasklet_init(&flite->tasklet_flite_str, tasklet_flite_str1, (unsigned long)subdev);
+                       tasklet_init(&flite->tasklet_flite_early_end, tasklet_flite_end, (unsigned long)subdev);
+                       tasklet_init(&flite->tasklet_flite_end, tasklet_flite_end_chk, (unsigned long)subdev);
+                       break;
+               default:
+                       tasklet_init(&flite->tasklet_flite_str, tasklet_flite_str1, (unsigned long)subdev);
+                       tasklet_init(&flite->tasklet_flite_end, tasklet_flite_end, (unsigned long)subdev);
+                       break;
+               }
+
+               flite_hw_set_output_local(flite->base_reg, false);
+               clear_bit(FLITE_OTF_WITH_3AA, &flite->state);
+       }
+
+       /* 4. register setting */
+       start_fimc_lite(flite->base_reg, image, otf_setting, bns, flite->csi, flite->instance);
+
+p_err:
+       return ret;
+}
+
+static int flite_stream_off(struct v4l2_subdev *subdev,
+       struct fimc_is_device_flite *flite,
+       bool nowait)
+{
+       int ret = 0;
+       unsigned long __iomem *base_reg;
+       unsigned long flags;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!flite);
+       BUG_ON(!flite->base_reg);
+       BUG_ON(!flite->framemgr);
+
+       base_reg = flite->base_reg;
+       framemgr = flite->framemgr;
+
+       /* for preventing invalid memory access */
+       flite_hw_set_unuse_buffer(base_reg, FLITE_A_SLOT_VALID);
+       flite_hw_set_unuse_buffer(base_reg, FLITE_B_SLOT_VALID);
+       flite_hw_set_output_dma(base_reg, false, flite->image.format.pixelformat);
+       flite_hw_set_output_local(base_reg, false);
+
+       stop_fimc_lite(base_reg);
+       if (!nowait) {
+               u32 timetowait;
+
+               timetowait = wait_event_timeout(flite->wait_queue,
+                       test_bit(FLITE_LAST_CAPTURE, &flite->state),
+                       FIMC_IS_FLITE_STOP_TIMEOUT);
+               if (!timetowait) {
+                       /* forcely stop */
+                       stop_fimc_lite(base_reg);
+                       set_bit(FLITE_LAST_CAPTURE, &flite->state);
+                       err("last capture timeout:%s", __func__);
+                       msleep(200);
+                       flite_hw_force_reset(base_reg);
+                       ret = -ETIME;
+               }
+       } else {
+               if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY)
+                       flush_delayed_work(&flite->early_work_wq);
+               /*
+                * DTP test can make iommu fault because senosr is streaming
+                * therefore it need  force reset
+                */
+               flite_hw_force_reset(base_reg);
+       }
+
+       if (flite->buf_done_mode == FLITE_BUF_DONE_EARLY)
+               cancel_delayed_work_sync(&flite->early_work_wq);
+
+       /* clr interrupt source */
+       flite_hw_clr_interrupt_source(base_reg);
+
+       framemgr_e_barrier_irqs(framemgr, FMGR_IDX_3, flags);
+
+       fimc_is_frame_complete_head(framemgr, &frame);
+       while (frame) {
+               fimc_is_frame_trans_com_to_fre(framemgr, frame);
+               fimc_is_frame_complete_head(framemgr, &frame);
+       }
+
+       fimc_is_frame_process_head(framemgr, &frame);
+       while (frame) {
+               fimc_is_frame_trans_pro_to_fre(framemgr, frame);
+               fimc_is_frame_process_head(framemgr, &frame);
+       }
+
+       fimc_is_frame_request_head(framemgr, &frame);
+       while (frame) {
+               fimc_is_frame_trans_req_to_fre(framemgr, frame);
+               fimc_is_frame_request_head(framemgr, &frame);
+       }
+
+       /* buffer done mode init */
+       flite->buf_done_mode = FLITE_BUF_DONE_NORMAL;
+       flite->early_buf_done_mode = FLITE_BUF_EARLY_NOTHING;
+
+       framemgr_x_barrier_irqr(framemgr, FMGR_IDX_3, flags);
+
+       return ret;
+}
+
+/*
+ * enable
+ * @X0 : disable
+ * @X1 : enable
+ * @1X : no waiting flag
+ * @0X : waiting flag
+ */
+static int flite_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       int ret = 0;
+       bool nowait;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!subdev);
+
+       nowait = (enable & FLITE_NOWAIT_MASK) >> FLITE_NOWAIT_SHIFT;
+       enable = enable & FLITE_ENABLE_MASK;
+
+       flite = (struct fimc_is_device_flite *)v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (enable) {
+               ret = flite_stream_on(subdev, flite);
+               if (ret) {
+                       err("flite_stream_on is fail(%d)", ret);
+                       goto p_err;
+               }
+       } else {
+               ret = flite_stream_off(subdev, flite, nowait);
+               if (ret) {
+                       err("flite_stream_off is fail(%d)", ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       mdbgd_back("%s(%d, %d)\n", flite, __func__, enable, ret);
+       return 0;
+}
+
+static int flite_s_format(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *fmt)
+{
+       int ret = 0;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!subdev);
+       BUG_ON(!fmt);
+
+       flite = (struct fimc_is_device_flite *)v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       flite->image.window.offs_h = 0;
+       flite->image.window.offs_v = 0;
+       flite->image.window.width = fmt->width;
+       flite->image.window.height = fmt->height;
+       flite->image.window.o_width = fmt->width;
+       flite->image.window.o_height = fmt->height;
+       flite->image.format.pixelformat = fmt->code;
+
+p_err:
+       mdbgd_back("%s(%dx%d, %X)\n", flite, __func__, fmt->width, fmt->height, fmt->code);
+       return ret;
+}
+
+static int flite_s_ctrl(struct v4l2_subdev *subdev, struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!subdev);
+       BUG_ON(!ctrl);
+
+       flite = (struct fimc_is_device_flite *)v4l2_get_subdevdata(subdev);
+       if (!flite) {
+               err("flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_S_BNS:
+               {
+                       u32 width, height, ratio;
+
+                       width = flite->image.window.width;
+                       height = flite->image.window.height;
+                       ratio = ctrl->value;
+
+                       flite->image.window.otf_width
+                               = rounddown((width * 1000 / ratio), 4);
+                       flite->image.window.otf_height
+                               = rounddown((height * 1000 / ratio), 2);
+               }
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = flite_init,
+       .s_ctrl = flite_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = flite_s_stream,
+       .s_mbus_fmt = flite_s_format
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops
+};
+
+int fimc_is_flite_probe(struct fimc_is_device_sensor *device,
+       u32 instance)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_flite;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!device);
+
+       subdev_flite = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_flite) {
+               merr("subdev_flite is NULL", device);
+               ret = -ENOMEM;
+               goto err_alloc_subdev_flite;
+       }
+       device->subdev_flite = subdev_flite;
+
+       flite = kzalloc(sizeof(struct fimc_is_device_flite), GFP_KERNEL);
+       if (!flite) {
+               merr("flite is NULL", device);
+               ret = -ENOMEM;
+               goto err_alloc_flite;
+       }
+
+       /* pointer to me from device sensor */
+       flite->subdev = &device->subdev_flite;
+       flite->instance = instance;
+       init_waitqueue_head(&flite->wait_queue);
+       switch(instance) {
+       case FLITE_ID_A:
+               flite->base_reg = (unsigned long *)FIMCLITE0_REG_BASE;
+               break;
+       case FLITE_ID_B:
+               flite->base_reg = (unsigned long *)FIMCLITE1_REG_BASE;
+               break;
+       case FLITE_ID_C:
+               flite->base_reg = (unsigned long *)FIMCLITE2_REG_BASE;
+               break;
+       default:
+               err("instance is invalid(%d)", instance);
+               ret = -EINVAL;
+               goto err_invalid_instance;
+       }
+
+       v4l2_subdev_init(subdev_flite, &subdev_ops);
+       v4l2_set_subdevdata(subdev_flite, (void *)flite);
+       v4l2_set_subdev_hostdata(subdev_flite, device);
+       snprintf(subdev_flite->name, V4L2_SUBDEV_NAME_SIZE, "flite-subdev.%d", instance);
+       ret = v4l2_device_register_subdev(&device->v4l2_dev, subdev_flite);
+       if (ret) {
+               merr("v4l2_device_register_subdev is fail(%d)", device, ret);
+               goto err_reg_v4l2_subdev;
+       }
+
+       /* buffer done mode is normal (default) */
+       flite->buf_done_mode = FLITE_BUF_DONE_NORMAL;
+       flite->early_buf_done_mode = FLITE_BUF_EARLY_NOTHING;
+       flite->chk_early_buf_done = NULL;
+#ifdef SUPPORTED_EARLY_BUF_DONE
+       flite->chk_early_buf_done = chk_early_buf_done;
+       flite->early_workqueue = alloc_workqueue("fimc-is/early_workqueue/highpri", WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
+       if (!flite->early_workqueue) {
+               warn("failed to alloc own workqueue, will be use global one");
+               goto err_reg_v4l2_subdev;
+       } else {
+               INIT_DELAYED_WORK(&flite->early_work_wq, wq_func_flite_early_work);
+       }
+#endif
+       info("[BAK:D:%d] %s(%d)\n", instance, __func__, ret);
+       return 0;
+
+err_reg_v4l2_subdev:
+err_invalid_instance:
+       kfree(flite);
+
+err_alloc_flite:
+       kfree(subdev_flite);
+       device->subdev_flite = NULL;
+
+err_alloc_subdev_flite:
+       err("[BAK:D:%d] %s(%d)\n", instance, __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-flite.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-flite.h
new file mode 100644 (file)
index 0000000..825900f
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_FLITE_H
+#define FIMC_IS_DEVICE_FLITE_H
+
+#include <linux/interrupt.h>
+#include "fimc-is-type.h"
+
+#define EXPECT_FRAME_START     0
+#define EXPECT_FRAME_END       1
+
+#define FLITE_NOTIFY_FSTART    0
+#define FLITE_NOTIFY_FEND      1
+
+#define FLITE_ENABLE_FLAG      1
+#define FLITE_ENABLE_MASK      0xFFFF
+#define FLITE_ENABLE_SHIFT     0
+
+#define FLITE_NOWAIT_FLAG      1
+#define FLITE_NOWAIT_MASK      0xFFFF0000
+#define FLITE_NOWAIT_SHIFT     16
+
+#define FLITE_OVERFLOW_COUNT   10
+
+#define FLITE_VVALID_TIME_BASE 32 /* ms */
+
+
+struct fimc_is_device_sensor;
+
+enum fimc_is_flite_state {
+       /* buffer state*/
+       FLITE_A_SLOT_VALID = 0,
+       FLITE_B_SLOT_VALID,
+       /* finish state */
+       FLITE_LAST_CAPTURE,
+       /* flite join ischain */
+       FLITE_JOIN_ISCHAIN,
+       /* one the fly output */
+       FLITE_OTF_WITH_3AA,
+};
+
+enum fimc_is_flite_buf_done_mode {
+       FLITE_BUF_DONE_NORMAL   = 0, /* when end-irq */
+       FLITE_BUF_DONE_EARLY    = 1, /* when delayed work queue since start-irq */
+};
+
+/*
+ * 10p means 10% early than end irq. We supposed that VVALID time is variable
+ * ex. 32 * 0.1 = 3ms, early interval is (33 - 3) = 29ms
+ *     32 * 0.2 = 6ms,                   (33 - 6) = 26ms
+ *     32 * 0.3 = 9ms,                   (33 - 9) = 23ms
+ *     32 * 0.4 = 12ms,                  (33 - 12) = 20ms
+ */
+enum fimc_is_flite_early_buf_done_mode {
+       FLITE_BUF_EARLY_NOTHING = 0,
+       FLITE_BUF_EARLY_10P     = 1, /* 10%(29ms) 3ms */
+       FLITE_BUF_EARLY_20P     = 2, /* 20%(26ms) 6ms */
+       FLITE_BUF_EARLY_30P     = 3, /* 30%(23ms) 9ms */
+       FLITE_BUF_EARLY_40P     = 4, /* 40%(20ms) 12ms */
+};
+
+struct fimc_is_device_flite {
+       u32                             instance;
+       unsigned long __iomem           *base_reg;
+       unsigned long                   state;
+       wait_queue_head_t               wait_queue;
+
+       struct fimc_is_image            image;
+       struct fimc_is_framemgr         *framemgr;
+
+       u32                             overflow_cnt;
+
+       u32                             csi; /* which csi channel is connceted */
+       u32                             group; /* which 3aa gorup is connected when otf is enable */
+
+       u32                             sw_checker;
+       u32                             sw_trigger;
+       atomic_t                        bcount;
+       atomic_t                        fcount;
+       u32                             tasklet_param_str;
+       struct tasklet_struct           tasklet_flite_str;
+       u32                             tasklet_param_end;
+       struct tasklet_struct           tasklet_flite_end;
+
+       /* for early buffer done */
+       u32                             buf_done_mode;
+       u32                             early_buf_done_mode;
+       u32                             buf_done_wait_time;
+       bool                            early_work_skip;
+       bool                            early_work_called;
+       struct tasklet_struct           tasklet_flite_early_end;
+       struct workqueue_struct         *early_workqueue;
+       struct delayed_work             early_work_wq;
+       void                            (*chk_early_buf_done)(struct fimc_is_device_flite *flite, u32 framerate, u32 position);
+
+       /* pointer address from device sensor */
+       struct v4l2_subdev              **subdev;
+};
+
+int fimc_is_flite_probe(struct fimc_is_device_sensor *device,
+       u32 instance);
+int fimc_is_flite_open(struct v4l2_subdev *subdev,
+       struct fimc_is_framemgr *framemgr);
+int fimc_is_flite_close(struct v4l2_subdev *subdev);
+
+extern u32 __iomem *notify_fcount_sen0;
+extern u32 __iomem *notify_fcount_sen1;
+extern u32 __iomem *notify_fcount_sen2;
+extern u32 __iomem *last_fcount0;
+extern u32 __iomem *last_fcount1;
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-ischain.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-ischain.c
new file mode 100644 (file)
index 0000000..2483bc6
--- /dev/null
@@ -0,0 +1,7657 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/vmalloc.h>
+#include <linux/kthread.h>
+#include <linux/pm_qos.h>
+#include <linux/debugfs.h>
+#include <linux/syscalls.h>
+#include <linux/bug.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/smc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#if defined(CONFIG_SOC_EXYNOS3470)
+#include <mach/bts.h>
+#endif
+
+#include "fimc-is-time.h"
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-groupmgr.h"
+#include "fimc-is-device-ischain.h"
+#include "fimc-is-companion.h"
+#include "fimc-is-clk-gate.h"
+#include "fimc-is-dvfs.h"
+#include "fimc-is-device-companion.h"
+#include <linux/pinctrl/consumer.h>
+#include <mach/pinctrl-samsung.h>
+
+#ifdef CONFIG_USE_VENDER_FEATURE
+#include "fimc-is-sec-define.h"
+#else
+#define SDCARD_FW
+#define FIMC_IS_SETFILE_SDCARD_PATH            "/data/"
+#define FIMC_IS_FW                             "fimc_is_fw2.bin"
+#define FIMC_IS_FW_SDCARD                      "/data/fimc_is_fw2.bin"
+
+#define FIMC_IS_FW_BASE_MASK                   ((1 << 26) - 1)
+#define FIMC_IS_VERSION_SIZE                   42
+#define FIMC_IS_SETFILE_VER_OFFSET             0x40
+#define FIMC_IS_SETFILE_VER_SIZE               52
+
+#define FIMC_IS_CAL_SDCARD                     "/data/cal_data.bin"
+#define FIMC_IS_CAL_SDCARD_FRONT                       "/data/cal_data_front.bin"
+#define FIMC_IS_MAX_FW_SIZE                    (2048 * 1024)
+#define FIMC_IS_CAL_START_ADDR                 (0x013D0000)
+#define FIMC_IS_CAL_START_ADDR_FRONT                   (0x013E0000)
+#define FIMC_IS_CAL_RETRY_CNT                  (2)
+#define FIMC_IS_FW_RETRY_CNT                   (2)
+#endif
+
+/* Default setting values */
+#define DEFAULT_PREVIEW_STILL_WIDTH            (1280) /* sensor margin : 16 */
+#define DEFAULT_PREVIEW_STILL_HEIGHT           (720) /* sensor margin : 12 */
+#define DEFAULT_CAPTURE_VIDEO_WIDTH            (1920)
+#define DEFAULT_CAPTURE_VIDEO_HEIGHT           (1080)
+#define DEFAULT_CAPTURE_STILL_WIDTH            (2560)
+#define DEFAULT_CAPTURE_STILL_HEIGHT           (1920)
+#define DEFAULT_CAPTURE_STILL_CROP_WIDTH       (2560)
+#define DEFAULT_CAPTURE_STILL_CROP_HEIGHT      (1440)
+#define DEFAULT_PREVIEW_VIDEO_WIDTH            (640)
+#define DEFAULT_PREVIEW_VIDEO_HEIGHT           (480)
+
+/* sysfs variable for debug */
+extern struct fimc_is_sysfs_debug sysfs_debug;
+
+#ifdef FW_DEBUG
+#define DEBUG_FS_ROOT_NAME     "fimc-is"
+#define DEBUG_FS_FILE_NAME     "isfw-msg"
+static struct dentry           *debugfs_root;
+static struct dentry           *debugfs_file;
+
+#define SETFILE_SIZE   0x6000
+#define READ_SIZE              0x100
+
+static char fw_name[100];
+//static char setf_name[100];
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+#define FIMC_IS_MAX_CAL_SIZE   (8 * 1024)
+#else
+#define FIMC_IS_MAX_CAL_SIZE   (64 * 1024)
+#endif
+#define FIMC_IS_MAX_CAL_SIZE_FRONT     (8 * 1024)
+
+#define FIMC_IS_DEFAULT_CAL_SIZE       (20 * 1024)
+extern bool crc32_check;
+extern bool crc32_header_check;
+extern bool crc32_check_front;
+extern bool crc32_header_check_front;
+
+static int cam_id;
+#ifdef CONFIG_USE_VENDER_FEATURE
+extern bool is_dumped_fw_loading_needed;
+extern char fw_core_version;
+#else
+bool is_dumped_fw_loading_needed = false;
+#endif
+
+static int isfw_debug_open(struct inode *inode, struct file *file)
+{
+       if (inode->i_private)
+               file->private_data = inode->i_private;
+
+       return 0;
+}
+
+static int isfw_debug_read(struct file *file, char __user *user_buf,
+       size_t buf_len, loff_t *ppos)
+{
+       char *debug;
+       size_t debug_cnt, backup_cnt;
+       size_t count1, count2;
+       size_t buf_count = 0;
+       struct fimc_is_device_ischain *device =
+               (struct fimc_is_device_ischain *)file->private_data;
+       struct fimc_is_ishcain_mem *imemory;
+       struct fimc_is_core *core;
+
+       BUG_ON(!device);
+
+       count1 = 0;
+       count2 = 0;
+       debug_cnt = 0;
+       imemory = &device->imemory;
+       core = (struct fimc_is_core *)device->interface->core;
+
+       if (atomic_read(&core->video_isp.refcount) <= 0) {
+               err("isp video node is not open");
+               goto exit;
+       }
+
+       vb2_ion_sync_for_device(imemory->fw_cookie, DEBUG_OFFSET,
+               DEBUG_CNT, DMA_FROM_DEVICE);
+
+       debug_cnt = *((int *)(imemory->kvaddr + DEBUGCTL_OFFSET)) - DEBUG_OFFSET;
+       backup_cnt = core->debug_cnt;
+
+       if (core->debug_cnt > debug_cnt) {
+               count1 = DEBUG_CNT - core->debug_cnt;
+               count2 = debug_cnt;
+       } else {
+               count1 = debug_cnt - core->debug_cnt;
+               count2 = 0;
+       }
+
+       buf_count = buf_len;
+
+       if (buf_count && count1) {
+               debug = (char *)(imemory->kvaddr + DEBUG_OFFSET + core->debug_cnt);
+
+               if (count1 > buf_count)
+                       count1 = buf_count;
+
+               buf_count -= count1;
+
+               memcpy(user_buf, debug, count1);
+               core->debug_cnt += count1;
+       }
+
+       if (buf_count && count2) {
+               debug = (char *)(imemory->kvaddr + DEBUG_OFFSET);
+
+               if (count2 > buf_count)
+                       count2 = buf_count;
+
+               buf_count -= count2;
+
+               memcpy(user_buf, debug, count2);
+               core->debug_cnt = count2;
+       }
+
+       info("FW_READ : Origin(%d), New(%d) - Length(%d)\n",
+               backup_cnt,
+               core->debug_cnt,
+               (buf_len - buf_count));
+
+exit:
+       return buf_len - buf_count;
+}
+
+static const struct file_operations debug_fops = {
+       .open   = isfw_debug_open,
+       .read   = isfw_debug_read,
+       .llseek = default_llseek
+};
+
+#endif
+
+static const struct sensor_param init_sensor_param = {
+       .config = {
+#ifdef FIXED_FPS_DEBUG
+               .framerate = FIXED_FPS_VALUE,
+               .min_target_fps = FIXED_FPS_VALUE,
+               .max_target_fps = FIXED_FPS_VALUE,
+#else
+               .framerate = 30,
+               .min_target_fps = 15,
+               .max_target_fps = 30,
+#endif
+       },
+};
+
+static const struct taa_param init_taa_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_DISABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = OTF_INPUT_FORMAT_BAYER,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_10BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .bayer_crop_offset_x = 0,
+               .bayer_crop_offset_y = 0,
+               .bayer_crop_width = 0,
+               .bayer_crop_height = 0,
+               .frametime_min = 0,
+               .frametime_max = 33333,
+               .sensor_binning_ratio_x = 1000,
+               .sensor_binning_ratio_y = 1000,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .vdma1_input = {
+               .cmd = DMA_INPUT_COMMAND_DISABLE,
+               .width = 0,
+               .height = 0,
+               .format = 0,
+               .bitwidth = 0,
+               .plane = 0,
+               .order = 0,
+               .bayer_crop_offset_x = 0,
+               .bayer_crop_offset_y = 0,
+               .bayer_crop_width = 0,
+               .bayer_crop_height = 0,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .sensor_binning_ratio_x = 1000,
+               .sensor_binning_ratio_y = 1000,
+               .err = 0,
+       },
+       .ddma_input = {
+               .cmd = DMA_INPUT_COMMAND_DISABLE,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_DISABLE,
+       },
+       .vdma4_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+               .dma_out_mask = 0,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = DMA_INPUT_FORMAT_YUV444,
+               .bitwidth = DMA_INPUT_BIT_WIDTH_8BIT,
+               .plane = DMA_INPUT_PLANE_1,
+               .order = DMA_INPUT_ORDER_YCbCr,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .err = DMA_OUTPUT_ERROR_NO,
+       },
+       .vdma2_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = DMA_OUTPUT_FORMAT_BAYER,
+               .bitwidth = DMA_OUTPUT_BIT_WIDTH_12BIT,
+               .plane = DMA_OUTPUT_PLANE_1,
+               .order = DMA_OUTPUT_ORDER_GB_BG,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .dma_out_mask = 0xFFFFFFFF,
+               .err = DMA_OUTPUT_ERROR_NO,
+       },
+       .ddma_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+       },
+};
+
+static const struct isp_param init_isp_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_DISABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_DISABLE,
+       },
+       .vdma1_input = {
+               .cmd = DMA_INPUT_COMMAND_DISABLE,
+               .width = 0,
+               .height = 0,
+               .format = 0,
+               .bitwidth = 0,
+               .plane = 0,
+               .order = 0,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .sensor_binning_ratio_x = 1000,
+               .sensor_binning_ratio_y = 1000,
+               .err = 0,
+       },
+       .vdma3_input = {
+               .cmd = DMA_INPUT_COMMAND_DISABLE,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV444,
+               .bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+       .vdma4_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+       },
+       .vdma5_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+       },
+};
+
+static const struct drc_param init_drc_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_ENABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .dma_input = {
+               .cmd = DMA_INPUT_COMMAND_DISABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = DMA_INPUT_FORMAT_YUV444,
+               .bitwidth = DMA_INPUT_BIT_WIDTH_8BIT,
+               .plane = DMA_INPUT_PLANE_1,
+               .order = DMA_INPUT_ORDER_YCbCr,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .err = 0,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+};
+
+static const struct scalerc_param init_scalerc_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_ENABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_12BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .bayer_crop_offset_x = 0,
+               .bayer_crop_offset_y = 0,
+               .bayer_crop_width = 0,
+               .bayer_crop_height = 0,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .effect = {
+               .cmd = 0,
+               .arbitrary_cb = 128, /* default value : 128 */
+               .arbitrary_cr = 128, /* default value : 128 */
+               .yuv_range = SCALER_OUTPUT_YUV_RANGE_FULL,
+               .err = 0,
+       },
+       .input_crop = {
+               .cmd = OTF_INPUT_COMMAND_DISABLE,
+               .pos_x = 0,
+               .pos_y = 0,
+               .crop_width = DEFAULT_CAPTURE_STILL_CROP_WIDTH,
+               .crop_height = DEFAULT_CAPTURE_STILL_CROP_HEIGHT,
+               .in_width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .in_height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .out_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .out_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .err = 0,
+       },
+       .output_crop = {
+               .cmd = SCALER_CROP_COMMAND_DISABLE,
+               .pos_x = 0,
+               .pos_y = 0,
+               .crop_width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .crop_height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = DMA_OUTPUT_FORMAT_YUV422,
+               .err = 0,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV444,
+               .bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+       .dma_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+               .width = DEFAULT_CAPTURE_STILL_WIDTH,
+               .height = DEFAULT_CAPTURE_STILL_HEIGHT,
+               .format = DMA_OUTPUT_FORMAT_YUV422,
+               .bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
+               .plane = DMA_OUTPUT_PLANE_1,
+               .order = DMA_OUTPUT_ORDER_CrYCbY,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .dma_out_mask = 0xffff,
+               .reserved[0] = SCALER_DMA_OUT_UNSCALED,
+               .err = DMA_OUTPUT_ERROR_NO,
+       },
+};
+
+static const struct odc_param init_odc_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_ENABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .bayer_crop_offset_x = 0,
+               .bayer_crop_offset_y = 0,
+               .bayer_crop_width = 0,
+               .bayer_crop_height = 0,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV422,
+               .bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+};
+
+static const struct dis_param init_dis_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_ENABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV422,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .bayer_crop_offset_x = 0,
+               .bayer_crop_offset_y = 0,
+               .bayer_crop_width = 0,
+               .bayer_crop_height = 0,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV422,
+               .bitwidth = OTF_OUTPUT_BIT_WIDTH_8BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+};
+static const struct tdnr_param init_tdnr_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_ENABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV422,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .frame = {
+               .cmd = 0,
+               .err = 0,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+       .dma_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = DMA_OUTPUT_FORMAT_YUV420,
+               .bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
+               .plane = DMA_OUTPUT_PLANE_2,
+               .order = DMA_OUTPUT_ORDER_CbCr,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .dma_out_mask = 0xffff,
+               .err = DMA_OUTPUT_ERROR_NO,
+       },
+};
+
+static const struct scalerp_param init_scalerp_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_START,
+               .bypass = CONTROL_BYPASS_ENABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .bayer_crop_offset_x = 0,
+               .bayer_crop_offset_y = 0,
+               .bayer_crop_width = 0,
+               .bayer_crop_height = 0,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .effect = {
+               .cmd = 0,
+               .arbitrary_cb = 128, /* default value : 128 */
+               .arbitrary_cr = 128, /* default value : 128 */
+               .yuv_range = SCALER_OUTPUT_YUV_RANGE_FULL,
+               .err = 0,
+       },
+       .input_crop = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .pos_x = 0,
+               .pos_y = 0,
+               .crop_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .crop_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .in_width = DEFAULT_CAPTURE_VIDEO_WIDTH,
+               .in_height = DEFAULT_CAPTURE_VIDEO_HEIGHT,
+               .out_width = DEFAULT_PREVIEW_STILL_WIDTH,
+               .out_height = DEFAULT_PREVIEW_STILL_HEIGHT,
+               .err = 0,
+       },
+       .output_crop = {
+               .cmd = SCALER_CROP_COMMAND_DISABLE,
+               .pos_x = 0,
+               .pos_y = 0,
+               .crop_width = DEFAULT_PREVIEW_STILL_WIDTH,
+               .crop_height = DEFAULT_PREVIEW_STILL_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV420,
+               .err = 0,
+       },
+       .rotation = {
+               .cmd = 0,
+               .err = 0,
+       },
+       .flip = {
+               .cmd = 0,
+               .err = 0,
+       },
+       .otf_output = {
+               .cmd = OTF_OUTPUT_COMMAND_ENABLE,
+               .width = DEFAULT_PREVIEW_STILL_WIDTH,
+               .height = DEFAULT_PREVIEW_STILL_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_OUTPUT_ORDER_BAYER_GR_BG,
+               .crop_offset_x = 0,
+               .crop_offset_y = 0,
+               .err = OTF_OUTPUT_ERROR_NO,
+       },
+       .dma_output = {
+               .cmd = DMA_OUTPUT_COMMAND_DISABLE,
+               .width = DEFAULT_PREVIEW_STILL_WIDTH,
+               .height = DEFAULT_PREVIEW_STILL_HEIGHT,
+               .format = OTF_OUTPUT_FORMAT_YUV420,
+               .bitwidth = DMA_OUTPUT_BIT_WIDTH_8BIT,
+               .plane = DMA_OUTPUT_PLANE_3,
+               .order = DMA_OUTPUT_ORDER_NO,
+               .buffer_number = 0,
+               .buffer_address = 0,
+               .dma_out_mask = 0xffff,
+               .err = DMA_OUTPUT_ERROR_NO,
+       },
+};
+
+static const struct fd_param init_fd_param = {
+       .control = {
+               .cmd = CONTROL_COMMAND_STOP,
+               .bypass = CONTROL_BYPASS_DISABLE,
+               .err = CONTROL_ERROR_NO,
+       },
+       .otf_input = {
+               .cmd = OTF_INPUT_COMMAND_ENABLE,
+               .width = DEFAULT_PREVIEW_STILL_WIDTH,
+               .height = DEFAULT_PREVIEW_STILL_HEIGHT,
+               .format = OTF_INPUT_FORMAT_YUV444,
+               .bitwidth = OTF_INPUT_BIT_WIDTH_8BIT,
+               .order = OTF_INPUT_ORDER_BAYER_GR_BG,
+               .err = OTF_INPUT_ERROR_NO,
+       },
+       .dma_input = {
+               .cmd = DMA_INPUT_COMMAND_DISABLE,
+               .width = 0, .height = 0,
+               .format = 0, .bitwidth = 0, .plane = 0,
+               .order = 0, .buffer_number = 0, .buffer_address = 0,
+               .err = 0,
+       },
+       .config = {
+               .cmd = FD_CONFIG_COMMAND_MAXIMUM_NUMBER |
+                       FD_CONFIG_COMMAND_ROLL_ANGLE |
+                       FD_CONFIG_COMMAND_YAW_ANGLE |
+                       FD_CONFIG_COMMAND_SMILE_MODE |
+                       FD_CONFIG_COMMAND_BLINK_MODE |
+                       FD_CONFIG_COMMAND_EYES_DETECT |
+                       FD_CONFIG_COMMAND_MOUTH_DETECT |
+                       FD_CONFIG_COMMAND_ORIENTATION |
+                       FD_CONFIG_COMMAND_ORIENTATION_VALUE,
+               .max_number = CAMERA2_MAX_FACES,
+               .roll_angle = FD_CONFIG_ROLL_ANGLE_FULL,
+               .yaw_angle = FD_CONFIG_YAW_ANGLE_45_90,
+               .smile_mode = FD_CONFIG_SMILE_MODE_DISABLE,
+               .blink_mode = FD_CONFIG_BLINK_MODE_DISABLE,
+               .eye_detect = FD_CONFIG_EYES_DETECT_ENABLE,
+               .mouth_detect = FD_CONFIG_MOUTH_DETECT_DISABLE,
+               .orientation = FD_CONFIG_ORIENTATION_DISABLE,
+               .orientation_value = 0,
+               .err = ERROR_FD_NO,
+       },
+};
+
+#ifndef RESERVED_MEM
+static int fimc_is_ishcain_deinitmem(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+
+       vb2_ion_private_free(device->imemory.fw_cookie);
+
+       return ret;
+}
+#endif
+
+static void fimc_is_ischain_cache_flush(struct fimc_is_device_ischain *this,
+       u32 offset, u32 size)
+{
+       vb2_ion_sync_for_device(this->imemory.fw_cookie,
+               offset,
+               size,
+               DMA_TO_DEVICE);
+}
+
+static void fimc_is_ischain_region_invalid(struct fimc_is_device_ischain *device)
+{
+       vb2_ion_sync_for_device(
+               device->imemory.fw_cookie,
+               device->imemory.offset_region,
+               sizeof(struct is_region),
+               DMA_FROM_DEVICE);
+}
+
+static void fimc_is_ischain_region_flush(struct fimc_is_device_ischain *device)
+{
+       vb2_ion_sync_for_device(
+               device->imemory.fw_cookie,
+               device->imemory.offset_region,
+               sizeof(struct is_region),
+               DMA_TO_DEVICE);
+}
+
+void fimc_is_ischain_meta_flush(struct fimc_is_frame *frame)
+{
+#ifdef ENABLE_CACHE
+       vb2_ion_sync_for_device(
+               (void *)frame->cookie_shot,
+               0,
+               frame->shot_size,
+               DMA_TO_DEVICE);
+#endif
+}
+
+void fimc_is_ischain_meta_invalid(struct fimc_is_frame *frame)
+{
+#ifdef ENABLE_CACHE
+       vb2_ion_sync_for_device(
+               (void *)frame->cookie_shot,
+               0,
+               frame->shot_size,
+               DMA_FROM_DEVICE);
+#endif
+}
+
+static void fimc_is_ischain_version(struct fimc_is_device_ischain *this, char *name, const char *load_bin, u32 size)
+{
+       struct fimc_is_from_info *pinfo = NULL;
+       char version_str[60];
+
+       if (!strcmp(fw_name, name)) {
+               memcpy(version_str, &load_bin[size - FIMC_IS_VERSION_SIZE],
+                       FIMC_IS_VERSION_SIZE);
+               version_str[FIMC_IS_VERSION_SIZE] = '\0';
+
+               pinfo = &this->pinfo;
+               memcpy(pinfo->header_ver, &version_str[32], 11);
+               pinfo->header_ver[11] = '\0';
+       } else {
+               memcpy(version_str, &load_bin[size - FIMC_IS_SETFILE_VER_OFFSET],
+                       FIMC_IS_SETFILE_VER_SIZE);
+               version_str[FIMC_IS_SETFILE_VER_SIZE] = '\0';
+
+               pinfo = &this->pinfo;
+               memcpy(pinfo->setfile_ver, &version_str[17], 4);
+               pinfo->setfile_ver[4] = '\0';
+       }
+
+       info("%s version : %s\n", name, version_str);
+}
+
+void fimc_is_ischain_savefirm(struct fimc_is_device_ischain *this)
+{
+#ifdef DEBUG_DUMP_FIRMWARE
+       loff_t pos;
+
+       write_data_to_file("/data/firmware.bin", (char *)this->imemory.kvaddr,
+               (size_t)FIMC_IS_A5_MEM_SIZE, &pos);
+#endif
+}
+
+static int fimc_is_ischain_loadfirm(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       int location = 0;
+       const struct firmware *fw_blob = NULL;
+       u8 *buf = NULL;
+#ifdef USE_ION_ALLOC
+       struct ion_handle *handle = NULL;
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(device->pdev);
+#endif
+#ifdef SDCARD_FW
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long fsize, nread;
+       int fw_requested = 1;
+       char fw_path[100];
+       int retry_count = 0;
+
+       mdbgd_ischain("%s\n", device, __func__);
+#ifdef USE_ION_ALLOC
+       BUG_ON(!core);
+       BUG_ON(!core->fimc_ion_client);
+#endif
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       fp = filp_open(FIMC_IS_FW_SDCARD, O_RDONLY, 0);
+       if (IS_ERR_OR_NULL(fp)) {
+#ifdef CONFIG_USE_VENDER_FEATURE
+               if (is_dumped_fw_loading_needed &&
+                       device->pdev->id == SENSOR_POSITION_REAR) {
+                       snprintf(fw_path, sizeof(fw_path), "%s%s",
+                               FIMC_IS_FW_DUMP_PATH, FIMC_IS_FW);
+                       fp = filp_open(fw_path, O_RDONLY, 0);
+                       if (IS_ERR_OR_NULL(fp)) {
+                               fp = NULL;
+                               ret = -EIO;
+                               set_fs(old_fs);
+                               goto out;
+                       }
+               } else
+#endif
+                       goto request_fw;
+       }
+
+       location = 1;
+       fw_requested = 0;
+       fsize = fp->f_path.dentry->d_inode->i_size;
+       pr_info("start, file path %s, size %ld Bytes\n",
+                       is_dumped_fw_loading_needed ? fw_path : FIMC_IS_FW_SDCARD, fsize);
+#ifdef USE_ION_ALLOC
+       handle = ion_alloc(core->fimc_ion_client, (size_t)fsize, 0,
+                               EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+       if (IS_ERR_OR_NULL(handle)) {
+               err("fimc_is_comp_load_binary:failed to ioc_alloc\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       buf = (u8 *)ion_map_kernel(core->fimc_ion_client, handle);
+       if (IS_ERR_OR_NULL(buf)) {
+               err("fimc_is_comp_load_binary:fail to ion_map_kernle\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+#else
+       buf = vmalloc(fsize);
+       if (!buf) {
+               dev_err(&device->pdev->dev,
+                       "failed to allocate memory\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+#endif
+       nread = vfs_read(fp, (char __user *)buf, fsize, &fp->f_pos);
+       if (nread != fsize) {
+               dev_err(&device->pdev->dev,
+                       "failed to read firmware file, %ld Bytes\n", nread);
+               ret = -EIO;
+               goto out;
+       }
+
+       memcpy((void *)device->imemory.kvaddr, (void *)buf, fsize);
+       fimc_is_ischain_cache_flush(device, 0, fsize + 1);
+       fimc_is_ischain_version(device, fw_name, buf, fsize);
+
+request_fw:
+       if (fw_requested) {
+               set_fs(old_fs);
+#endif
+               retry_count = 3;
+               ret = request_firmware(&fw_blob, fw_name, &device->pdev->dev);
+               while (--retry_count && ret == -EAGAIN) {
+                       err("request_firmware retry(count:%d)", retry_count);
+                       ret = request_firmware(&fw_blob, fw_name, &device->pdev->dev);
+               }
+
+               if (ret) {
+                       err("request_firmware is fail(%d)", ret);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (!fw_blob) {
+                       merr("fw_blob is NULL", device);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (!fw_blob->data) {
+                       merr("fw_blob->data is NULL", device);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               memcpy((void *)device->imemory.kvaddr, fw_blob->data,
+                       fw_blob->size);
+               fimc_is_ischain_cache_flush(device, 0, fw_blob->size + 1);
+               fimc_is_ischain_version(device, fw_name, fw_blob->data,
+                       fw_blob->size);
+#ifdef SDCARD_FW
+       }
+#endif
+
+out:
+#ifdef SDCARD_FW
+#ifdef USE_ION_ALLOC
+       if (!IS_ERR_OR_NULL(buf)) {
+               ion_unmap_kernel(core->fimc_ion_client, handle);
+       }
+
+       if (!IS_ERR_OR_NULL(handle)) {
+               ion_free(core->fimc_ion_client, handle);
+       }
+#endif
+
+       if (!fw_requested) {
+#ifndef USE_ION_ALLOC
+               if (buf) {
+                       vfree(buf);
+               }
+#endif
+               if (!IS_ERR_OR_NULL(fp)) {
+                       filp_close(fp, current->files);
+               }
+               set_fs(old_fs);
+       } else
+#endif
+       {
+               if (!IS_ERR_OR_NULL(fw_blob)) {
+                       release_firmware(fw_blob);
+               }
+       }
+       if (ret)
+               err("firmware loading is fail");
+       else
+               info("Camera: the %s FW were applied successfully.\n",
+                       ((cam_id == CAMERA_SINGLE_REAR) &&
+                               is_dumped_fw_loading_needed) ? "dumped" : "default");
+
+       return ret;
+}
+
+static int fimc_is_ischain_buf_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node,
+       struct fimc_is_queue *queue,
+       struct fimc_is_framemgr *framemgr,
+       u32 width, u32 height,
+       u32 target_addr[],
+       enum fimc_is_frame_output frame_output)
+{
+       int ret = 0;
+       struct fimc_is_frame *frame;
+       u32 frame_size;
+       unsigned long flags;
+
+       framemgr_e_barrier_irqs(framemgr, 0, flags);
+
+       fimc_is_frame_request_head(framemgr, &frame);
+       if (frame) {
+               if (!frame->stream) {
+                       framemgr_x_barrier_irqr(framemgr, 0, flags);
+                       merr("frame->stream is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               frame_size = width * height;
+
+               switch (queue->framecfg.format.pixelformat) {
+               case V4L2_PIX_FMT_NV21:
+               case V4L2_PIX_FMT_NV12:
+                       target_addr[0] = frame->dvaddr_buffer[0];
+                       target_addr[1] = target_addr[0] + frame_size;
+                       break;
+               case V4L2_PIX_FMT_YVU420M:
+                       target_addr[0] = frame->dvaddr_buffer[0];
+                       target_addr[1] = frame->dvaddr_buffer[2];
+                       target_addr[2] = frame->dvaddr_buffer[1];
+                       break;
+               default:
+                       target_addr[0] = frame->dvaddr_buffer[0];
+                       target_addr[1] = frame->dvaddr_buffer[1];
+                       target_addr[2] = frame->dvaddr_buffer[2];
+                       break;
+               }
+
+               frame->stream->findex = ldr_frame->index;
+               set_bit(frame_output, &ldr_frame->out_flag);
+               set_bit(REQ_FRAME, &frame->req_flag);
+               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+       } else {
+               mwarn("%d frame is drop (node-id:%d)", device, ldr_frame->fcount, node->vid);
+               target_addr[0] = 0;
+               target_addr[1] = 0;
+               target_addr[2] = 0;
+               node->request = 0;
+       }
+
+       framemgr_x_barrier_irqr(framemgr, 0, flags);
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_loadsetf(struct fimc_is_device_ischain *device,
+       u32 load_addr, char *setfile_name)
+{
+       int ret = 0;
+       int location = 0;
+       void *address;
+       const struct firmware *fw_blob = NULL;
+       u8 *buf = NULL;
+#ifdef USE_ION_ALLOC
+       struct ion_handle *handle = NULL;
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(device->pdev);
+#endif
+
+#ifdef SDCARD_FW
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long fsize, nread;
+       int fw_requested = 1;
+       char setfile_path[256];
+       u32 retry;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+#ifdef USE_ION_ALLOC
+       BUG_ON(!core);
+       BUG_ON(!core->fimc_ion_client);
+#endif
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       memset(setfile_path, 0x00, sizeof(setfile_path));
+       snprintf(setfile_path, sizeof(setfile_path), "%s%s",
+               FIMC_IS_SETFILE_SDCARD_PATH, setfile_name);
+       fp = filp_open(setfile_path, O_RDONLY, 0);
+       if (IS_ERR_OR_NULL(fp)) {
+#ifdef CONFIG_USE_VENDER_FEATURE
+               if (is_dumped_fw_loading_needed &&
+                       device->pdev->id == SENSOR_POSITION_REAR) {
+                       memset(setfile_path, 0x00, sizeof(setfile_path));
+                       snprintf(setfile_path, sizeof(setfile_path), "%s%s",
+                               FIMC_IS_FW_DUMP_PATH, setfile_name);
+                       fp = filp_open(setfile_path, O_RDONLY, 0);
+                       if (IS_ERR_OR_NULL(fp)) {
+                               ret = -EIO;
+                               fp = NULL;
+                               set_fs(old_fs);
+                               goto out;
+                       }
+               } else
+#endif
+                       goto request_fw;
+       }
+
+       location = 1;
+       fw_requested = 0;
+       fsize = fp->f_path.dentry->d_inode->i_size;
+       info("start, file path %s, size %ld Bytes\n",
+               setfile_path, fsize);
+#ifdef USE_ION_ALLOC
+       handle = ion_alloc(core->fimc_ion_client, (size_t)fsize, 0,
+                               EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+       if (IS_ERR_OR_NULL(handle)) {
+               err("fimc_is_comp_load_binary:failed to ioc_alloc\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       buf = (u8 *)ion_map_kernel(core->fimc_ion_client, handle);
+       if (IS_ERR_OR_NULL(buf)) {
+               err("fimc_is_comp_load_binary:fail to ion_map_kernle\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+#else
+       buf = vmalloc(fsize);
+       if (!buf) {
+               dev_err(&device->pdev->dev,
+                       "failed to allocate memory\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+#endif
+       nread = vfs_read(fp, (char __user *)buf, fsize, &fp->f_pos);
+       if (nread != fsize) {
+               dev_err(&device->pdev->dev,
+                       "failed to read firmware file, %ld Bytes\n", nread);
+               ret = -EIO;
+               goto out;
+       }
+
+       address = (void *)(device->imemory.kvaddr + load_addr);
+       memcpy((void *)address, (void *)buf, fsize);
+       fimc_is_ischain_cache_flush(device, load_addr, fsize + 1);
+       fimc_is_ischain_version(device, setfile_name, buf, fsize);
+
+request_fw:
+       if (fw_requested) {
+               set_fs(old_fs);
+#endif
+
+               retry = 4;
+               ret = request_firmware((const struct firmware **)&fw_blob,
+                       setfile_name, &device->pdev->dev);
+               while (--retry && ret) {
+                       mwarn("request_firmware is fail(%d)", device, ret);
+                       ret = request_firmware((const struct firmware **)&fw_blob,
+                               setfile_name, &device->pdev->dev);
+               }
+
+               if (!retry) {
+                       merr("request_firmware is fail(%d)", device, ret);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (!fw_blob) {
+                       merr("fw_blob is NULL", device);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               if (!fw_blob->data) {
+                       merr("fw_blob->data is NULL", device);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               address = (void *)(device->imemory.kvaddr + load_addr);
+               memcpy(address, fw_blob->data, fw_blob->size);
+               fimc_is_ischain_cache_flush(device, load_addr, fw_blob->size + 1);
+               fimc_is_ischain_version(device, setfile_name, fw_blob->data,
+                       (u32)fw_blob->size);
+
+#ifdef SDCARD_FW
+       }
+#endif
+
+out:
+#ifdef SDCARD_FW
+#ifdef USE_ION_ALLOC
+       if (!IS_ERR_OR_NULL(buf)) {
+               ion_unmap_kernel(core->fimc_ion_client, handle);
+       }
+
+       if (!IS_ERR_OR_NULL(handle)) {
+               ion_free(core->fimc_ion_client, handle);
+       }
+#endif
+
+       if (!fw_requested) {
+#ifndef USE_ION_ALLOC
+               if (buf) {
+                       vfree(buf);
+               }
+#endif
+               if (!IS_ERR_OR_NULL(fp)) {
+                       filp_close(fp, current->files);
+               }
+               set_fs(old_fs);
+       } else
+#endif
+       {
+               if (!IS_ERR_OR_NULL(fw_blob)) {
+                       release_firmware(fw_blob);
+               }
+       }
+
+       if (ret)
+               err("setfile loading is fail");
+       else
+               info("Camera: the %s Setfile were applied successfully.\n",
+                       ((cam_id == CAMERA_SINGLE_REAR) &&
+                               is_dumped_fw_loading_needed) ? "dumped" : "default");
+
+       return ret;
+}
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR) || defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+static int fimc_is_ischain_loadcalb_eeprom(struct fimc_is_device_ischain *device,
+       struct fimc_is_module_enum *active_sensor, int id)
+       {
+               int ret = 0;
+#ifdef CONFIG_USE_VENDER_FEATURE
+               char *cal_ptr;
+               char *cal_buf = NULL;
+               u32 start_addr = 0;
+               int cal_size = 0;
+               struct fimc_is_from_info *finfo;
+
+               mdbgd_ischain("%s\n", device, __func__);
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+               if (id == SENSOR_POSITION_FRONT) {
+                       start_addr = FIMC_IS_CAL_START_ADDR_FRONT;
+                       cal_size = FIMC_IS_MAX_CAL_SIZE_FRONT;
+                       fimc_is_sec_get_sysfs_finfo_front(&finfo);
+                       fimc_is_sec_get_front_cal_buf(&cal_buf);
+               } else
+#endif
+               {
+                       start_addr = FIMC_IS_CAL_START_ADDR;
+                       cal_size = FIMC_IS_MAX_CAL_SIZE;
+                       fimc_is_sec_get_sysfs_finfo(&finfo);
+                       fimc_is_sec_get_cal_buf(&cal_buf);
+               }
+
+               cal_ptr = (char *)(device->imemory.kvaddr + start_addr);
+
+               info("CAL DATA : MAP ver : %c%c%c%c\n", cal_buf[0x30], cal_buf[0x31],
+                       cal_buf[0x32], cal_buf[0x33]);
+
+               /* CRC check */
+               if (id == SENSOR_POSITION_FRONT) {
+                       if (crc32_check_front == true) {
+                               memcpy((void *)(cal_ptr) ,(void *)cal_buf, cal_size);
+                               info("Front Camera : the dumped Cal. data was applied successfully.\n");
+                       } else {
+                               if (crc32_header_check_front == true) {
+                                       pr_err("Front Camera : CRC32 error but only header section is no problem.\n");
+                                       memset((void *)(cal_ptr + 0x1000), 0xFF, cal_size - 0x1000);
+                               } else {
+                                       pr_err("Front Camera : CRC32 error for all section.\n");
+                                       memset((void *)(cal_ptr), 0xFF, cal_size);
+                                       ret = -EIO;
+                               }
+                       }
+               } else {
+                       if (crc32_check == true) {
+                               memcpy((void *)(cal_ptr) ,(void *)cal_buf, cal_size);
+                               info("Rear Camera : the dumped Cal. data was applied successfully.\n");
+                       } else {
+                               if (crc32_header_check == true) {
+                                       pr_err("Rear Camera : CRC32 error but only header section is no problem.\n");
+                                       memset((void *)(cal_ptr + 0x1000), 0xFF, cal_size - 0x1000);
+                               } else {
+                                       pr_err("Rear Camera : CRC32 error for all section.\n");
+                                       memset((void *)(cal_ptr), 0xFF, cal_size);
+                                       ret = -EIO;
+                               }
+                       }
+               }
+
+               fimc_is_ischain_cache_flush(device, start_addr, cal_size);
+               if (ret)
+                       mwarn("calibration loading is fail", device);
+               else
+                       mwarn("calibration loading is success", device);
+
+#endif
+               return ret;
+       }
+#endif
+
+#if !defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+static int fimc_is_ischain_loadcalb(struct fimc_is_device_ischain *device,
+       struct fimc_is_module_enum *active_sensor)
+{
+       int ret = 0;
+#ifdef CONFIG_USE_VENDER_FEATURE
+       char *cal_ptr;
+       struct fimc_is_from_info *sysfs_finfo;
+       char *cal_buf;
+
+#ifdef CONFIG_COMPANION_USE
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(device->pdev);
+#endif
+       mdbgd_ischain("%s\n", device, __func__);
+
+       cal_ptr = (char *)(device->imemory.kvaddr + FIMC_IS_CAL_START_ADDR);
+
+       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+       fimc_is_sec_get_cal_buf(&cal_buf);
+
+       info("CAL DATA : MAP ver : %c%c%c%c\n", cal_buf[0x60], cal_buf[0x61],
+               cal_buf[0x62], cal_buf[0x63]);
+
+       /* CRC check */
+       if (crc32_check == true) {
+#ifdef CONFIG_COMPANION_USE
+               if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+                       memcpy((void *)(cal_ptr) ,(void *)cal_buf, FIMC_IS_MAX_CAL_SIZE);
+                       info("Camera : the dumped Cal. data was applied successfully.\n");
+               } else {
+                       info("Camera : Did not load dumped Cal. Sensor version is lower than V004.\n");
+               }
+#else
+               memcpy((void *)(cal_ptr) ,(void *)cal_buf, FIMC_IS_MAX_CAL_SIZE);
+               info("Camera : the dumped Cal. data was applied successfully.\n");
+#endif
+       } else {
+               if (crc32_header_check == true) {
+                       pr_err("Camera : CRC32 error but only header section is no problem.\n");
+                       memset((void *)(cal_ptr + 0x1000), 0xFF, FIMC_IS_MAX_CAL_SIZE - 0x1000);
+               } else {
+                       pr_err("Camera : CRC32 error for all section.\n");
+                       memset((void *)(cal_ptr), 0xFF, FIMC_IS_MAX_CAL_SIZE);
+                       ret = -EIO;
+               }
+       }
+
+       fimc_is_ischain_cache_flush(device, FIMC_IS_CAL_START_ADDR,
+               FIMC_IS_MAX_CAL_SIZE);
+       if (ret)
+               mwarn("calibration loading is fail", device);
+       else
+               mwarn("calibration loading is success", device);
+#endif
+       return ret;
+}
+#endif
+static void fimc_is_ischain_forcedown(struct fimc_is_device_ischain *this,
+       bool on)
+{
+       if (on) {
+               printk(KERN_INFO "Set low poweroff mode\n");
+               __raw_writel(0x0, PMUREG_ISP_ARM_OPTION);
+               __raw_writel(0x1CF82000, PMUREG_ISP_LOW_POWER_OFF);
+               this->force_down = true;
+       } else {
+               printk(KERN_INFO "Clear low poweroff mode\n");
+               __raw_writel(0xFFFFFFFF, PMUREG_ISP_ARM_OPTION);
+               __raw_writel(0x8, PMUREG_ISP_LOW_POWER_OFF);
+               this->force_down = false;
+       }
+}
+
+#if !defined(CONFIG_SOC_EXYNOS4415)
+void tdnr_s3d_pixel_async_sw_reset(struct fimc_is_device_ischain *this)
+{
+       u32 cfg = readl(SYSREG_GSCBLK_CFG1);
+       /* S3D pixel async sw reset */
+       cfg &= ~(1 << 25);
+       writel(cfg, SYSREG_GSCBLK_CFG1);
+
+       cfg = readl(SYSREG_ISPBLK_CFG);
+       /* 3DNR pixel async sw reset */
+       cfg &= ~(1 << 5);
+       writel(cfg, SYSREG_ISPBLK_CFG);
+}
+#endif
+
+static void fimc_is_a5_power(struct device *dev, int power_flags)
+{
+       u32 timeout;
+
+       /* configuration */
+       __raw_writel(power_flags, PMUREG_ISP_ARM_CONFIGURATION);
+
+       /* option */
+       if (power_flags) {
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+               /* A5 enable[15] */
+               writel((1 << 15), PMUREG_ISP_ARM_OPTION);
+#else
+               /* STANDBY WFI[16] & A5 enable[15] */
+               writel((1 << 16 | 1 << 15), PMUREG_ISP_ARM_OPTION);
+#endif
+       }
+
+       /* status */
+       timeout = 1000;
+       while ((__raw_readl(PMUREG_ISP_ARM_STATUS) & 0x1) != power_flags) {
+               if (timeout == 0)
+                       err("%s can't control power(%d), timeout\n", __func__, power_flags);
+               timeout--;
+               udelay(1);
+       }
+}
+
+int fimc_is_ischain_power(struct fimc_is_device_ischain *device, int on)
+{
+#ifdef CONFIG_ARM_TRUSTZONE
+       int i;
+#endif
+       int ret = 0;
+       u32 debug;
+#if defined(CONFIG_PM_RUNTIME)
+       int rpm_ret;
+#endif
+       u32 val;
+       char setf_name[100];
+
+       struct device *dev = &device->pdev->dev;
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(device->pdev);
+       struct fimc_is_from_info *sysfs_finfo;
+
+       if (on) {
+               /* 1. force poweroff setting */
+               if (device->force_down)
+                       fimc_is_ischain_forcedown(device, false);
+
+               /* 2. FIMC-IS local power enable */
+#if defined(CONFIG_PM_RUNTIME)
+               mdbgd_ischain("pm_runtime_suspended = %d\n", device, pm_runtime_suspended(dev));
+               rpm_ret = pm_runtime_get_sync(dev);
+               if (rpm_ret < 0)
+                       err("pm_runtime_get_sync() return error: %d", rpm_ret);
+#else
+               fimc_is_runtime_resume(dev);
+               info("%s(%d) - fimc_is runtime resume complete\n", __func__, on);
+#endif
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+               if (core->id == SENSOR_POSITION_FRONT) {
+                       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+                       if (!sysfs_finfo->is_caldata_read) {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+                               ret = fimc_is_sec_fw_sel_eeprom(dev, fw_name, setf_name, SENSOR_POSITION_REAR, true);
+#else
+                               ret = fimc_is_sec_fw_sel(core, dev, fw_name, setf_name, true);
+#endif
+                       } else {
+                               snprintf(fw_name, sizeof(fw_name), "%s", sysfs_finfo->load_fw_name);
+                       }
+                       fimc_is_sec_get_sysfs_finfo_front(&sysfs_finfo);
+                       if (!sysfs_finfo->is_caldata_read) {
+                               ret = fimc_is_sec_fw_sel_eeprom(dev, fw_name, setf_name, SENSOR_POSITION_FRONT, false);
+                               if (ret < 0) {
+                                       err("failed to select firmware (%d)", ret);
+                                       clear_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+                                       goto p_err_pm;
+                               }
+                       }
+               } else
+#endif
+               {
+                       fimc_is_sec_get_sysfs_finfo(&sysfs_finfo);
+                       if (!sysfs_finfo->is_caldata_read) {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+                               ret = fimc_is_sec_fw_sel_eeprom(dev, fw_name, setf_name, SENSOR_POSITION_REAR, false);
+#else
+                               ret = fimc_is_sec_fw_sel(core, dev, fw_name, setf_name, false);
+#endif
+                               if (ret < 0) {
+                                       err("failed to select firmware (%d)", ret);
+                                       clear_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+                                       goto p_err_pm;
+                               }
+                       } else {
+                               snprintf(fw_name, sizeof(fw_name), "%s", sysfs_finfo->load_fw_name);
+                       }
+               }
+
+#ifdef CONFIG_COMPANION_USE
+//             ret = fimc_is_sec_concord_fw_sel(core, dev, device->pdata, companion_fw_name, master_setf_name, mode_setf_name);
+               /*if (ret < 0) {
+                       err("failed to select companion firmware (%d)", ret);
+                       clear_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+                       goto exit;
+               }*/
+#endif
+               /* 3. Load IS firmware */
+               ret = fimc_is_ischain_loadfirm(device);
+               if (ret) {
+                       err("failed to fimc_is_request_firmware (%d)", ret);
+                       clear_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+                       ret = -EINVAL;
+                       goto p_err_pm;
+               }
+               set_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+
+#if defined(CONFIG_SOC_EXYNOS5422)
+               tdnr_s3d_pixel_async_sw_reset(device);
+#endif /* defined(CONFIG_SOC_EXYNOS5422) */
+               /* 4. A5 start address setting */
+               mdbgd_ischain("imemory.base(dvaddr) : 0x%08x\n", device, device->imemory.dvaddr);
+               mdbgd_ischain("imemory.base(kvaddr) : 0x%08X\n", device, device->imemory.kvaddr);
+
+               if (!device->imemory.dvaddr) {
+                       merr("firmware device virtual is null", device);
+                       ret = -ENOMEM;
+                       goto p_err_pm;
+               }
+
+               writel(device->imemory.dvaddr, device->regs + BBOAR);
+               val = __raw_readl(device->regs + BBOAR);
+               if(device->imemory.dvaddr != val)
+                       err("dvaddr : %x , BBOAR : %x", device->imemory.dvaddr,val);
+
+#ifdef CONFIG_ARM_TRUSTZONE
+               exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(PA_FIMC_IS_GIC_C + 0x4), 0x000000FF, 0);
+               for (i = 0; i < 3; i++)
+                       exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(PA_FIMC_IS_GIC_D + 0x80 + (i * 4)), 0xFFFFFFFF, 0);
+               for (i = 0; i < 18; i++)
+                       exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(PA_FIMC_IS_GIC_D + 0x400 + (i * 4)), 0x10101010, 0);
+
+               exynos_smc_readsfr(PA_FIMC_IS_GIC_C + 0x4, &debug);
+               info("%s : PA_FIMC_IS_GIC_C : 0x%08x\n", __func__, debug);
+               if (debug == 0x00)
+                       merr("secure configuration is fail[0x131E0004:%08X]", device, debug);
+#endif
+
+               /* To guarantee FW restart */
+               if (__raw_readl(PMUREG_ISP_ARM_STATUS) & 0x1) {
+                       fimc_is_a5_power(dev, 0);
+               }
+
+               /* 5. A5 power on*/
+               fimc_is_a5_power(dev, 1);
+
+               set_bit(FIMC_IS_ISCHAIN_POWER_ON, &device->state);
+
+               /* for mideaserver force down */
+               set_bit(FIMC_IS_ISCHAIN_POWER_ON, &core->state);
+       } else {
+               /* Check FW state for WFI of A5 */
+               debug = readl(device->interface->regs + ISSR6);
+               printk(KERN_INFO "%s: A5 state(0x%x)\n", __func__, debug);
+
+               /* FIMC-IS local power down */
+#if defined(CONFIG_PM_RUNTIME)
+               rpm_ret = pm_runtime_put_sync(dev);
+               if (rpm_ret < 0)
+                       err("pm_runtime_put_sync() return error: %d", rpm_ret);
+               mdbgd_ischain("pm_runtime_suspended = %d\n", device, pm_runtime_suspended(dev));
+
+               if (!pm_runtime_suspended(dev)) {
+                       err("failed to call RPM device callback, try A5 power down manually\n");
+
+                       fimc_is_a5_power(dev, 0);
+               }
+#else
+               fimc_is_a5_power(dev, 0);
+
+               fimc_is_runtime_suspend(dev);
+#endif
+               clear_bit(FIMC_IS_ISCHAIN_POWER_ON, &device->state);
+
+               /* for mideaserver force down */
+               clear_bit(FIMC_IS_ISCHAIN_POWER_ON, &core->state);
+       }
+
+       info("%s(%d)\n", __func__, test_bit(FIMC_IS_ISCHAIN_POWER_ON, &device->state));
+       return ret;
+
+p_err_pm:
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_put_sync(dev);
+#else
+       fimc_is_runtime_suspend(dev);
+#endif
+
+       return ret;
+}
+
+static int fimc_is_itf_s_param(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       u32 lindex,
+       u32 hindex,
+       u32 indexes)
+{
+       int ret = 0;
+       u32 flag, index;
+       u32 dst_base, src_base;
+
+       BUG_ON(!device);
+
+       if (frame) {
+               if (!test_bit(FIMC_IS_ISHCAIN_START, &device->state)) {
+                       merr("s_param is fail, device already is stopped", device);
+                       BUG();
+               }
+
+               dst_base = (u32)&device->is_region->parameter;
+               src_base = (u32)frame->shot->ctl.entry.parameter;
+
+               for (index = 0; lindex && (index < 32); index++) {
+                       flag = 1 << index;
+                       if (lindex & flag) {
+                               memcpy((u32 *)(dst_base + (index * PARAMETER_MAX_SIZE)),
+                                       (u32 *)(src_base + (index * PARAMETER_MAX_SIZE)),
+                                       PARAMETER_MAX_SIZE);
+                               lindex &= ~flag;
+                       }
+               }
+
+               for (index = 0; hindex && (index < 32); index++) {
+                       flag = 1 << index;
+                       if (hindex & flag) {
+                               memcpy((u32 *)(dst_base + ((32 + index) * PARAMETER_MAX_SIZE)),
+                                       (u32 *)(src_base + ((32 + index) * PARAMETER_MAX_SIZE)),
+                                       PARAMETER_MAX_SIZE);
+                               hindex &= ~flag;
+                       }
+               }
+
+               fimc_is_ischain_region_flush(device);
+       } else {
+               /*
+                * this check code is commented until per-frame control is worked fully
+                *
+                * if ( test_bit(FIMC_IS_ISHCAIN_START, &device->state)) {
+                *      merr("s_param is fail, device already is started", device);
+                *      BUG();
+                * }
+                */
+
+               fimc_is_ischain_region_flush(device);
+
+               if (lindex || hindex) {
+                       ret = fimc_is_hw_s_param(device->interface,
+                               device->instance,
+                               lindex,
+                               hindex,
+                               indexes);
+               }
+       }
+
+       return ret;
+}
+
+static void * fimc_is_itf_g_param(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       u32 index)
+{
+       u32 dst_base, src_base, dst_param, src_param;
+
+       BUG_ON(!device);
+
+       if (frame) {
+               if (!test_bit(FIMC_IS_ISHCAIN_START, &device->state)) {
+                       merr("s_param is fail, device already is stopped", device);
+                       BUG();
+               }
+
+               dst_base = (u32)&frame->shot->ctl.entry.parameter[0];
+               dst_param = (dst_base + (index * PARAMETER_MAX_SIZE));
+               src_base = (u32)&device->is_region->parameter;
+               src_param = (src_base + (index * PARAMETER_MAX_SIZE));
+               memcpy((u32 *)dst_param, (u32 *)src_param, PARAMETER_MAX_SIZE);
+       } else {
+               dst_base = (u32)&device->is_region->parameter;
+               dst_param = (dst_base + (index * PARAMETER_MAX_SIZE));
+       }
+
+       return (void *)dst_param;
+}
+
+static int fimc_is_itf_a_param(struct fimc_is_device_ischain *device,
+       u32 group)
+{
+       int ret = 0;
+
+       BUG_ON(!device);
+
+       if (device->setfile >= ISS_SUB_END) {
+               mwarn("setfile id(%d) is invalid", device, device->setfile);
+               device->setfile = ISS_SUB_SCENARIO_STILL_PREVIEW;
+       }
+
+       ret = fimc_is_hw_a_param(device->interface,
+               device->instance,
+               group,
+               device->setfile);
+
+       return ret;
+}
+
+static int fimc_is_itf_f_param(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       u32 group = 0;
+#ifdef DEBUG
+       u32 navailable = 0;
+       struct is_region *region = device->is_region;
+#endif
+
+       mdbgd_ischain(" NAME          SIZE    BINNING    FRAMERATE\n", device);
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state) ||
+               !IS_ISCHAIN_OTF(device))
+               mdbgd_ischain("SENSOR :  %04dx%04d        %1dx%1d          %3d\n",
+                       device,
+                       region->parameter.taa.vdma1_input.width + device->margin_width,
+                       region->parameter.taa.vdma1_input.height + device->margin_height,
+                       (region->parameter.taa.vdma1_input.sensor_binning_ratio_x / 1000),
+                       (region->parameter.taa.vdma1_input.sensor_binning_ratio_y / 1000),
+                       region->parameter.sensor.config.framerate
+                       );
+       else
+               mdbgd_ischain("SENSOR :  %04dx%04d        %1dx%1d          %3d\n",
+                       device,
+                       region->parameter.sensor.dma_output.width,
+                       region->parameter.sensor.dma_output.height,
+                       (region->parameter.taa.otf_input.sensor_binning_ratio_x / 1000),
+                       (region->parameter.taa.otf_input.sensor_binning_ratio_y / 1000),
+                       region->parameter.sensor.config.framerate
+                       );
+       mdbgd_ischain(" NAME    ON  BYPASS PATH        SIZE FORMAT\n", device);
+       mdbgd_ischain("3AX OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.taa.control.cmd,
+               region->parameter.taa.control.bypass,
+               region->parameter.taa.otf_input.cmd,
+               region->parameter.taa.otf_input.width,
+               region->parameter.taa.otf_input.height,
+               region->parameter.taa.otf_input.format
+               );
+       mdbgd_ischain("3AX DI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.taa.control.cmd,
+               region->parameter.taa.control.bypass,
+               region->parameter.taa.vdma1_input.cmd,
+               region->parameter.taa.vdma1_input.width,
+               region->parameter.taa.vdma1_input.height,
+               region->parameter.taa.vdma1_input.format
+               );
+       mdbgd_ischain("3AX DO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.taa.control.cmd,
+               region->parameter.taa.control.bypass,
+               region->parameter.taa.vdma2_output.cmd,
+               region->parameter.taa.vdma2_output.width,
+               region->parameter.taa.vdma2_output.height,
+               region->parameter.taa.vdma2_output.format
+               );
+       mdbgd_ischain("ISP OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.isp.control.cmd,
+               region->parameter.isp.control.bypass,
+               region->parameter.isp.otf_input.cmd,
+               region->parameter.isp.otf_input.width,
+               region->parameter.isp.otf_input.height,
+               region->parameter.isp.otf_input.format
+               );
+       mdbgd_ischain("ISP DI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.isp.control.cmd,
+               region->parameter.isp.control.bypass,
+               region->parameter.isp.vdma1_input.cmd,
+               region->parameter.isp.vdma1_input.width,
+               region->parameter.isp.vdma1_input.height,
+               region->parameter.isp.vdma1_input.format
+               );
+       mdbgd_ischain("ISP OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.isp.control.cmd,
+               region->parameter.isp.control.bypass,
+               region->parameter.isp.otf_output.cmd,
+               region->parameter.isp.otf_output.width,
+               region->parameter.isp.otf_output.height,
+               region->parameter.isp.otf_output.format
+               );
+       mdbgd_ischain("DRC OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.drc.control.cmd,
+               region->parameter.drc.control.bypass,
+               region->parameter.drc.otf_input.cmd,
+               region->parameter.drc.otf_input.width,
+               region->parameter.drc.otf_input.height,
+               region->parameter.drc.otf_input.format
+               );
+       mdbgd_ischain("DRC OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.drc.control.cmd,
+               region->parameter.drc.control.bypass,
+               region->parameter.drc.otf_output.cmd,
+               region->parameter.drc.otf_output.width,
+               region->parameter.drc.otf_output.height,
+               region->parameter.drc.otf_output.format
+               );
+       mdbgd_ischain("SCC OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.scalerc.control.cmd,
+               region->parameter.scalerc.control.bypass,
+               region->parameter.scalerc.otf_input.cmd,
+               region->parameter.scalerc.otf_input.width,
+               region->parameter.scalerc.otf_input.height,
+               region->parameter.scalerc.otf_input.format
+               );
+       mdbgd_ischain("SCC DO : %2d    %4d  %3d   %04dx%04d %4d,%d\n", device,
+               region->parameter.scalerc.control.cmd,
+               region->parameter.scalerc.control.bypass,
+               region->parameter.scalerc.dma_output.cmd,
+               region->parameter.scalerc.dma_output.width,
+               region->parameter.scalerc.dma_output.height,
+               region->parameter.scalerc.dma_output.format,
+               region->parameter.scalerc.dma_output.plane
+               );
+       mdbgd_ischain("SCC OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.scalerc.control.cmd,
+               region->parameter.scalerc.control.bypass,
+               region->parameter.scalerc.otf_output.cmd,
+               region->parameter.scalerc.otf_output.width,
+               region->parameter.scalerc.otf_output.height,
+               region->parameter.scalerc.otf_output.format
+               );
+       mdbgd_ischain("ODC OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.odc.control.cmd,
+               region->parameter.odc.control.bypass,
+               region->parameter.odc.otf_input.cmd,
+               region->parameter.odc.otf_input.width,
+               region->parameter.odc.otf_input.height,
+               region->parameter.odc.otf_input.format
+               );
+       mdbgd_ischain("ODC OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.odc.control.cmd,
+               region->parameter.odc.control.bypass,
+               region->parameter.odc.otf_output.cmd,
+               region->parameter.odc.otf_output.width,
+               region->parameter.odc.otf_output.height,
+               region->parameter.odc.otf_output.format
+               );
+       mdbgd_ischain("DIS OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.dis.control.cmd,
+               region->parameter.dis.control.bypass,
+               region->parameter.dis.otf_input.cmd,
+               region->parameter.dis.otf_input.width,
+               region->parameter.dis.otf_input.height,
+               region->parameter.dis.otf_input.format
+               );
+       mdbgd_ischain("DIS OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.dis.control.cmd,
+               region->parameter.dis.control.bypass,
+               region->parameter.dis.otf_output.cmd,
+               region->parameter.dis.otf_output.width,
+               region->parameter.dis.otf_output.height,
+               region->parameter.dis.otf_output.format
+               );
+       mdbgd_ischain("DNR OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.tdnr.control.cmd,
+               region->parameter.tdnr.control.bypass,
+               region->parameter.tdnr.otf_input.cmd,
+               region->parameter.tdnr.otf_input.width,
+               region->parameter.tdnr.otf_input.height,
+               region->parameter.tdnr.otf_input.format
+               );
+       mdbgd_ischain("DNR OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.tdnr.control.cmd,
+               region->parameter.tdnr.control.bypass,
+               region->parameter.tdnr.otf_output.cmd,
+               region->parameter.tdnr.otf_output.width,
+               region->parameter.tdnr.otf_output.height,
+               region->parameter.tdnr.otf_output.format
+               );
+       mdbgd_ischain("SCP OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.scalerp.control.cmd,
+               region->parameter.scalerp.control.bypass,
+               region->parameter.scalerp.otf_input.cmd,
+               region->parameter.scalerp.otf_input.width,
+               region->parameter.scalerp.otf_input.height,
+               region->parameter.scalerp.otf_input.format
+               );
+       mdbgd_ischain("SCP DO : %2d    %4d  %3d   %04dx%04d %4d,%d\n", device,
+               region->parameter.scalerp.control.cmd,
+               region->parameter.scalerp.control.bypass,
+               region->parameter.scalerp.dma_output.cmd,
+               region->parameter.scalerp.dma_output.width,
+               region->parameter.scalerp.dma_output.height,
+               region->parameter.scalerp.dma_output.format,
+               region->parameter.scalerp.dma_output.plane
+               );
+       mdbgd_ischain("SCP OO : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.scalerp.control.cmd,
+               region->parameter.scalerp.control.bypass,
+               region->parameter.scalerp.otf_output.cmd,
+               region->parameter.scalerp.otf_output.width,
+               region->parameter.scalerp.otf_output.height,
+               region->parameter.scalerp.otf_output.format
+               );
+       mdbgd_ischain("FD  OI : %2d    %4d  %3d   %04dx%04d    %3d\n", device,
+               region->parameter.fd.control.cmd,
+               region->parameter.fd.control.bypass,
+               region->parameter.fd.otf_input.cmd,
+               region->parameter.fd.otf_input.width,
+               region->parameter.fd.otf_input.height,
+               region->parameter.fd.otf_input.format
+               );
+       mdbgd_ischain(" NAME   CMD    IN_SZIE   OT_SIZE      CROP       POS\n", device);
+       mdbgd_ischain("SCC CI :  %d  %04dx%04d %04dx%04d %04dx%04d %04dx%04d\n", device,
+               region->parameter.scalerc.input_crop.cmd,
+               region->parameter.scalerc.input_crop.in_width,
+               region->parameter.scalerc.input_crop.in_height,
+               region->parameter.scalerc.input_crop.out_width,
+               region->parameter.scalerc.input_crop.out_height,
+               region->parameter.scalerc.input_crop.crop_width,
+               region->parameter.scalerc.input_crop.crop_height,
+               region->parameter.scalerc.input_crop.pos_x,
+               region->parameter.scalerc.input_crop.pos_y
+               );
+       mdbgd_ischain("SCC CO :  %d  %04dx%04d %04dx%04d %04dx%04d %04dx%04d\n", device,
+               region->parameter.scalerc.output_crop.cmd,
+               navailable,
+               navailable,
+               navailable,
+               navailable,
+               region->parameter.scalerc.output_crop.crop_width,
+               region->parameter.scalerc.output_crop.crop_height,
+               region->parameter.scalerc.output_crop.pos_x,
+               region->parameter.scalerc.output_crop.pos_y
+               );
+       mdbgd_ischain("SCP CI :  %d  %04dx%04d %04dx%04d %04dx%04d %04dx%04d\n", device,
+               region->parameter.scalerp.input_crop.cmd,
+               region->parameter.scalerp.input_crop.in_width,
+               region->parameter.scalerp.input_crop.in_height,
+               region->parameter.scalerp.input_crop.out_width,
+               region->parameter.scalerp.input_crop.out_height,
+               region->parameter.scalerp.input_crop.crop_width,
+               region->parameter.scalerp.input_crop.crop_height,
+               region->parameter.scalerp.input_crop.pos_x,
+               region->parameter.scalerp.input_crop.pos_y
+               );
+       mdbgd_ischain("SCP CO :  %d  %04dx%04d %04dx%04d %04dx%04d %04dx%04d\n", device,
+               region->parameter.scalerp.output_crop.cmd,
+               navailable,
+               navailable,
+               navailable,
+               navailable,
+               region->parameter.scalerp.output_crop.crop_width,
+               region->parameter.scalerp.output_crop.crop_height,
+               region->parameter.scalerp.output_crop.pos_x,
+               region->parameter.scalerp.output_crop.pos_y
+               );
+
+       group |= GROUP_ID(device->group_3aa.id);
+       group |= GROUP_ID(device->group_isp.id);
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group = GROUP_ID(GROUP_ID_3A0);
+
+       if (device->setfile >= ISS_SUB_END) {
+               mwarn("setfile id(%d) is invalid", device, device->setfile);
+               device->setfile = ISS_SUB_SCENARIO_STILL_PREVIEW;
+       }
+
+       ret = fimc_is_hw_a_param(device->interface,
+               device->instance,
+               (group & GROUP_ID_PARM_MASK),
+               device->setfile);
+       return ret;
+}
+
+static int fimc_is_itf_enum(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+
+       mdbgd_ischain("%s()\n", device, __func__);
+
+       ret = fimc_is_hw_enum(device->interface);
+       if (ret) {
+               merr("fimc_is_itf_enum is fail(%d)", device, ret);
+               CALL_POPS(device, print_pwr, device->pdev);
+               CALL_POPS(device, print_clk, device->pdev);
+       }
+
+       return ret;
+}
+
+static int fimc_is_itf_open(struct fimc_is_device_ischain *device,
+       u32 module_id,
+       u32 group_id,
+       u32 flag,
+       struct sensor_open_extended *ext_info)
+{
+       int ret = 0;
+       struct is_region *region;
+       struct fimc_is_interface *itf;
+
+       BUG_ON(!device);
+       BUG_ON(!device->is_region);
+       BUG_ON(!device->sensor);
+       BUG_ON(!device->interface);
+       BUG_ON(!ext_info);
+
+       region = device->is_region;
+       itf = device->interface;
+
+       memcpy(&region->shared[0], ext_info, sizeof(struct sensor_open_extended));
+
+       fimc_is_ischain_region_flush(device);
+
+       ret = fimc_is_hw_open(device->interface,
+               device->instance,
+               module_id,
+               device->imemory.dvaddr_shared,
+               group_id,
+               flag,
+               &device->margin_width,
+               &device->margin_height);
+       if (ret) {
+               merr("fimc_is_hw_open is fail", device);
+               CALL_POPS(device, print_cfg, device->pdev,
+                               fimc_is_sensor_g_instance(device->sensor));
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* HACK */
+       device->margin_left = 8;
+       device->margin_right = 8;
+       device->margin_top = 6;
+       device->margin_bottom = 4;
+       device->margin_width = device->margin_left + device->margin_right;
+       device->margin_height = device->margin_top + device->margin_bottom;
+       mdbgd_ischain("margin %dx%d\n", device,
+               device->margin_width, device->margin_height);
+
+       fimc_is_ischain_region_invalid(device);
+
+       if (region->shared[MAX_SHARED_COUNT-1] != MAGIC_NUMBER) {
+               merr("MAGIC NUMBER error", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       memset(&region->parameter, 0x0, sizeof(struct is_param_region));
+
+       memcpy(&region->parameter.sensor, &init_sensor_param,
+               sizeof(struct sensor_param));
+       memcpy(&region->parameter.taa, &init_taa_param,
+               sizeof(struct taa_param));
+       memcpy(&region->parameter.isp, &init_isp_param,
+               sizeof(struct isp_param));
+       memcpy(&region->parameter.drc, &init_drc_param,
+               sizeof(struct drc_param));
+       memcpy(&region->parameter.scalerc, &init_scalerc_param,
+               sizeof(struct scalerc_param));
+       memcpy(&region->parameter.odc, &init_odc_param,
+               sizeof(struct odc_param));
+       memcpy(&region->parameter.dis, &init_dis_param,
+               sizeof(struct dis_param));
+       memcpy(&region->parameter.tdnr, &init_tdnr_param,
+               sizeof(struct tdnr_param));
+       memcpy(&region->parameter.scalerp, &init_scalerp_param,
+               sizeof(struct scalerp_param));
+       memcpy(&region->parameter.fd, &init_fd_param,
+               sizeof(struct fd_param));
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_itf_close(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       struct fimc_is_interface *itf;
+
+       BUG_ON(!device);
+       BUG_ON(!device->interface);
+
+       itf = device->interface;
+
+       ret = fimc_is_hw_close(itf, device->instance);
+       if (ret) {
+               merr("fimc_is_hw_close is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_itf_setfile(struct fimc_is_device_ischain *device,
+       char *setfile_name)
+{
+       int ret = 0;
+       u32 setfile_addr = 0;
+       struct fimc_is_interface *itf;
+
+       BUG_ON(!device);
+       BUG_ON(!device->interface);
+       BUG_ON(!setfile_name);
+
+       itf = device->interface;
+
+       mdbgd_ischain("%s(setfile : %s)\n", device, __func__, setfile_name);
+
+       ret = fimc_is_hw_saddr(itf, device->instance, &setfile_addr);
+       if (ret) {
+               merr("fimc_is_hw_saddr is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       if (!setfile_addr) {
+               merr("setfile address is NULL", device);
+               pr_err("cmd : %08X\n", readl(&itf->com_regs->ihcmd));
+               pr_err("id : %08X\n", readl(&itf->com_regs->ihc_sensorid));
+               pr_err("param1 : %08X\n", readl(&itf->com_regs->ihc_param1));
+               pr_err("param2 : %08X\n", readl(&itf->com_regs->ihc_param2));
+               pr_err("param3 : %08X\n", readl(&itf->com_regs->ihc_param3));
+               pr_err("param4 : %08X\n", readl(&itf->com_regs->ihc_param4));
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_loadsetf(device, setfile_addr, setfile_name);
+       if (ret) {
+               merr("fimc_is_ischain_loadsetf is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_hw_setfile(itf, device->instance);
+       if (ret) {
+               merr("fimc_is_hw_setfile is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_itf_map(struct fimc_is_device_ischain *device,
+       u32 group, u32 shot_addr, u32 shot_size)
+{
+       int ret = 0;
+
+       BUG_ON(!device);
+
+       mdbgd_ischain("%s()\n", device, __func__);
+
+       ret = fimc_is_hw_map(device->interface, device->instance, group, shot_addr, shot_size);
+       if (ret)
+               merr("fimc_is_hw_map is fail(%d)", device, ret);
+
+       return ret;
+}
+
+static int fimc_is_itf_unmap(struct fimc_is_device_ischain *device,
+       u32 group)
+{
+       int ret = 0;
+
+       mdbgd_ischain("%s()\n", device, __func__);
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group = GROUP_ID(GROUP_ID_3A0);
+
+       ret = fimc_is_hw_unmap(device->interface, device->instance, group);
+       if (ret)
+               merr("fimc_is_hw_unmap is fail(%d)", device, ret);
+
+       return ret;
+}
+
+int fimc_is_itf_stream_on(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       u32 retry = 10000;
+#ifdef ENABLE_DVFS
+       int scenario_id;
+#endif
+       struct fimc_is_group *group_3aa, *group_isp;
+       struct fimc_is_resourcemgr *resourcemgr;
+
+       BUG_ON(!device);
+       BUG_ON(!device->resourcemgr);
+
+       resourcemgr = device->resourcemgr;
+       group_3aa = &device->group_3aa;
+       group_isp = &device->group_isp;
+
+       /* 3ax, isp group should be started */
+       if (!test_bit(FIMC_IS_GROUP_READY, &group_3aa->state)) {
+               merr("group isp is not start", device);
+               goto p_err;
+       }
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) ||
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1)) {
+               if (!test_bit(FIMC_IS_GROUP_READY, &group_3aa->state)) {
+                       merr("group 3ax is not start", device);
+                       goto p_err;
+               }
+
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group_3aa->state)) {
+                       while (--retry && (atomic_read(&group_3aa->scount) <
+                                               group_3aa->async_shots)) {
+                               udelay(100);
+                       }
+               }
+       }
+
+       if (retry)
+               info("[ISC:D:%d] stream on ready\n", device->instance);
+       else
+               pr_err("[ISC:D:%d] stream on NOT ready\n", device->instance);
+
+#ifdef ENABLE_DVFS
+       mutex_lock(&resourcemgr->dvfs_ctrl.lock);
+       if ((!pm_qos_request_active(&device->user_qos)) &&
+                       (sysfs_debug.en_dvfs)) {
+               /* try to find dynamic scenario to apply */
+               scenario_id = fimc_is_dvfs_sel_scenario(FIMC_IS_STATIC_SN, device, NULL);
+               if (scenario_id >= 0) {
+                       struct fimc_is_dvfs_scenario_ctrl *static_ctrl =
+                               resourcemgr->dvfs_ctrl.static_ctrl;
+                       info("[ISC:D:%d] static scenario(%d)-[%s]\n",
+                                       device->instance, scenario_id,
+                                       static_ctrl->scenarios[static_ctrl->cur_scenario_idx].scenario_nm);
+                       fimc_is_set_dvfs(device, scenario_id);
+               }
+       }
+       mutex_unlock(&resourcemgr->dvfs_ctrl.lock);
+#endif
+       ret = fimc_is_hw_stream_on(device->interface, device->instance);
+       if (ret) {
+               merr("fimc_is_hw_stream_on is fail(%d)", device, ret);
+               CALL_POPS(device, print_clk, device->pdev);
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_itf_stream_off(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+
+       info("[ISC:D:%d] stream off ready\n", device->instance);
+
+       ret = fimc_is_hw_stream_off(device->interface, device->instance);
+
+       return ret;
+}
+
+int fimc_is_itf_process_start(struct fimc_is_device_ischain *device,
+       u32 group)
+{
+       int ret = 0;
+
+       ret = fimc_is_hw_process_on(device->interface,
+               device->instance, group);
+
+       return ret;
+}
+
+int fimc_is_itf_process_stop(struct fimc_is_device_ischain *device,
+       u32 group)
+{
+       int ret = 0;
+
+#ifdef ENABLE_CLOCK_GATE
+       struct fimc_is_core *core = (struct fimc_is_core *)device->interface->core;
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST) {
+               fimc_is_clk_gate_lock_set(core, device->instance, true);
+               fimc_is_wrap_clk_gate_set(core, (1 << GROUP_ID_MAX) - 1, true);
+       }
+#endif
+       ret = fimc_is_hw_process_off(device->interface,
+               device->instance, group, 0);
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+               sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+               fimc_is_clk_gate_lock_set(core, device->instance, false);
+#endif
+       return ret;
+}
+
+int fimc_is_itf_force_stop(struct fimc_is_device_ischain *device,
+       u32 group)
+{
+       int ret = 0;
+
+#ifdef ENABLE_CLOCK_GATE
+       struct fimc_is_core *core = (struct fimc_is_core *)device->interface->core;
+#endif
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group = GROUP_ID(GROUP_ID_3A0);
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST) {
+               fimc_is_clk_gate_lock_set(core, device->instance, true);
+               fimc_is_wrap_clk_gate_set(core, (1 << GROUP_ID_MAX) - 1, true);
+       }
+#endif
+       ret = fimc_is_hw_process_off(device->interface,
+               device->instance, group, 1);
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+               sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+               fimc_is_clk_gate_lock_set(core, device->instance, false);
+#endif
+       return ret;
+}
+
+static int fimc_is_itf_init_process_start(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       u32 group = 0;
+
+       group |= GROUP_ID(device->group_3aa.id);
+       group |= GROUP_ID(device->group_isp.id);
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group = GROUP_ID(GROUP_ID_3A0);
+
+       ret = fimc_is_hw_process_on(device->interface,
+               device->instance,
+               (group & GROUP_ID_PARM_MASK));
+
+       return ret;
+}
+
+static int fimc_is_itf_init_process_stop(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       u32 group = 0;
+
+#ifdef ENABLE_CLOCK_GATE
+       struct fimc_is_core *core = (struct fimc_is_core *)device->interface->core;
+#endif
+       group |= GROUP_ID(device->group_3aa.id);
+       group |= GROUP_ID(device->group_isp.id);
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group = GROUP_ID(GROUP_ID_3A0);
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST) {
+               fimc_is_clk_gate_lock_set(core, device->instance, true);
+               fimc_is_wrap_clk_gate_set(core, (1 << GROUP_ID_MAX) - 1, true);
+
+       }
+#endif
+       ret = fimc_is_hw_process_off(device->interface,
+               device->instance, (group & GROUP_ID_PARM_MASK), 0);
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+               sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+               fimc_is_clk_gate_lock_set(core, device->instance, false);
+#endif
+       return ret;
+}
+
+int fimc_is_itf_i2c_lock(struct fimc_is_device_ischain *this,
+                       int i2c_clk, bool lock)
+{
+       int ret = 0;
+       struct fimc_is_interface *itf = this->interface;
+
+       if (lock)
+               fimc_is_interface_lock(itf);
+
+       ret = fimc_is_hw_i2c_lock(itf, this->instance,
+                               i2c_clk, lock);
+
+       if (!lock)
+               fimc_is_interface_unlock(itf);
+
+       return ret;
+}
+
+int fimc_is_itf_g_capability(struct fimc_is_device_ischain *this)
+{
+       int ret = 0;
+#ifdef PRINT_CAPABILITY
+       u32 metadata;
+       u32 index;
+       struct camera2_sm *capability;
+#endif
+
+       ret = fimc_is_hw_g_capability(this->interface, this->instance,
+               (this->imemory.kvaddr_shared - this->imemory.kvaddr));
+
+       fimc_is_ischain_region_invalid(this);
+
+#ifdef PRINT_CAPABILITY
+       memcpy(&this->capability, &this->is_region->shared,
+               sizeof(struct camera2_sm));
+       capability = &this->capability;
+
+       printk(KERN_INFO "===ColorC================================\n");
+       printk(KERN_INFO "===ToneMapping===========================\n");
+       metadata = capability->tonemap.maxCurvePoints;
+       printk(KERN_INFO "maxCurvePoints : %d\n", metadata);
+
+       printk(KERN_INFO "===Scaler================================\n");
+       printk(KERN_INFO "foramt : %d, %d, %d, %d\n",
+               capability->scaler.availableFormats[0],
+               capability->scaler.availableFormats[1],
+               capability->scaler.availableFormats[2],
+               capability->scaler.availableFormats[3]);
+
+       printk(KERN_INFO "===StatisTicsG===========================\n");
+       index = 0;
+       metadata = capability->stats.availableFaceDetectModes[index];
+       while (metadata) {
+               printk(KERN_INFO "availableFaceDetectModes : %d\n", metadata);
+               index++;
+               metadata = capability->stats.availableFaceDetectModes[index];
+       }
+       printk(KERN_INFO "maxFaceCount : %d\n",
+               capability->stats.maxFaceCount);
+       printk(KERN_INFO "histogrambucketCount : %d\n",
+               capability->stats.histogramBucketCount);
+       printk(KERN_INFO "maxHistogramCount : %d\n",
+               capability->stats.maxHistogramCount);
+       printk(KERN_INFO "sharpnessMapSize : %dx%d\n",
+               capability->stats.sharpnessMapSize[0],
+               capability->stats.sharpnessMapSize[1]);
+       printk(KERN_INFO "maxSharpnessMapValue : %d\n",
+               capability->stats.maxSharpnessMapValue);
+
+       printk(KERN_INFO "===3A====================================\n");
+       printk(KERN_INFO "maxRegions : %d\n", capability->aa.maxRegions);
+
+       index = 0;
+       metadata = capability->aa.aeAvailableModes[index];
+       while (metadata) {
+               printk(KERN_INFO "aeAvailableModes : %d\n", metadata);
+               index++;
+               metadata = capability->aa.aeAvailableModes[index];
+       }
+       printk(KERN_INFO "aeCompensationStep : %d,%d\n",
+               capability->aa.aeCompensationStep.num,
+               capability->aa.aeCompensationStep.den);
+       printk(KERN_INFO "aeCompensationRange : %d ~ %d\n",
+               capability->aa.aeCompensationRange[0],
+               capability->aa.aeCompensationRange[1]);
+       index = 0;
+       metadata = capability->aa.aeAvailableTargetFpsRanges[index][0];
+       while (metadata) {
+               printk(KERN_INFO "TargetFpsRanges : %d ~ %d\n", metadata,
+                       capability->aa.aeAvailableTargetFpsRanges[index][1]);
+               index++;
+               metadata = capability->aa.aeAvailableTargetFpsRanges[index][0];
+       }
+       index = 0;
+       metadata = capability->aa.aeAvailableAntibandingModes[index];
+       while (metadata) {
+               printk(KERN_INFO "aeAvailableAntibandingModes : %d\n",
+                       metadata);
+               index++;
+               metadata = capability->aa.aeAvailableAntibandingModes[index];
+       }
+       index = 0;
+       metadata = capability->aa.awbAvailableModes[index];
+       while (metadata) {
+               printk(KERN_INFO "awbAvailableModes : %d\n", metadata);
+               index++;
+               metadata = capability->aa.awbAvailableModes[index];
+       }
+       index = 0;
+       metadata = capability->aa.afAvailableModes[index];
+       while (metadata) {
+               printk(KERN_INFO "afAvailableModes : %d\n", metadata);
+               index++;
+               metadata = capability->aa.afAvailableModes[index];
+       }
+#endif
+       return ret;
+}
+
+int fimc_is_itf_power_down(struct fimc_is_interface *interface)
+{
+       int ret = 0;
+#ifdef ENABLE_CLOCK_GATE
+       /* HACK */
+       struct fimc_is_core *core = (struct fimc_is_core *)interface->core;
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST) {
+               fimc_is_clk_gate_lock_set(core, 0, true);
+               fimc_is_wrap_clk_gate_set(core, (1 << GROUP_ID_MAX) - 1, true);
+       }
+#endif
+       ret = fimc_is_hw_power_down(interface, 0);
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+               sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+               fimc_is_clk_gate_lock_set(core, 0, false);
+#endif
+       return ret;
+}
+
+int fimc_is_itf_sys_ctl(struct fimc_is_device_ischain *this,
+                       int cmd, int val)
+{
+       int ret = 0;
+       struct fimc_is_interface *itf = this->interface;
+
+       ret = fimc_is_hw_sys_ctl(itf, this->instance,
+                               cmd, val);
+
+       return ret;
+}
+
+int fimc_is_itf_sensor_mode(struct fimc_is_device_ischain *ischain)
+{
+       struct fimc_is_device_sensor *sensor = ischain->sensor;
+
+       return fimc_is_hw_sensor_mode(ischain->interface,
+                       ischain->instance,
+                       ((sensor->mode << 16) | (ischain->module & 0xFFFF)));
+}
+
+static int fimc_is_itf_grp_shot(struct fimc_is_device_ischain *device,
+       struct fimc_is_group *group,
+       struct fimc_is_frame *frame)
+{
+       int ret = 0;
+       u32 group_id = 0;
+#ifdef ENABLE_CLOCK_GATE
+       struct fimc_is_core *core = (struct fimc_is_core *)device->interface->core;
+#endif
+       BUG_ON(!device);
+       BUG_ON(!group);
+       BUG_ON(!frame);
+       BUG_ON(!frame->shot);
+
+       /* Cache Flush */
+       fimc_is_ischain_meta_flush(frame);
+
+       if (frame->shot->magicNumber != SHOT_MAGIC_NUMBER) {
+               merr("shot magic number error(0x%08X)\n", device, frame->shot->magicNumber);
+               merr("shot_ext size : %d", device, sizeof(struct camera2_shot_ext));
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+#ifdef DBG_STREAMING
+       if (group->id == GROUP_ID_3A0)
+               info("[3A0:D:%d] GRP%d SHOT(%d)\n", device->instance, group->id, frame->fcount);
+       else if (group->id == GROUP_ID_3A1)
+               info("[3A1:D:%d] GRP%d SHOT(%d)\n", device->instance, group->id, frame->fcount);
+       else if (group->id == GROUP_ID_ISP)
+               info("[ISP:D:%d] GRP%d SHOT(%d)\n", device->instance, group->id, frame->fcount);
+       else if (group->id == GROUP_ID_DIS)
+               info("[DIS:D:%d] GRP%d SHOT(%d)\n", device->instance, group->id, frame->fcount);
+       else
+               info("[ERR:D:%d] GRP%d SHOT(%d)\n", device->instance, group->id, frame->fcount);
+#endif
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+       do_gettimeofday(&frame->time_shot);
+#endif
+#ifdef EXTERNAL_TIME
+       do_gettimeofday(&frame->tzone[TM_SHOT]);
+#endif
+#endif
+
+#ifdef ENABLE_CLOCK_GATE
+       /* HACK */
+       /* dynamic clock on */
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+               fimc_is_clk_gate_set(core, group->id, true, false, true);
+#endif
+       group_id = GROUP_ID(group->id);
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group_id & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group_id = GROUP_ID(GROUP_ID_3A0);
+
+       ret = fimc_is_hw_shot_nblk(device->interface,
+               device->instance,
+               group_id,
+               frame->dvaddr_buffer[0],
+               frame->dvaddr_shot,
+               frame->fcount,
+               frame->rcount);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_probe(struct fimc_is_device_ischain *device,
+       struct fimc_is_interface *interface,
+       struct fimc_is_resourcemgr *resourcemgr,
+       struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_mem *mem,
+       struct platform_device *pdev,
+       u32 instance,
+       u32 regs)
+{
+       int ret = 0;
+       struct fimc_is_subdev *scc, *dis, *scp;
+
+       BUG_ON(!interface);
+       BUG_ON(!mem);
+       BUG_ON(!pdev);
+       BUG_ON(!device);
+
+       /*device initialization should be just one time*/
+       scc = &device->scc;
+       dis = &device->dis;
+       scp = &device->scp;
+
+       device->interface       = interface;
+       device->mem             = mem;
+       device->pdev            = pdev;
+       device->pdata           = pdev->dev.platform_data;
+       device->regs            = (void *)regs;
+       device->instance        = instance;
+       device->groupmgr        = groupmgr;
+       device->resourcemgr     = resourcemgr;
+       device->sensor          = NULL;
+       device->margin_left     = 0;
+       device->margin_right    = 0;
+       device->margin_width    = 0;
+       device->margin_top      = 0;
+       device->margin_bottom   = 0;
+       device->margin_height   = 0;
+       device->dis_width       = 0;
+       device->dis_height      = 0;
+       device->chain0_width    = 0;
+       device->chain0_height   = 0;
+       device->chain1_width    = 0;
+       device->chain1_height   = 0;
+       device->chain2_width    = 0;
+       device->chain2_height   = 0;
+       device->chain3_width    = 0;
+       device->chain3_height   = 0;
+       device->crop_x          = 0;
+       device->crop_y          = 0;
+       device->crop_width      = 0;
+       device->crop_height     = 0;
+       device->setfile         = 0;
+       device->color_range     = 0;
+       device->dzoom_width     = 0;
+       device->force_down      = false;
+       device->is_region       = NULL;
+       device->taa_size_forceset = 0;
+       device->taa_size_changed_fcount = 0;
+       device->isp_size_forceset = 0;
+       device->isp_size_changed_fcount = 0;
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0))
+               fimc_is_group_probe(groupmgr, &device->group_3aa, ENTRY_3AA);
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, isp))
+               fimc_is_group_probe(groupmgr, &device->group_isp, ENTRY_ISP);
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, dis))
+               fimc_is_group_probe(groupmgr, &device->group_dis, ENTRY_DIS);
+
+       device->drc.entry = ENTRY_DRC;
+       device->scc.entry = ENTRY_SCALERC;
+       device->dis.entry = ENTRY_DIS;
+       device->dnr.entry = ENTRY_TDNR;
+       device->scp.entry = ENTRY_SCALERP;
+       device->fd.entry = ENTRY_LHFD;
+       device->taac.entry = ENTRY_3AAC;
+       device->taap.entry = ENTRY_3AAP;
+
+       clear_bit(FIMC_IS_ISCHAIN_OPEN, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_POWER_ON, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state);
+
+       /* clear group open state */
+       clear_bit(FIMC_IS_GROUP_OPEN, &device->group_3aa.state);
+       clear_bit(FIMC_IS_GROUP_OPEN, &device->group_isp.state);
+       clear_bit(FIMC_IS_GROUP_OPEN, &device->group_dis.state);
+
+       /* clear subdevice state */
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->group_3aa.leader.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->group_isp.leader.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->group_dis.leader.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->drc.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->scc.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->dis.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->dnr.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->scp.state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &device->fd.state);
+
+       clear_bit(FIMC_IS_SUBDEV_START, &device->group_3aa.leader.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->group_dis.leader.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->drc.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->scc.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->dis.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->dnr.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->scp.state);
+       clear_bit(FIMC_IS_SUBDEV_START, &device->fd.state);
+
+       mutex_init(&device->mutex_state);
+
+#ifdef FW_DEBUG
+       debugfs_root = debugfs_create_dir(DEBUG_FS_ROOT_NAME, NULL);
+       if (debugfs_root)
+               mdbgd_ischain("debugfs %s is created\n", device, DEBUG_FS_ROOT_NAME);
+
+       debugfs_file = debugfs_create_file(DEBUG_FS_FILE_NAME, S_IRUSR,
+               debugfs_root, device, &debug_fops);
+       if (debugfs_file)
+               mdbgd_ischain("debugfs %s is created\n", device, DEBUG_FS_FILE_NAME);
+#endif
+
+       return ret;
+}
+
+int fimc_is_ischain_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx,
+       struct fimc_is_minfo *minfo)
+{
+       int ret = 0;
+       struct fimc_is_ishcain_mem *imemory;
+#ifdef ENABLE_CLOCK_GATE
+       struct fimc_is_core *core;
+#endif
+       BUG_ON(!device);
+       BUG_ON(!device->groupmgr);
+       BUG_ON(!vctx);
+       BUG_ON(!minfo);
+
+       if (test_bit(FIMC_IS_ISCHAIN_OPEN, &device->state)) {
+               merr("already open", device);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+#ifndef RESERVED_MEM
+       if (device->instance == 0) {
+               /* 1. init memory */
+               ret = fimc_is_ishcain_initmem(device);
+               if (ret) {
+                       err("fimc_is_ishcain_initmem is fail(%d)\n", ret);
+                       goto p_err;
+               }
+       }
+#endif
+
+       clear_bit(FIMC_IS_ISCHAIN_LOADED, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_POWER_ON, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state);
+       clear_bit(FIMC_IS_ISHCAIN_START, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state);
+
+       /* 2. Init variables */
+       memset(&device->cur_peri_ctl, 0,
+               sizeof(struct camera2_uctl));
+       memset(&device->peri_ctls, 0,
+               sizeof(struct camera2_uctl)*SENSOR_MAX_CTL);
+       memset(&device->capability, 0,
+               sizeof(struct camera2_sm));
+
+       /* initial state, it's real apply to setting when opening*/
+       device->margin_left     = 0;
+       device->margin_right    = 0;
+       device->margin_width    = 0;
+       device->margin_top      = 0;
+       device->margin_bottom   = 0;
+       device->margin_height   = 0;
+       device->dis_width       = 0;
+       device->dis_height      = 0;
+       device->chain0_width    = 0;
+       device->chain0_height   = 0;
+       device->chain1_width    = 0;
+       device->chain1_height   = 0;
+       device->chain2_width    = 0;
+       device->chain2_height   = 0;
+       device->chain3_width    = 0;
+       device->chain3_height   = 0;
+       device->crop_x          = 0;
+       device->crop_y          = 0;
+       device->crop_width      = 0;
+       device->crop_height     = 0;
+       device->setfile         = ISS_SUB_SCENARIO_STILL_PREVIEW;
+       device->color_range     = 0;
+       device->color_range     |= (FIMC_IS_CRANGE_FULL << FIMC_IS_ISP_CRANGE_SHIFT);
+       device->color_range     |= (FIMC_IS_CRANGE_FULL << FIMC_IS_SCC_CRANGE_SHIFT);
+       device->color_range     |= (FIMC_IS_CRANGE_FULL << FIMC_IS_SCP_CRANGE_SHIFT);
+       device->dzoom_width     = 0;
+       device->force_down      = false;
+       device->sensor          = NULL;
+       device->module          = 0;
+
+       imemory                 = &device->imemory;
+       imemory->base           = minfo->base;
+       imemory->size           = minfo->size;
+       imemory->vaddr_base     = minfo->vaddr_base;
+       imemory->vaddr_curr     = minfo->vaddr_curr;
+       imemory->fw_cookie      = minfo->fw_cookie;
+       imemory->dvaddr         = minfo->dvaddr;
+       imemory->kvaddr         = minfo->kvaddr;
+       imemory->dvaddr_odc     = minfo->dvaddr_odc;
+       imemory->kvaddr_odc     = minfo->kvaddr_odc;
+       imemory->dvaddr_dis     = minfo->dvaddr_dis;
+       imemory->kvaddr_dis     = minfo->kvaddr_dis;
+       imemory->dvaddr_3dnr    = minfo->dvaddr_3dnr;
+       imemory->kvaddr_3dnr    = minfo->kvaddr_3dnr;
+       imemory->offset_region  = (FIMC_IS_A5_MEM_SIZE -
+               ((device->instance + 1) * FIMC_IS_REGION_SIZE));
+       imemory->dvaddr_region  = imemory->dvaddr + imemory->offset_region;
+       imemory->kvaddr_region  = imemory->kvaddr + imemory->offset_region;
+       imemory->is_region      = (struct is_region *)imemory->kvaddr_region;
+       imemory->offset_shared  = (u32)&imemory->is_region->shared[0] -
+               imemory->kvaddr;
+       imemory->dvaddr_shared  = imemory->dvaddr + imemory->offset_shared;
+       imemory->kvaddr_shared  = imemory->kvaddr + imemory->offset_shared;
+       device->is_region = imemory->is_region;
+
+       fimc_is_group_open(device->groupmgr, &device->group_isp, GROUP_ID_ISP,
+               device->instance, vctx, device, fimc_is_ischain_isp_callback);
+
+       /* subdev open */
+       fimc_is_subdev_open(&device->drc, NULL, &init_drc_param.control);
+       fimc_is_subdev_open(&device->dis, NULL, &init_dis_param.control);
+       fimc_is_subdev_open(&device->dnr, NULL, &init_tdnr_param.control);
+       /* FD see only control.command not bypass */
+       fimc_is_subdev_open(&device->fd, NULL, NULL);
+
+       /* for mediaserver force close */
+       ret = fimc_is_resource_get(device->resourcemgr, RESOURCE_TYPE_ISCHAIN);
+       if (ret) {
+               merr("fimc_is_resource_get is fail", device);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_ISCHAIN_OPEN, &device->state);
+
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST) {
+               core = (struct fimc_is_core *)device->interface->core;
+               fimc_is_clk_gate_lock_set(core, device->instance, true);
+               fimc_is_wrap_clk_gate_set(core, (1 << GROUP_ID_MAX) - 1, true);
+       }
+#endif
+p_err:
+       info("[ISC:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return ret;
+}
+
+int fimc_is_ischain_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       int refcount;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_queue *queue;
+       struct fimc_is_core *core;
+#ifdef CONFIG_COMPANION_USE
+       struct fimc_is_spi_gpio *spi_gpio;
+#endif
+       BUG_ON(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_isp;
+       leader = &group->leader;
+       queue = GET_SRC_QUEUE(vctx);
+       core = (struct fimc_is_core *)device->interface->core;
+       refcount = atomic_read(&vctx->video->refcount);
+#ifdef CONFIG_COMPANION_USE
+       spi_gpio = &core->spi_gpio;
+#endif
+       if (refcount < 0) {
+               merr("invalid ischain refcount", device);
+               ret = -ENODEV;
+               goto exit;
+       }
+
+       if (!test_bit(FIMC_IS_ISCHAIN_OPEN, &device->state)) {
+               merr("already close", device);
+               ret = -EMFILE;
+               goto exit;
+       }
+
+#ifdef ENABLE_CLOCK_GATE
+       core = (struct fimc_is_core *)device->interface->core;
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST) {
+               fimc_is_clk_gate_lock_set(core, device->instance, true);
+               fimc_is_wrap_clk_gate_set(core, (1 << GROUP_ID_MAX) - 1, true);
+       }
+#endif
+       /* 1. Stop all request */
+       ret = fimc_is_ischain_isp_stop(device, leader, queue);
+       if (ret)
+               merr("fimc_is_ischain_isp_stop is fail", device);
+
+       /* group close */
+       ret = fimc_is_group_close(groupmgr, group);
+       if (ret)
+               merr("fimc_is_group_close is fail", device);
+
+       /* subdev close */
+       fimc_is_subdev_close(&device->drc);
+       fimc_is_subdev_close(&device->dis);
+       fimc_is_subdev_close(&device->dnr);
+       fimc_is_subdev_close(&device->fd);
+
+       /* CLOSE_SENSOR */
+       if (test_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state)) {
+               ret = fimc_is_itf_close(device);
+               if (ret)
+                       merr("fimc_is_itf_close is fail", device);
+
+               if(device->sensor->pdata->is_softlanding)
+                       fimc_is_sensor_gpio_off_softlanding(device->sensor);
+       }
+
+       /* for mediaserver force close */
+       ret = fimc_is_resource_put(device->resourcemgr, RESOURCE_TYPE_ISCHAIN);
+       if (ret) {
+               merr("fimc_is_resource_put is fail", device);
+               goto exit;
+       }
+
+       clear_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state);
+       clear_bit(FIMC_IS_ISCHAIN_OPEN, &device->state);
+#ifdef CONFIG_COMPANION_USE
+       fimc_is_set_spi_config(spi_gpio, FIMC_IS_SPI_OUTPUT, true);
+#endif
+
+#ifdef ENABLE_CLOCK_GATE
+       if (sysfs_debug.en_clk_gate &&
+                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+               fimc_is_clk_gate_lock_set(core, device->instance, false);
+#endif
+exit:
+       pr_info("[ISC:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return ret;
+}
+
+static int fimc_is_ischain_init(struct fimc_is_device_ischain *device,
+       u32 module_id,
+       u32 group_id,
+       u32 video_id,
+       u32 flag)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *sensor;
+#ifdef CONFIG_COMPANION_USE
+       struct fimc_is_core *core
+               = (struct fimc_is_core *)platform_get_drvdata(device->pdev);
+       /* Workaround for Host to use ISP-SPI. Will be removed later.*/
+//     struct fimc_is_spi_gpio *spi_gpio = &core->spi_gpio;
+#endif
+
+       BUG_ON(!device);
+       BUG_ON(!device->sensor);
+
+       mdbgd_ischain("%s(module : %d)\n", device, __func__, module_id);
+
+       sensor = device->sensor;
+
+       if (test_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state)) {
+               mwarn("sensor is already open", device);
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_SENSOR_OPEN, &sensor->state)) {
+               merr("I2C gpio is not yet set", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_g_module(sensor, &module);
+       if (ret) {
+               merr("fimc_is_sensor_g_module is fail(%d)", device, ret);
+               goto p_err;
+       }
+       if (module->id != module_id) {
+               merr("module id is invalid(%d != %d)", device, module->id, module_id);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               /* sensor instance means flite channel */
+               if(sensor->instance == 0) {
+                       /* Load calibration data from sensor */
+                       module->ext.sensor_con.cal_address = FIMC_IS_CAL_START_ADDR;
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+                       ret = fimc_is_ischain_loadcalb_eeprom(device, NULL, SENSOR_POSITION_REAR);
+#else
+                       ret = fimc_is_ischain_loadcalb(device, NULL);
+#endif
+                       if (ret) {
+                               err("loadcalb fail, load default caldata\n");
+                       }
+               } else {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+                       module->ext.sensor_con.cal_address = FIMC_IS_CAL_START_ADDR_FRONT;
+                       ret = fimc_is_ischain_loadcalb_eeprom(device, NULL, SENSOR_POSITION_FRONT);
+                       if (ret) {
+                               err("loadcalb fail, load default caldata\n");
+                       }
+#else
+                       module->ext.sensor_con.cal_address = 0;
+#endif
+               }
+       }
+
+#ifdef CONFIG_COMPANION_USE
+       if(core->companion->companion_status != FIMC_IS_COMPANION_IDLE) {
+               pr_info("[ISC:D:%d] fimc_is_companion_wait wait(%d)\n", device->instance,core->companion->companion_status);
+               fimc_is_companion_wait(core->companion);
+               pr_info("[ISC:D:%d] fimc_is_companion_wait wake up(%d)\n", device->instance,core->companion->companion_status);
+       }
+
+       fimc_is_s_int_comb_isp(core, false, INTMR2_INTMCIS22);
+
+#if 0
+       /* FW loading of peripheral device */
+       if ((module->position == SENSOR_POSITION_REAR)
+               && !test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               // Workaround for Host to use ISP-SPI. Will be removed later.
+               /* set pin output for Host to use SPI*/
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+                                       PINCFG_PACK(PINCFG_TYPE_FUNC, FUNC_OUTPUT));
+
+               fimc_is_set_spi_config(spi_gpio, FIMC_IS_SPI_FUNC, false);
+
+               if (fimc_is_comp_is_valid(core) == 0) {
+                       fimc_is_power_binning(core);
+                       ret = fimc_is_comp_loadfirm(core);
+                       if (ret) {
+                               err("fimc_is_comp_loadfirm() fail");
+                               goto p_err;
+                       }
+                       ret = fimc_is_comp_loadcal(core);
+                       if (ret) {
+                               err("fimc_is_comp_loadcal() fail");
+                       }
+                       ret = fimc_is_comp_loadsetf(core);
+                       if (ret) {
+                               err("fimc_is_comp_loadsetf() fail");
+                               goto p_err;
+                       }
+               } else {
+                       module->ext.companion_con.product_name
+                               = COMPANION_NAME_NOTHING;
+               }
+               // Workaround for Host to use ISP-SPI. Will be removed later.
+               /* Set SPI pins to low before changing pin function */
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_sclk,
+                                       PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+                                       PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_miso,
+                                       PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_mois,
+                                       PINCFG_PACK(PINCFG_TYPE_DAT, 0));
+
+               /* Set pin function for A5 to use SPI */
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+                                       PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+       }
+#endif
+#endif
+
+       ret = fimc_is_itf_enum(device);
+       if (ret) {
+               err("enum fail");
+               goto p_err;
+       }
+
+#if (FW_HAS_SENSOR_MODE_CMD)
+       ret = fimc_is_itf_open(device, ((sensor->mode << 16) | (module_id & 0xFFFF)),
+                       group_id, flag, &module->ext);
+#else
+       ret = fimc_is_itf_open(device, module_id, group_id, flag, &module->ext);
+#endif
+       if (ret) {
+               merr("open fail", device);
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_setfile(device, module->setfile_name);
+       if (ret) {
+               merr("setfile fail", device);
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               ret = fimc_is_itf_stream_off(device);
+               if (ret) {
+                       merr("streamoff fail", device);
+                       goto p_err;
+               }
+       }
+
+       ret = fimc_is_itf_init_process_stop(device);
+       if (ret) {
+               merr("fimc_is_itf_init_process_stop is fail", device);
+               goto p_err;
+       }
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               measure_period(&device->group_3aa.time, 1);
+               measure_period(&device->group_isp.time, 1);
+               measure_period(&device->group_dis.time, 1);
+       } else {
+               measure_period(&device->group_3aa.time, 66);
+               measure_period(&device->group_isp.time, 66);
+               measure_period(&device->group_dis.time, 66);
+       }
+#endif
+#endif
+
+       device->module = module_id;
+       set_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_init_wrap(struct fimc_is_device_ischain *device,
+       u32 input)
+{
+       int ret = 0;
+       u32 flag = 0;
+       u32 group_id = 0;
+       u32 module, ssx_vindex, tax_vindex, rep_stream;
+       struct fimc_is_core *core = NULL;
+       struct fimc_is_device_sensor *sensor = NULL;
+
+       BUG_ON(!device);
+
+       mdbgd_ischain("%s(input : %08X)\n", device, __func__, input);
+
+       core = (struct fimc_is_core *)platform_get_drvdata(device->pdev);
+
+       module = input & MODULE_MASK;
+       ssx_vindex = (input & SSX_VINDEX_MASK) >> SSX_VINDEX_SHIFT;
+       tax_vindex = (input & TAX_VINDEX_MASK) >> TAX_VINDEX_SHIFT;
+       rep_stream = (input & REPROCESSING_MASK) >> REPROCESSING_SHIFT;
+
+       /* 1. checking 3ax group to connect */
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)
+                       || GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1))
+               group_id = device->group_3aa.id;
+       else
+               group_id = GROUP_ID_3A0;
+
+       /* 2. checking sensor video node to connect */
+       if (ssx_vindex == FIMC_IS_VIDEO_SS0_NUM) {
+               sensor = &core->sensor[0];
+               info("[ISP:V:%d] <-> [SS0:V:0]\n", device->instance);
+       } else if (ssx_vindex == FIMC_IS_VIDEO_SS1_NUM) {
+               sensor = &core->sensor[1];
+               info("[ISP:V:%d] <-> [SS1:V:0]\n", device->instance);
+       } else {
+               sensor = NULL;
+               merr("sensor is not matched", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* 3. checking reprocessing stream */
+       if (rep_stream) {
+               flag = REPROCESSING_FLAG;
+               set_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state);
+       } else {
+               /* connect to sensor if it's not a reprocessing stream */
+               sensor->ischain = device;
+               flag = 0;
+       }
+
+       /* 4. init variable */
+       device->instance_sensor = sensor->instance;
+       device->sensor = sensor;
+
+       info("%s(%s) : module(%d), flag(%08X), group_id(%d)\n", __func__,
+                       (rep_stream ? "Reprocessing" : "Preview"), module, flag, group_id);
+
+       /* 5. init ischain */
+       ret = fimc_is_ischain_init(device, module, group_id, tax_vindex, flag);
+       if (ret)
+               merr("fimc_is_device_init(%d, %d, %d) is fail", device, module, group_id, rep_stream);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_s_color_range(struct fimc_is_device_ischain *device,
+       u32 color_range, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       int ret = 0;
+       u32 crange;
+       struct param_otf_output *otf_output;
+       struct param_scaler_imageeffect *scaler_effect;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       /*
+        * Color Range
+        * 0 : Wide range
+        * 1 : Narrow range
+        */
+       otf_output = fimc_is_itf_g_param(device, NULL, PARAM_ISP_OTF_OUTPUT);
+       crange = (color_range & FIMC_IS_ISP_CRANGE_MASK) >> FIMC_IS_ISP_CRANGE_SHIFT;
+       if (crange)
+               otf_output->format = OTF_OUTPUT_FORMAT_YUV444_TRUNCATED;
+       else
+               otf_output->format = OTF_OUTPUT_FORMAT_YUV444;
+       *lindex |= LOWBIT_OF(PARAM_ISP_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_ISP_OTF_OUTPUT);
+
+       info("[ISC:D:%d] ISP color range: %s\n", device->instance,
+                       (crange ? "limited" : "full"));
+
+       scaler_effect = fimc_is_itf_g_param(device, NULL, PARAM_SCALERC_IMAGE_EFFECT);
+       crange = (color_range & FIMC_IS_SCC_CRANGE_MASK) >> FIMC_IS_SCC_CRANGE_SHIFT;
+       if (crange)
+               scaler_effect->yuv_range = SCALER_OUTPUT_YUV_RANGE_NARROW;
+       else
+               scaler_effect->yuv_range = SCALER_OUTPUT_YUV_RANGE_FULL;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_IMAGE_EFFECT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_IMAGE_EFFECT);
+       (*indexes)++;
+
+       info("[ISC:D:%d] SCC color range: %s\n", device->instance,
+                       (crange ? "limited" : "full"));
+
+       scaler_effect = fimc_is_itf_g_param(device, NULL, PARAM_SCALERP_IMAGE_EFFECT);
+       crange = (color_range & FIMC_IS_SCP_CRANGE_MASK) >> FIMC_IS_SCP_CRANGE_SHIFT;
+       if (crange)
+               scaler_effect->yuv_range = SCALER_OUTPUT_YUV_RANGE_NARROW;
+       else
+               scaler_effect->yuv_range = SCALER_OUTPUT_YUV_RANGE_FULL;
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_IMAGE_EFFECT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_IMAGE_EFFECT);
+       (*indexes)++;
+
+       info("[ISC:D:%d] SCP color range: %s\n", device->instance,
+                       (crange ? "limited" : "full"));
+
+       return ret;
+}
+
+static int fimc_is_ischain_s_sensor(struct fimc_is_device_ischain *device,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct sensor_param *sensor_param;
+       size_t sensor_width, sensor_height;
+       u32 framerate;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+       BUG_ON(!device->sensor);
+
+       sensor_param = &device->is_region->parameter.sensor;
+       sensor_width = fimc_is_sensor_g_width(device->sensor);
+       sensor_height = fimc_is_sensor_g_height(device->sensor);
+       framerate = fimc_is_sensor_g_framerate(device->sensor);
+
+#ifdef FIXED_FPS_DEBUG
+       sensor_param->config.framerate = FIXED_FPS_VALUE;
+#else
+       sensor_param->config.framerate = framerate;
+#endif
+       if (device->sensor->min_target_fps > 0)
+               sensor_param->config.min_target_fps = device->sensor->min_target_fps;
+       if (device->sensor->max_target_fps > 0)
+               sensor_param->config.max_target_fps = device->sensor->max_target_fps;
+       if (device->sensor->scene_mode >= AA_SCENE_MODE_UNSUPPORTED)
+               sensor_param->config.scene_mode = device->sensor->scene_mode;
+
+       *lindex |= LOWBIT_OF(PARAM_SENSOR_CONFIG);
+       *hindex |= HIGHBIT_OF(PARAM_SENSOR_CONFIG);
+       (*indexes)++;
+
+       sensor_param->dma_output.width = sensor_width;
+       sensor_param->dma_output.height = sensor_height;
+
+       *lindex |= LOWBIT_OF(PARAM_SENSOR_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SENSOR_DMA_OUTPUT);
+       (*indexes)++;
+
+       return ret;
+}
+
+static int fimc_is_ischain_s_3aa_size(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       u32 *input_crop,
+       u32 *output_crop,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct fimc_is_group *group_3aa;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_queue *queue;
+       struct param_control *taa_control;
+       struct param_otf_input *taa_otf_input;
+       struct param_dma_input *taa_dma_input;
+       size_t sensor_width, sensor_height;
+       size_t bns_width, bns_height;
+       size_t total_width, total_height;
+       u32 binning;
+       u32 bns_binning;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+       BUG_ON(!device->sensor);
+
+       sensor_width = fimc_is_sensor_g_width(device->sensor);
+       sensor_height = fimc_is_sensor_g_height(device->sensor);
+       bns_width = fimc_is_sensor_g_bns_width(device->sensor);
+       bns_height = fimc_is_sensor_g_bns_height(device->sensor);
+       binning = fimc_is_sensor_g_bratio(device->sensor);
+       bns_binning = fimc_is_sensor_g_bns_ratio(device->sensor);
+       total_width = 2 * input_crop[0] + input_crop[2];
+       total_height = 2 * input_crop[1] + input_crop[3];
+
+       /* check crop size */
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &device->group_3aa.state)) {
+               if (bns_width <= total_width) {
+                       merr("crop width(%d) is bigger than input width(%d)\n",
+                               device, total_width, bns_width);
+                       goto p_err;
+               }
+
+               if (bns_height <= total_height) {
+                       merr("crop height(%d) is bigger than input height(%d)\n",
+                               device, total_height, bns_height);
+                       goto p_err;
+               }
+
+               taa_otf_input = fimc_is_itf_g_param(device, frame, PARAM_3AA_OTF_INPUT);
+               taa_otf_input->cmd = OTF_INPUT_COMMAND_ENABLE;
+
+               taa_dma_input = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA1_INPUT);
+               taa_dma_input->cmd = DMA_INPUT_COMMAND_DISABLE;
+       } else {
+               if (sensor_width <= total_width) {
+                       merr("crop width(%d) is bigger than input width(%d)\n",
+                               device, total_width, sensor_width);
+                       goto p_err;
+               }
+
+               if (sensor_height <= total_height) {
+                       merr("crop height(%d) is bigger than input height(%d)\n",
+                               device, total_height, sensor_height);
+                       goto p_err;
+               }
+
+               taa_otf_input = fimc_is_itf_g_param(device, frame, PARAM_3AA_OTF_INPUT);
+               taa_otf_input->cmd = OTF_INPUT_COMMAND_DISABLE;
+
+               taa_dma_input = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA1_INPUT);
+               taa_dma_input->cmd = DMA_INPUT_COMMAND_BUF_MNGR;
+       }
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0))
+               group_3aa = &device->group_3aa;
+       else
+               group_3aa = &device->group_isp;
+       leader = &group_3aa->leader;
+       queue = GET_LEADER_QUEUE(leader);
+       if (!queue) {
+               merr("get queue fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       taa_control = fimc_is_itf_g_param(device, frame, PARAM_3AA_CONTROL);
+       taa_control->cmd = CONTROL_COMMAND_START;
+       taa_control->bypass = CONTROL_BYPASS_DISABLE;
+       taa_control->run_mode = 1;
+       *lindex |= LOWBIT_OF(PARAM_3AA_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_CONTROL);
+       (*indexes)++;
+
+       /* OTF */
+       taa_otf_input->width = sensor_width;
+       taa_otf_input->height = sensor_height;
+       taa_otf_input->bayer_crop_enable = 1;
+       taa_otf_input->bayer_crop_offset_x = input_crop[0];
+       taa_otf_input->bayer_crop_offset_y = input_crop[1];
+       taa_otf_input->bayer_crop_width = input_crop[2];
+       taa_otf_input->bayer_crop_height = input_crop[3];
+       taa_otf_input->sensor_binning_ratio_x = binning;
+       taa_otf_input->sensor_binning_ratio_y = binning;
+
+       taa_otf_input->bns_binning_enable = 1;
+       taa_otf_input->bns_binning_ratio_x = bns_binning;
+       taa_otf_input->bns_binning_ratio_y = bns_binning;
+       taa_otf_input->bns_margin_left = 0;
+       taa_otf_input->bns_margin_top = 0;
+       taa_otf_input->bns_output_width = bns_width;
+       taa_otf_input->bns_output_height = bns_height;
+
+       taa_otf_input->format = OTF_INPUT_FORMAT_BAYER;
+       taa_otf_input->bitwidth = OTF_INPUT_BIT_WIDTH_10BIT;
+       taa_otf_input->order = OTF_INPUT_ORDER_BAYER_GR_BG;
+       taa_otf_input->frametime_min = 0;
+       taa_otf_input->frametime_max = 1000000;
+       *lindex |= LOWBIT_OF(PARAM_3AA_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_OTF_INPUT);
+       (*indexes)++;
+
+       /* M2M */
+       taa_dma_input->width = sensor_width;
+       taa_dma_input->height = sensor_height;
+       taa_dma_input->bayer_crop_enable = 1;
+       taa_dma_input->bayer_crop_offset_x = input_crop[0];
+       taa_dma_input->bayer_crop_offset_y = input_crop[1];
+       taa_dma_input->bayer_crop_width = input_crop[2];
+       taa_dma_input->bayer_crop_height = input_crop[3];
+
+       if (!GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)) {
+               taa_dma_input->bds_out_enable = ISP_BDS_COMMAND_ENABLE;
+               taa_dma_input->bds_out_width = output_crop[2];
+               taa_dma_input->bds_out_height = output_crop[3];
+       }
+
+       taa_dma_input->user_min_frame_time = 0;
+       taa_dma_input->user_max_frame_time = 1000000;
+
+       if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR10 ||
+                       queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR12) {
+               taa_dma_input->format = DMA_INPUT_FORMAT_BAYER_PACKED12;
+       } else if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR16) {
+               taa_dma_input->format = DMA_INPUT_FORMAT_BAYER;
+       } else {
+               merr("Invalid bayer format(%d)", device, queue->framecfg.format.pixelformat);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       taa_dma_input->bitwidth = DMA_INPUT_BIT_WIDTH_10BIT;
+       taa_dma_input->order = DMA_INPUT_ORDER_GR_BG;
+       taa_dma_input->plane = 1;
+       taa_dma_input->buffer_number = 0;
+       taa_dma_input->buffer_address = 0;
+       taa_dma_input->sensor_binning_ratio_x = binning;
+       taa_dma_input->sensor_binning_ratio_y = binning;
+       /*
+        * hidden spec
+        *     [0] : sensor size is dma input size
+        *     [X] : sensor size is reserved field
+        */
+       taa_dma_input->reserved[1] = 0;
+       taa_dma_input->reserved[2] = 0;
+       *lindex |= LOWBIT_OF(PARAM_3AA_VDMA1_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_VDMA1_INPUT);
+       (*indexes)++;
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_s_chain0_size(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       u32 width,
+       u32 height,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct fimc_is_group *group_isp;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_queue *queue;
+       struct param_otf_input *otf_input;
+       struct param_dma_input *dma_input;
+       struct param_otf_output *otf_output;
+       struct param_scaler_input_crop *input_crop;
+       u32 chain0_width, chain0_height;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       chain0_width = width;
+       chain0_height = height;
+
+       group_isp = &device->group_isp;
+       if (!group_isp) {
+               merr("get gourp_isp fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       leader = &group_isp->leader;
+       if (!leader) {
+               merr("get leader fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       queue = GET_LEADER_QUEUE(leader);
+       if (!queue) {
+               merr("get queue fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       mdbgd_ischain("request chain0 size : %dx%d\n", device, chain0_width, chain0_height);
+
+       /* ISP */
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)) {
+               dma_input = fimc_is_itf_g_param(device, frame, PARAM_ISP_VDMA1_INPUT);
+               dma_input->cmd = DMA_INPUT_COMMAND_BUF_MNGR;
+               dma_input->width = chain0_width;
+               dma_input->height = chain0_height;
+               dma_input->bitwidth = DMA_INPUT_BIT_WIDTH_10BIT;
+
+               if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR10 ||
+                       queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR12) {
+                       dma_input->format = DMA_INPUT_FORMAT_BAYER_PACKED12;
+               } else if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR16) {
+                       dma_input->format = DMA_INPUT_FORMAT_BAYER;
+               } else {
+                       merr("Invalid bayer format(%d)", device, queue->framecfg.format.pixelformat);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               *lindex |= LOWBIT_OF(PARAM_ISP_VDMA1_INPUT);
+               *hindex |= HIGHBIT_OF(PARAM_ISP_VDMA1_INPUT);
+               (*indexes)++;
+       }
+
+       otf_output = fimc_is_itf_g_param(device, frame, PARAM_ISP_OTF_OUTPUT);
+       otf_output->cmd = OTF_OUTPUT_COMMAND_ENABLE;
+       otf_output->width = chain0_width;
+       otf_output->height = chain0_height;
+       otf_output->format = OTF_OUTPUT_FORMAT_YUV444;
+       otf_output->bitwidth = OTF_OUTPUT_BIT_WIDTH_12BIT;
+       otf_output->order = OTF_INPUT_ORDER_BAYER_GR_BG;
+       *lindex |= LOWBIT_OF(PARAM_ISP_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_ISP_OTF_OUTPUT);
+       (*indexes)++;
+
+       /* DRC */
+       otf_input = fimc_is_itf_g_param(device, frame, PARAM_DRC_OTF_INPUT);
+       otf_input->cmd = OTF_INPUT_COMMAND_ENABLE;
+       otf_input->width = chain0_width;
+       otf_input->height = chain0_height;
+       *lindex |= LOWBIT_OF(PARAM_DRC_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_DRC_OTF_INPUT);
+       (*indexes)++;
+
+       otf_output = fimc_is_itf_g_param(device, frame, PARAM_DRC_OTF_OUTPUT);
+       otf_output->cmd = OTF_OUTPUT_COMMAND_ENABLE;
+       otf_output->width = chain0_width;
+       otf_output->height = chain0_height;
+       *lindex |= LOWBIT_OF(PARAM_DRC_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_DRC_OTF_OUTPUT);
+       (*indexes)++;
+
+       /* SCC */
+       otf_input = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OTF_INPUT);
+       otf_input->cmd = OTF_INPUT_COMMAND_ENABLE;
+       otf_input->width = chain0_width;
+       otf_input->height = chain0_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_OTF_INPUT);
+       (*indexes)++;
+
+       /* SCC CROP */
+       input_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_INPUT_CROP);
+       input_crop->pos_x = 0;
+       input_crop->pos_y = 0;
+       input_crop->crop_width = chain0_width;
+       input_crop->crop_height = chain0_height;
+       input_crop->in_width = chain0_width;
+       input_crop->in_height = chain0_height;
+
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       (*indexes)++;
+
+       device->bds_width = width;
+       device->bds_height = height;
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_s_chain1_size(struct fimc_is_device_ischain *device,
+       u32 width, u32 height, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       int ret = 0;
+       struct scalerc_param *scc_param;
+       struct odc_param *odc_param;
+       struct dis_param *dis_param;
+       u32 chain1_width, chain1_height;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
+               return 0;
+
+       scc_param = &device->is_region->parameter.scalerc;
+       odc_param = &device->is_region->parameter.odc;
+       dis_param = &device->is_region->parameter.dis;
+       chain1_width = width;
+       chain1_height = height;
+
+       mdbgd_ischain("current chain1 size : %dx%d\n", device,
+               device->chain1_width, device->chain1_height);
+       mdbgd_ischain("request chain1 size : %dx%d\n", device,
+               chain1_width, chain1_height);
+
+       if (!chain1_width) {
+               err("chain1 width is zero");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       if (!chain1_height) {
+               err("chain1 height is zero");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       /* SCC OUTPUT */
+       scc_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
+       scc_param->input_crop.out_width = chain1_width;
+       scc_param->input_crop.out_height = chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       (*indexes)++;
+
+       scc_param->output_crop.cmd = SCALER_CROP_COMMAND_DISABLE;
+       scc_param->output_crop.pos_x = 0;
+       scc_param->output_crop.pos_y = 0;
+       scc_param->output_crop.crop_width = chain1_width;
+       scc_param->output_crop.crop_height = chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+       (*indexes)++;
+
+       scc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
+       scc_param->otf_output.width = chain1_width;
+       scc_param->otf_output.height = chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+       (*indexes)++;
+
+       /* ODC */
+       odc_param->otf_input.width = chain1_width;
+       odc_param->otf_input.height = chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_ODC_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_ODC_OTF_INPUT);
+       (*indexes)++;
+
+       odc_param->otf_output.width = chain1_width;
+       odc_param->otf_output.height = chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_ODC_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_ODC_OTF_OUTPUT);
+       (*indexes)++;
+
+       /* DIS INPUT */
+       dis_param->otf_input.width = chain1_width;
+       dis_param->otf_input.height = chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_DIS_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_DIS_OTF_INPUT);
+       (*indexes)++;
+
+exit:
+       return ret;
+}
+
+static int fimc_is_ischain_s_chain2_size(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       u32 width,
+       u32 height,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_otf_input *otf_input;
+       struct param_otf_output *otf_output;
+       struct param_dma_output *dma_output;
+       u32 chain2_width, chain2_height;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
+               return 0;
+
+       mdbgd_ischain("request chain2 size : %dx%d\n", device, width, height);
+       mdbgd_ischain("current chain2 size : %dx%d\n",
+               device, device->chain2_width, device->chain2_height);
+
+       /* CALCULATION */
+       chain2_width = width;
+       chain2_height = height;
+
+       /* DIS OUTPUT */
+       otf_output = fimc_is_itf_g_param(device, frame, PARAM_DIS_OTF_OUTPUT);
+       otf_output->width = chain2_width;
+       otf_output->height = chain2_height;
+       *lindex |= LOWBIT_OF(PARAM_DIS_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_DIS_OTF_OUTPUT);
+       (*indexes)++;
+
+       otf_input = fimc_is_itf_g_param(device, frame, PARAM_TDNR_OTF_INPUT);
+       otf_input->width = chain2_width;
+       otf_input->height = chain2_height;
+       *lindex |= LOWBIT_OF(PARAM_TDNR_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_TDNR_OTF_INPUT);
+       (*indexes)++;
+
+       dma_output = fimc_is_itf_g_param(device, frame, PARAM_TDNR_DMA_OUTPUT);
+       dma_output->width = chain2_width;
+       dma_output->height = chain2_height;
+       *lindex |= LOWBIT_OF(PARAM_TDNR_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_TDNR_DMA_OUTPUT);
+       (*indexes)++;
+
+       otf_output = fimc_is_itf_g_param(device, frame, PARAM_TDNR_OTF_OUTPUT);
+       otf_output->width = chain2_width;
+       otf_output->height = chain2_height;
+       *lindex |= LOWBIT_OF(PARAM_TDNR_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_TDNR_OTF_OUTPUT);
+       (*indexes)++;
+
+       otf_input = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_OTF_INPUT);
+       otf_input->width = chain2_width;
+       otf_input->height = chain2_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_OTF_INPUT);
+       (*indexes)++;
+
+       return ret;
+}
+
+/**
+ Utility function to adjust output crop size based on the
+ H/W limitation of SCP scaling.
+ output_crop_w and output_crop_h are call-by reference parameter,
+ which contain intended cropping size. Adjusted size will be stored on
+ those parameters when this function returns.
+ */
+static int fimc_is_ischain_scp_adjust_crop(struct fimc_is_device_ischain *device,
+       struct scalerp_param *scp_param,
+       u32 *output_crop_w, u32 *output_crop_h)
+{
+       int changed = 0;
+
+       if (*output_crop_w > scp_param->otf_input.width * 4) {
+               mwarn("Cannot be scaled up beyond 4 times(%d -> %d)",
+                       device, scp_param->otf_input.width, *output_crop_w);
+               *output_crop_w = scp_param->otf_input.width * 4;
+               changed |= 0x01;
+       }
+
+       if (*output_crop_h > scp_param->otf_input.height * 4) {
+               mwarn("Cannot be scaled up beyond 4 times(%d -> %d)",
+                       device, scp_param->otf_input.height, *output_crop_h);
+               *output_crop_h = scp_param->otf_input.height * 4;
+               changed |= 0x02;
+       }
+
+       if (*output_crop_w < (scp_param->otf_input.width + 15) / 16) {
+               mwarn("Cannot be scaled down beyond 1/16 times(%d -> %d)",
+                       device, scp_param->otf_input.width, *output_crop_w);
+               *output_crop_w = (scp_param->otf_input.width + 15) / 16;
+               changed |= 0x10;
+       }
+
+       if (*output_crop_h < (scp_param->otf_input.height + 15) / 16) {
+               mwarn("Cannot be scaled down beyond 1/16 times(%d -> %d)",
+                       device, scp_param->otf_input.height, *output_crop_h);
+               *output_crop_h = (scp_param->otf_input.height + 15) / 16;
+               changed |= 0x20;
+       }
+
+       return changed;
+}
+
+static int fimc_is_ischain_s_chain3_size(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       u32 width,
+       u32 height,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_scaler_input_crop *input_crop;
+       struct param_scaler_output_crop *output_crop;
+       struct param_otf_input *otf_input;
+       struct param_otf_output *otf_output;
+       struct param_dma_output *dma_output;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_queue *queue;
+       struct scalerp_param *scp_param;
+       u32 chain2_width, chain2_height;
+       u32 chain3_width, chain3_height;
+       u32 scp_crop_width, scp_crop_height;
+       u32 scp_crop_x, scp_crop_y;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
+               return 0;
+
+       /* Adjust output crop to prevent exceeding SCP limitation */
+       scp_param = &device->is_region->parameter.scalerp;
+       fimc_is_ischain_scp_adjust_crop(device, scp_param, &width, &height);
+
+       vctx = device->scp.vctx;
+       queue = vctx->q_dst;
+
+       chain2_width = device->chain2_width;
+       chain2_height = device->chain2_height;
+       chain3_width = width;
+       chain3_height = height;
+
+       scp_crop_x = 0;
+       scp_crop_y = 0;
+       scp_crop_width = chain2_width;
+       scp_crop_height = chain2_height;
+
+       mdbgd_ischain("request chain3 size : %dx%d\n", device, width, height);
+       mdbgd_ischain("current chain3 size : %dx%d\n",
+               device, device->chain3_width, device->chain3_height);
+
+       /* SCP */
+       input_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_INPUT_CROP);
+       input_crop->cmd = SCALER_CROP_COMMAND_ENABLE;
+       input_crop->pos_x = scp_crop_x;
+       input_crop->pos_y = scp_crop_y;
+       input_crop->crop_width = scp_crop_width;
+       input_crop->crop_height = scp_crop_height;
+       input_crop->in_width = chain2_width;
+       input_crop->in_height = chain2_height;
+       input_crop->out_width = chain3_width;
+       input_crop->out_height = chain3_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_INPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_INPUT_CROP);
+       (*indexes)++;
+
+       /*
+        * scaler can't apply stride to each plane, only y plane.
+        * basically cb, cr plane should be half of y plane,
+        * and it's automatically set
+        *
+        * 3 plane : all plane should be 8 or 16 stride
+        * 2 plane : y plane should be 32, 16 stride, others should be half stride of y
+        * 1 plane : all plane should be 8 stride
+        */
+       /*
+        * limitation of output_crop.pos_x and pos_y
+        * YUV422 3P, YUV420 3P : pos_x and pos_y should be x2
+        * YUV422 1P : pos_x should be x2
+        */
+       output_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_OUTPUT_CROP);
+       if (queue->framecfg.width_stride[0]) {
+               output_crop->cmd = SCALER_CROP_COMMAND_ENABLE;
+               output_crop->pos_x = 0;
+               output_crop->pos_y = 0;
+               output_crop->crop_width = chain3_width + queue->framecfg.width_stride[0];
+               output_crop->crop_height = chain3_height;
+               *lindex |= LOWBIT_OF(PARAM_SCALERP_OUTPUT_CROP);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERP_OUTPUT_CROP);
+               (*indexes)++;
+       } else {
+               output_crop->cmd = SCALER_CROP_COMMAND_DISABLE;
+               *lindex |= LOWBIT_OF(PARAM_SCALERP_OUTPUT_CROP);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERP_OUTPUT_CROP);
+               (*indexes)++;
+       }
+
+       otf_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_OTF_OUTPUT);
+       otf_output->width = chain3_width;
+       otf_output->height = chain3_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_OTF_OUTPUT);
+       (*indexes)++;
+
+       dma_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_DMA_OUTPUT);
+       dma_output->width = chain3_width;
+       dma_output->height = chain3_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_DMA_OUTPUT);
+       (*indexes)++;
+
+       /* FD */
+       otf_input = fimc_is_itf_g_param(device, frame, PARAM_FD_OTF_INPUT);
+       otf_input->width = chain3_width;
+       otf_input->height = chain3_height;
+       *lindex |= LOWBIT_OF(PARAM_FD_OTF_INPUT);
+       *hindex |= HIGHBIT_OF(PARAM_FD_OTF_INPUT);
+       (*indexes)++;
+
+       return ret;
+}
+
+static int fimc_is_ischain_s_path(struct fimc_is_device_ischain *device,
+       u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       int ret = 0;
+       struct isp_param *isp_param;
+       struct drc_param *drc_param;
+       struct scalerc_param *scc_param;
+       struct odc_param *odc_param;
+       struct dis_param *dis_param;
+       struct tdnr_param *dnr_param;
+       struct scalerp_param *scp_param;
+
+       BUG_ON(!device);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       isp_param = &device->is_region->parameter.isp;
+       drc_param = &device->is_region->parameter.drc;
+       scc_param = &device->is_region->parameter.scalerc;
+       odc_param = &device->is_region->parameter.odc;
+       dis_param = &device->is_region->parameter.dis;
+       dnr_param = &device->is_region->parameter.tdnr;
+       scp_param = &device->is_region->parameter.scalerp;
+
+       isp_param->control.cmd = CONTROL_COMMAND_START;
+       isp_param->control.bypass = CONTROL_BYPASS_DISABLE;
+       isp_param->control.run_mode = 1;
+       *lindex |= LOWBIT_OF(PARAM_ISP_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_ISP_CONTROL);
+       (*indexes)++;
+
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               scc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_DISABLE;
+               *lindex |= LOWBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+               (*indexes)++;
+
+               odc_param->control.cmd = CONTROL_COMMAND_STOP;
+               *lindex |= LOWBIT_OF(PARAM_ODC_CONTROL);
+               *hindex |= HIGHBIT_OF(PARAM_ODC_CONTROL);
+               (*indexes)++;
+
+               fimc_is_subdev_drc_bypass(device, &drc_param->control, lindex, hindex, indexes);
+               fimc_is_subdev_dis_stop(device, dis_param, lindex, hindex, indexes);
+               fimc_is_subdev_dnr_stop(device, &dnr_param->control, lindex, hindex, indexes);
+
+               scp_param->control.cmd = CONTROL_COMMAND_STOP;
+               *lindex |= LOWBIT_OF(PARAM_SCALERP_CONTROL);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERP_CONTROL);
+               (*indexes)++;
+       } else {
+               scc_param->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE;
+               *lindex |= LOWBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+               (*indexes)++;
+
+               odc_param->control.cmd = CONTROL_COMMAND_START;
+               *lindex |= LOWBIT_OF(PARAM_ODC_CONTROL);
+               *hindex |= HIGHBIT_OF(PARAM_ODC_CONTROL);
+               (*indexes)++;
+
+               fimc_is_subdev_drc_bypass(device, &drc_param->control, lindex, hindex, indexes);
+               fimc_is_subdev_dis_bypass(device, dis_param, lindex, hindex, indexes);
+               fimc_is_subdev_dnr_bypass(device, &dnr_param->control, lindex, hindex, indexes);
+
+               scp_param->control.cmd = CONTROL_COMMAND_START;
+#ifdef SCALER_PARALLEL_MODE
+               scp_param->otf_input.scaler_path_sel = OTF_INPUT_PARAL_PATH;
+#else
+               scp_param->otf_input.scaler_path_sel = OTF_INPUT_SERIAL_PATH;
+#endif
+               *lindex |= LOWBIT_OF(PARAM_SCALERP_CONTROL);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERP_CONTROL);
+               (*indexes)++;
+       }
+
+       return ret;
+}
+
+#ifdef ENABLE_SETFILE
+static int fimc_is_ischain_chg_setfile(struct fimc_is_device_ischain *device,
+       unsigned int setfile)
+{
+       int ret = 0;
+       u32 group_id = 0;
+       struct fimc_is_group *group_isp;
+       unsigned int save_setfile;
+
+       BUG_ON(!device);
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &device->group_3aa.state)) {
+               mwarn("Changing setfile index is not supportd at OTF group\n", device);
+               goto p_err;
+       }
+
+       group_isp = &device->group_isp;
+
+       if (group_isp->smp_shot.count < 1) {
+               mwarn("group%d is working(%d), setfile change is fail",
+                       device, group_isp->id, group_isp->smp_shot.count);
+               goto p_err;
+       }
+
+       group_id |= GROUP_ID(device->group_3aa.id);
+       group_id |= GROUP_ID(device->group_isp.id);
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group_id & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group_id = GROUP_ID(GROUP_ID_3A0);
+
+       if (test_bit(FIMC_IS_GROUP_ACTIVE, &device->group_dis.state))
+               group_id |= GROUP_ID(device->group_dis.id);
+
+       save_setfile = device->setfile;
+       device->setfile = setfile;
+
+       ret = fimc_is_itf_process_stop(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_stop fail", device);
+               device->setfile = save_setfile;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_a_param(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_a_param is fail", device);
+               device->setfile = save_setfile;
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_process_start(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_start fail", device);
+               device->setfile = save_setfile;
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       minfo("[ISC:D] setfile: 0x%08X\n", device, device->setfile);
+
+p_err:
+       return ret;
+}
+#endif
+
+#ifdef SCALER_CROP_DZOOM
+static int fimc_is_ischain_s_dzoom(struct fimc_is_device_ischain *this,
+       u32 crop_x, u32 crop_y, u32 crop_width)
+{
+       int ret = 0;
+       u32 indexes, lindex, hindex;
+       u32 chain0_width, chain0_height;
+       u32 temp_width, temp_height, input_width;
+       u32 zoom_input, zoom_target;
+       u32 crop_cx, crop_cy, crop_cwidth, crop_cheight;
+       struct scalerc_param *scc_param;
+       u32 chain0_ratio, preview_ratio;
+       u32 chain0_ratio_width, chain0_ratio_height;
+#ifdef USE_ADVANCED_DZOOM
+       u32 zoom_pre, zoom_post, zoom_pre_max;
+       u32 crop_px, crop_py, crop_pwidth, crop_pheight;
+       u32 chain1_width, chain1_height;
+       u32 chain2_width, chain2_height;
+       u32 chain3_width, chain3_height;
+       u32 scp_input_width, scp_input_height;
+       struct scalerp_param *scp_param;
+
+       scc_param = &this->is_region->parameter.scalerc;
+       scp_param = &this->is_region->parameter.scalerp;
+       indexes = lindex = hindex = 0;
+       chain0_width = this->chain0_width;
+       chain0_height = this->chain0_height;
+       chain1_width = this->chain1_width;
+       chain1_height = this->chain1_height;
+       chain2_width = this->chain2_width;
+       chain2_height = this->chain2_height;
+       chain3_width = this->chain3_width;
+       chain3_height = this->chain3_height;
+#ifdef PRINT_DZOOM
+       printk(KERN_INFO "chain0(%d, %d), chain1(%d, %d), chain2(%d, %d)\n",
+               chain0_width, chain0_height,
+               chain1_width, chain1_height,
+               chain2_width, chain2_height);
+#endif
+#else
+       scc_param = &this->is_region->parameter.scalerc;
+       indexes = lindex = hindex = 0;
+       chain0_width = this->chain0_width;
+       chain0_height = this->chain0_height;
+#ifdef PRINT_DZOOM
+       printk(KERN_INFO "chain0(%d, %d)\n", chain0_width, chain0_height);
+#endif
+#endif
+
+       /* CHECK */
+       input_width = crop_width;
+       temp_width = crop_width + (crop_x<<1);
+       if (temp_width != chain0_width) {
+               err("input width is not valid(%d != %d)",
+                       temp_width, chain0_width);
+               /* if invalid input come, dzoom is not apply and
+               shot command is sent to firmware */
+               ret = 0;
+               goto exit;
+       }
+
+       chain0_ratio_width = chain0_width;
+       chain0_ratio_height = chain0_height;
+
+#ifdef USE_ADVANCED_DZOOM
+       zoom_input = (chain0_ratio_width * 1000) / crop_width;
+       zoom_pre_max = (chain0_ratio_width * 1000) / chain1_width;
+
+       if (zoom_pre_max < 1000)
+               zoom_pre_max = 1000;
+
+#ifdef PRINT_DZOOM
+       printk(KERN_INFO "zoom input : %d, premax-zoom : %d\n",
+               zoom_input, zoom_pre_max);
+#endif
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &this->dis.state))
+               zoom_target = (zoom_input * 91 + 34000) / 125;
+       else
+               zoom_target = zoom_input;
+
+       if (zoom_target > zoom_pre_max) {
+               zoom_pre = zoom_pre_max;
+               zoom_post = (zoom_target * 1000) / zoom_pre;
+       } else {
+               zoom_pre = zoom_target;
+               zoom_post = 1000;
+       }
+
+       /* CALCULATION */
+       temp_width = (chain0_ratio_width * 1000) / zoom_pre;
+       temp_height = (chain0_ratio_height * 1000) / zoom_pre;
+       crop_cx = (chain0_width - temp_width)>>1;
+       crop_cy = (chain0_height - temp_height)>>1;
+       crop_cwidth = chain0_width - (crop_cx<<1);
+       crop_cheight = chain0_height - (crop_cy<<1);
+
+       scc_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
+       scc_param->input_crop.pos_x = crop_cx;
+       scc_param->input_crop.pos_y = crop_cy;
+       scc_param->input_crop.crop_width = crop_cwidth;
+       scc_param->input_crop.crop_height = crop_cheight;
+       scc_param->input_crop.in_width = chain0_width;
+       scc_param->input_crop.in_height = chain0_height;
+       scc_param->input_crop.out_width = chain1_width;
+       scc_param->input_crop.out_height = chain1_height;
+       lindex |= LOWBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       hindex |= HIGHBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       indexes++;
+
+#ifdef PRINT_DZOOM
+       printk(KERN_INFO "pre-zoom target : %d(%d, %d, %d %d)\n",
+               zoom_pre, crop_cx, crop_cy, crop_cwidth, crop_cheight);
+#endif
+
+#ifdef SCALER_PARALLEL_MODE
+       scp_input_width = chain0_width;
+       scp_input_height = chain0_height;
+#else
+       scp_input_width = chain2_width;
+       scp_input_height = chain2_height;
+#endif
+       temp_width = (scp_input_width * 1000) / zoom_post;
+       temp_height = (scp_input_height * 1000) / zoom_post;
+       crop_px = (scp_input_width - temp_width)>>1;
+       crop_py = (scp_input_height - temp_height)>>1;
+       crop_pwidth = scp_input_width - (crop_px<<1);
+       crop_pheight = scp_input_height - (crop_py<<1);
+
+       scp_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
+       scp_param->input_crop.pos_x = crop_px;
+       scp_param->input_crop.pos_y = crop_py;
+       scp_param->input_crop.crop_width = crop_pwidth;
+       scp_param->input_crop.crop_height = crop_pheight;
+       scp_param->input_crop.in_width = scp_input_width;
+       scp_param->input_crop.in_height = scp_input_height;
+       scp_param->input_crop.out_width = chain3_width;
+       scp_param->input_crop.out_height = chain3_height;
+       lindex |= LOWBIT_OF(PARAM_SCALERP_INPUT_CROP);
+       hindex |= HIGHBIT_OF(PARAM_SCALERP_INPUT_CROP);
+       indexes++;
+
+#ifdef PRINT_DZOOM
+       printk(KERN_INFO "post-zoom target : %d(%d, %d, %d %d)\n",
+               zoom_post, crop_px, crop_py, crop_pwidth, crop_pheight);
+#endif
+#else
+       zoom_input = (chain0_ratio_width * 1000) / crop_width;
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &this->dis.state))
+               zoom_target = (zoom_input * 91 + 34000) / 125;
+       else
+               zoom_target = zoom_input;
+
+       temp_width = (chain0_ratio_width * 1000) / zoom_target;
+       temp_height = (chain0_ratio_height * 1000) / zoom_target;
+       crop_cx = (chain0_width - temp_width)>>1;
+       crop_cy = (chain0_height - temp_height)>>1;
+       crop_cwidth = chain0_width - (crop_cx<<1);
+       crop_cheight = chain0_height - (crop_cy<<1);
+
+       scc_param->input_crop.cmd = SCALER_CROP_COMMAND_ENABLE;
+       scc_param->input_crop.pos_x = crop_cx;
+       scc_param->input_crop.pos_y = crop_cy;
+       scc_param->input_crop.crop_width = crop_cwidth;
+       scc_param->input_crop.crop_height = crop_cheight;
+       lindex |= LOWBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       hindex |= HIGHBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       indexes++;
+
+#ifdef PRINT_DZOOM
+       printk(KERN_INFO "zoom input : %d, zoom target : %d(%d, %d, %d %d)\n",
+               zoom_input, zoom_target,
+               crop_cx, crop_cy, crop_cwidth, crop_cheight);
+#endif
+#endif
+
+       ret = fimc_is_itf_s_param(this, indexes, lindex, hindex);
+       if (ret) {
+               err("fimc_is_itf_s_param is fail\n");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       this->crop_x = crop_cx;
+       this->crop_y = crop_cy;
+       this->crop_width = crop_cwidth;
+       this->crop_height = crop_cheight;
+       this->dzoom_width = input_width;
+
+exit:
+       return ret;
+}
+#endif
+
+#ifdef ENABLE_DRC
+static int fimc_is_ischain_drc_bypass(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       bool bypass)
+{
+       int ret = 0;
+       u32 lindex, hindex, indexes;
+       struct param_control *ctl_param;
+       u32 group_id = 0;
+       struct fimc_is_group *group;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+       group = &device->group_isp;
+       if (!group) {
+               merr("group is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+               GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group_id = GROUP_ID(GROUP_ID_3A0);
+       else
+               group_id = GROUP_ID(group->id);
+
+       lindex = hindex = indexes = 0;
+       ctl_param = fimc_is_itf_g_param(device, NULL, PARAM_DRC_CONTROL);
+
+       ret = fimc_is_itf_process_stop(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (bypass)
+               fimc_is_subdev_drc_bypass(device, ctl_param, &lindex, &hindex, &indexes);
+       else
+               fimc_is_subdev_drc_start(device, ctl_param, &lindex, &hindex, &indexes);
+
+       /*
+        * It deleted a per-frame control at here. Because It is impossible to use
+        * DRC full_bypass with per-frame. So per-frame deleted and changed to set param
+        * control by g_param , s_param parameters to NULL.
+        */
+
+       ret = fimc_is_itf_s_param(device, NULL, lindex, hindex, indexes);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, frame, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_a_param(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_a_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_process_start(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (bypass)
+               clear_bit(FIMC_IS_SUBDEV_START, &device->drc.state);
+       else
+               set_bit(FIMC_IS_SUBDEV_START, &device->drc.state);
+
+p_err:
+       mrinfo("[DRC] bypass : %d\n", device, frame, bypass);
+       return ret;
+}
+#endif
+
+#ifdef ENABLE_TDNR
+static int fimc_is_ischain_dnr_bypass(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame,
+       bool bypass)
+{
+       int ret = 0;
+       u32 lindex, hindex, indexes;
+       struct param_control *ctl_param;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+       lindex = hindex = indexes = 0;
+       ctl_param = fimc_is_itf_g_param(device, frame, PARAM_TDNR_CONTROL);
+
+       if (bypass)
+               fimc_is_subdev_dnr_bypass(device, ctl_param, &lindex, &hindex, &indexes);
+       else
+               fimc_is_subdev_dnr_start(device, ctl_param, &lindex, &hindex, &indexes);
+
+       frame->shot->ctl.entry.lowIndexParam |= lindex;
+       frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, frame, lindex, hindex, indexes);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, frame, ret);
+               goto p_err;
+       }
+
+       if (bypass)
+               clear_bit(FIMC_IS_SUBDEV_START, &device->dnr.state);
+       else
+               set_bit(FIMC_IS_SUBDEV_START, &device->dnr.state);
+
+p_err:
+       mrinfo("[DNR] bypass : %d\n", device, frame, bypass);
+       return ret;
+}
+#endif
+
+static int fimc_is_ischain_fd_bypass(struct fimc_is_device_ischain *device,
+       bool bypass)
+{
+       int ret = 0;
+       struct fd_param *fd_param;
+       struct fimc_is_subdev *fd;
+       struct fimc_is_group *group;
+       u32 indexes, lindex, hindex;
+       u32 group_id = 0;
+
+       BUG_ON(!device);
+
+       mdbgd_ischain("%s(%d)\n", device, __func__, bypass);
+
+       fd = &device->fd;
+       group = fd->group;
+       if (!group) {
+               merr("group is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       group_id |= GROUP_ID(group->id);
+       fd_param = &device->is_region->parameter.fd;
+       indexes = lindex = hindex = 0;
+
+       /* if there's only one group of isp, send group id by 3a0 */
+       if ((group_id & GROUP_ID(GROUP_ID_ISP)) &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+               group_id = GROUP_ID(GROUP_ID_3A0);
+
+       ret = fimc_is_itf_process_stop(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (bypass) {
+               fd_param->control.cmd = CONTROL_COMMAND_STOP;
+               fd_param->control.bypass = CONTROL_BYPASS_DISABLE;
+       } else {
+               fd_param->control.cmd = CONTROL_COMMAND_START;
+               fd_param->control.bypass = CONTROL_BYPASS_DISABLE;
+       }
+
+       lindex |= LOWBIT_OF(PARAM_FD_CONTROL);
+       hindex |= HIGHBIT_OF(PARAM_FD_CONTROL);
+       indexes++;
+
+       fd_param->otf_input.width = device->chain3_width;
+       fd_param->otf_input.height = device->chain3_height;
+       lindex |= LOWBIT_OF(PARAM_FD_OTF_INPUT);
+       hindex |= HIGHBIT_OF(PARAM_FD_OTF_INPUT);
+       indexes++;
+
+       ret = fimc_is_itf_s_param(device, NULL, lindex, hindex, indexes);
+       if (ret) {
+               merr("fimc_is_itf_s_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_process_start(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (bypass) {
+               clear_bit(FIMC_IS_SUBDEV_START, &fd->state);
+               mdbgd_ischain("FD off\n", device);
+       } else {
+               set_bit(FIMC_IS_SUBDEV_START, &fd->state);
+               mdbgd_ischain("FD on\n", device);
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_3aa_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       u32 group_id;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+       group_id = GET_3AA_ID(vctx->video);
+
+       ret = fimc_is_group_open(groupmgr,
+               group,
+               group_id,
+               device->instance,
+               vctx,
+               device,
+               fimc_is_ischain_3aa_callback);
+       if (ret)
+               merr("fimc_is_group_open is fail", device);
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+       leader = &group->leader;
+       queue = GET_SRC_QUEUE(vctx);
+
+       ret = fimc_is_ischain_3aa_stop(device, leader, queue);
+       if (ret)
+               merr("fimc_is_ischain_3aa_stop is fail", device);
+
+       ret = fimc_is_group_close(groupmgr, group);
+       if (ret)
+               merr("fimc_is_group_close is fail", device);
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!leader);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("already start", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_group_process_start(groupmgr, group, queue);
+       if (ret) {
+               merr("fimc_is_group_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SUBDEV_START, &leader->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_3aa_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!leader);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+
+       if (!test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               mwarn("already stop", device);
+               goto p_err;
+       }
+
+       ret = fimc_is_group_process_stop(groupmgr, group, queue);
+       if (ret) {
+               merr("fimc_is_group_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SUBDEV_START, &leader->state);
+
+p_err:
+       info("[3A%d:D:%d] %s(%d, %d)\n", group->id, device->instance, __func__,
+               ret, atomic_read(&group->scount));
+       return ret;
+}
+
+int fimc_is_ischain_3aa_reqbufs(struct fimc_is_device_ischain *device,
+       u32 count)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+
+       group = &device->group_3aa;
+
+       if (!count) {
+               ret = fimc_is_itf_unmap(device, GROUP_ID(group->id));
+               if (ret)
+                       merr("fimc_is_itf_unmap is fail(%d)", device, ret);
+       }
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_s_format(struct fimc_is_device_ischain *device,
+       u32 width, u32 height)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!device);
+
+       group = &device->group_3aa;
+       leader = &group->leader;
+
+       leader->input.width = width;
+       leader->input.height = height;
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_s_input(struct fimc_is_device_ischain *device,
+       u32 input)
+{
+       int ret = 0;
+       u32 otf_input;
+       struct fimc_is_group *group;
+       struct fimc_is_groupmgr *groupmgr;
+
+       BUG_ON(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+       otf_input = (input & OTF_3AA_MASK) >> OTF_3AA_SHIFT;
+
+       mdbgd_ischain("%s() calling fimc_is_group_init\n", device, __func__);
+
+       ret = fimc_is_group_init(groupmgr, group, otf_input, 0);
+       if (ret) {
+               merr("fimc_is_group_init is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_3aa_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!test_bit(FIMC_IS_ISCHAIN_OPEN, &device->state));
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+
+       ret = fimc_is_group_buffer_queue(groupmgr, group, queue, index);
+       if (ret)
+               merr("fimc_is_group_buffer_queue is fail(%d)", device, ret);
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_buffer_finish(struct fimc_is_device_ischain *device,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_3aa;
+
+       ret = fimc_is_group_buffer_finish(groupmgr, group, index);
+       if (ret)
+               merr("fimc_is_group_buffer_finish is fail(%d)", device, ret);
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct taa_param *taa_param;
+       u32 lindex, hindex, indexes;
+       u32 crop_x, crop_y, crop_width, crop_height;
+       u32 *input_crop;
+       u32 *output_crop;
+       u32 size_change_request = 0;
+
+       BUG_ON(!device);
+       BUG_ON(!device->is_region);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+       BUG_ON(!node);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("3AA TAG(request %d)\n", device, node->request);
+#endif
+
+       lindex = hindex = indexes = 0;
+       taa_param = &device->is_region->parameter.taa;
+       input_crop = node->input.cropRegion;
+       output_crop = node->output.cropRegion;
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &device->group_3aa.state)) {
+               crop_x = taa_param->otf_input.bayer_crop_offset_x;
+               crop_y = taa_param->otf_input.bayer_crop_offset_y;
+               crop_width = taa_param->otf_input.bayer_crop_width;
+               crop_height = taa_param->otf_input.bayer_crop_height;
+       } else {
+               crop_x = taa_param->vdma1_input.bayer_crop_offset_x;
+               crop_y = taa_param->vdma1_input.bayer_crop_offset_y;
+               crop_width = taa_param->vdma1_input.bayer_crop_width;
+               crop_height = taa_param->vdma1_input.bayer_crop_height;
+       }
+
+       if (IS_NULL_COORD(input_crop)) {
+               input_crop[0] = crop_x;
+               input_crop[1] = crop_y;
+               input_crop[2] = crop_width;
+               input_crop[3] = crop_height;
+       }
+
+       if (!GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)) {
+
+               size_change_request = ((taa_param->vdma1_input.bds_out_width != output_crop[2]) ||
+                               (taa_param->vdma1_input.bds_out_height != output_crop[3]) ||
+                               (taa_param->vdma1_input.bayer_crop_width != input_crop[2]) ||
+                               (taa_param->vdma1_input.bayer_crop_height != input_crop[3]));
+
+               if (size_change_request || device->isp_size_forceset) {
+                       /*
+                        * forcefully set subsequent frame 3aa sizes until firmware acknowledges the
+                        * updation of the changed information
+                        */
+                       device->isp_size_forceset = 1;
+                       if (size_change_request)
+                               device->taa_size_changed_fcount = ldr_frame->fcount;
+
+                       ret = fimc_is_ischain_s_3aa_size(device,
+                               ldr_frame,
+                               input_crop,
+                               output_crop,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aa_size is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       mrdbg("[3AA] in_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               input_crop[0], input_crop[1], input_crop[2], input_crop[3]);
+                       mdbg_pframe("[3AA] out_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+               }
+       } else {
+
+               size_change_request = ((input_crop[0] != crop_x) ||
+                               (input_crop[1] != crop_y) ||
+                               (input_crop[2] != crop_width) ||
+                               (input_crop[3] != crop_height));
+
+               if (size_change_request || device->taa_size_forceset) {
+                       /*
+                        * forcefully set subsequent frame 3aa sizes until firmware acknowledges the
+                        * updation of the changed information
+                        */
+                       device->taa_size_forceset = 1;
+                       if (size_change_request)
+                               device->taa_size_changed_fcount = ldr_frame->fcount;
+
+                       ret = fimc_is_ischain_s_3aa_size(device,
+                               ldr_frame,
+                               input_crop,
+                               output_crop,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aa_size is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mrdbg("[3AA] in_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               input_crop[0], input_crop[1], input_crop[2], input_crop[3]);
+               }
+       }
+
+       ldr_frame->shot->ctl.entry.lowIndexParam |= lindex;
+       ldr_frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, 0);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct fimc_is_queue_ops fimc_is_ischain_3aa_ops = {
+       .start_streaming        = fimc_is_ischain_3aa_start,
+       .stop_streaming         = fimc_is_ischain_3aa_stop
+};
+
+static int fimc_is_ischain_3aap_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       struct fimc_is_queue *queue,
+       struct taa_param *taa_param,
+       u32 *output_crop,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_dma_output *taa_vdma2_output;
+
+       if ((output_crop[2] > taa_param->otf_input.bayer_crop_width) ||
+               (output_crop[3] > taa_param->otf_input.bayer_crop_height)) {
+               mrerr("bds output size is invalid((%d, %d) > (%d, %d))", device, frame,
+                       output_crop[2],
+                       output_crop[3],
+                       taa_param->otf_input.bayer_crop_width,
+                       taa_param->otf_input.bayer_crop_height);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* HACK */
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &device->group_3aa.state)) {
+               struct param_otf_input *taa_otf_input;
+
+               taa_otf_input = fimc_is_itf_g_param(device, frame, PARAM_3AA_OTF_INPUT);
+               taa_otf_input->bds_out_enable = ISP_BDS_COMMAND_ENABLE;
+               taa_otf_input->bds_out_width = output_crop[2];
+               taa_otf_input->bds_out_height = output_crop[3];
+               *lindex |= LOWBIT_OF(PARAM_3AA_OTF_INPUT);
+               *hindex |= HIGHBIT_OF(PARAM_3AA_OTF_INPUT);
+               (*indexes)++;
+       } else {
+               struct param_dma_input *taa_dma_input;
+
+               taa_dma_input = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA1_INPUT);
+               taa_dma_input->bds_out_enable = ISP_BDS_COMMAND_ENABLE;
+               taa_dma_input->bds_out_width = output_crop[2];
+               taa_dma_input->bds_out_height = output_crop[3];
+               *lindex |= LOWBIT_OF(PARAM_3AA_VDMA1_INPUT);
+               *hindex |= HIGHBIT_OF(PARAM_3AA_VDMA1_INPUT);
+               (*indexes)++;
+       }
+
+       taa_vdma2_output = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA2_OUTPUT);
+       taa_vdma2_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
+       taa_vdma2_output->width = output_crop[2];
+       taa_vdma2_output->height = output_crop[3];
+       taa_vdma2_output->buffer_number = 0;
+       taa_vdma2_output->buffer_address = 0;
+       taa_vdma2_output->dma_out_mask = 0;
+       taa_vdma2_output->bitwidth = DMA_OUTPUT_BIT_WIDTH_12BIT;
+       taa_vdma2_output->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENBABLE;
+
+       if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR10 ||
+                       queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR12) {
+               taa_vdma2_output->format = DMA_INPUT_FORMAT_BAYER_PACKED12;
+       } else if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR16) {
+               taa_vdma2_output->format = DMA_INPUT_FORMAT_BAYER;
+       } else {
+               mwarn("Invalid bayer format", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       *lindex |= LOWBIT_OF(PARAM_3AA_VDMA2_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_VDMA2_OUTPUT);
+       (*indexes)++;
+
+       set_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+p_err:
+       return ret;
+}
+
+
+static int fimc_is_ischain_3aap_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_dma_output *taa_vdma2_output;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+       taa_vdma2_output = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA2_OUTPUT);
+       taa_vdma2_output->cmd = DMA_OUTPUT_COMMAND_DISABLE;
+       *lindex |= LOWBIT_OF(PARAM_3AA_VDMA2_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_VDMA2_OUTPUT);
+       (*indexes)++;
+
+       clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+       return ret;
+}
+
+static int fimc_is_ischain_3aap_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+       struct fimc_is_framemgr *framemgr;
+       struct camera2_scaler_uctl *scalerUd;
+       struct taa_param *taa_param;
+       u32 lindex, hindex, indexes;
+       u32 *output_crop;
+
+       BUG_ON(!device);
+       BUG_ON(!device->is_region);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+       BUG_ON(!node);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("3AAP TAG(request %d)\n", device, node->request);
+#endif
+
+       lindex = hindex = indexes = 0;
+       taa_param = &device->is_region->parameter.taa;
+       scalerUd = &ldr_frame->shot->uctl.scalerUd;
+       /* HACK */
+       framemgr = GET_SUBDEV_FRAMEMGR(subdev->leader);
+       if (!framemgr) {
+               merr("framemgr is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* HACK */
+       queue = GET_SUBDEV_QUEUE(subdev->leader);
+       if (!queue) {
+               merr("queue is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (node->request) {
+               output_crop = node->output.cropRegion;
+
+               if (output_crop[0] || output_crop[1]) {
+                       mwarn("crop pos(%d, %d) is ignored", device,
+                               output_crop[0],
+                               output_crop[1]);
+                       output_crop[0] = 0;
+                       output_crop[1] = 0;
+               }
+
+               if (!output_crop[0] && !output_crop[1] &&
+                       !output_crop[2] && !output_crop[3]) {
+                       output_crop[0] = 0;
+                       output_crop[1] = 0;
+                       output_crop[2] = taa_param->vdma2_output.width;
+                       output_crop[3] = taa_param->vdma2_output.height;
+               }
+
+               if ((output_crop[2] != taa_param->vdma2_output.width) ||
+                       (output_crop[3] != taa_param->vdma2_output.height) ||
+                       !test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_3aap_start(device,
+                               subdev,
+                               ldr_frame,
+                               queue,
+                               taa_param,
+                               output_crop,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aap_start is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mdbg_pframe("[3AP] ot_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+               }
+
+               /* device address setting */
+               if (fimc_is_ischain_buf_tag(device,
+                               subdev,
+                               ldr_frame,
+                               node,
+                               queue,
+                               framemgr,
+                               output_crop[2], output_crop[3],
+                               scalerUd->taapTargetAddress,
+                               OUT_3AAP_FRAME))
+                       goto p_err;
+       } else {
+               if (test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_3aap_stop(device,
+                               subdev,
+                               ldr_frame,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aap_stop is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       info("[3AP:D:%d] off, %d\n", device->instance, ldr_frame->fcount);
+               }
+
+               mwarn("3aap request is 0", device);
+               scalerUd->taapTargetAddress[0] = 0;
+               scalerUd->taapTargetAddress[1] = 0;
+               scalerUd->taapTargetAddress[2] = 0;
+               node->request = 0;
+       }
+
+       ldr_frame->shot->ctl.entry.lowIndexParam |= lindex;
+       ldr_frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, 0);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_3aac_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       struct fimc_is_queue *queue,
+       struct taa_param *taa_param,
+       u32 *output_crop,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_dma_output *taa_vdma4_output;
+
+       if ((output_crop[2] != taa_param->otf_input.bayer_crop_width) ||
+               (output_crop[3] != taa_param->otf_input.bayer_crop_height)) {
+               merr("bds output size is invalid((%d, %d) != (%d, %d))", device,
+                       output_crop[2],
+                       output_crop[3],
+                       taa_param->otf_input.bayer_crop_width,
+                       taa_param->otf_input.bayer_crop_height);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       taa_vdma4_output = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA4_OUTPUT);
+       taa_vdma4_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
+       taa_vdma4_output->width = output_crop[2];
+       taa_vdma4_output->height = output_crop[3];
+       taa_vdma4_output->buffer_number = 0;
+       taa_vdma4_output->buffer_address = 0;
+       taa_vdma4_output->dma_out_mask = 0;
+       taa_vdma4_output->bitwidth = DMA_OUTPUT_BIT_WIDTH_12BIT;
+       taa_vdma4_output->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENBABLE;
+
+       if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR10 ||
+                       queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR12) {
+               taa_vdma4_output->format = DMA_INPUT_FORMAT_BAYER_PACKED12;
+       } else if (queue->framecfg.format.pixelformat == V4L2_PIX_FMT_SBGGR16) {
+               taa_vdma4_output->format = DMA_INPUT_FORMAT_BAYER;
+       } else {
+               mwarn("Invalid bayer format", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       *lindex |= LOWBIT_OF(PARAM_3AA_VDMA4_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_VDMA4_OUTPUT);
+       (*indexes)++;
+
+       set_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_3aac_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_dma_output *taa_vdma4_output;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+       taa_vdma4_output = fimc_is_itf_g_param(device, frame, PARAM_3AA_VDMA4_OUTPUT);
+       taa_vdma4_output->cmd = DMA_OUTPUT_COMMAND_DISABLE;
+       *lindex |= LOWBIT_OF(PARAM_3AA_VDMA4_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_3AA_VDMA4_OUTPUT);
+       (*indexes)++;
+
+       clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+       return ret;
+}
+
+static int fimc_is_ischain_3aac_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+       struct fimc_is_framemgr *framemgr;
+       struct camera2_scaler_uctl *scalerUd;
+       struct taa_param *taa_param;
+       u32 lindex, hindex, indexes;
+       u32 *output_crop;
+
+       BUG_ON(!device);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("3AAC TAG(request %d)\n", device, node->request);
+#endif
+
+       lindex = hindex = indexes = 0;
+       taa_param = &device->is_region->parameter.taa;
+       scalerUd = &ldr_frame->shot->uctl.scalerUd;
+       framemgr = GET_SUBDEV_FRAMEMGR(subdev);
+       if (!framemgr) {
+               merr("framemgr is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       queue = GET_SUBDEV_QUEUE(subdev);
+       if (!queue) {
+               merr("queue is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (node->request) {
+               output_crop = node->output.cropRegion;
+
+               output_crop[0] = 0;
+               output_crop[1] = 0;
+               output_crop[2] = taa_param->otf_input.bayer_crop_width;
+               output_crop[3] = taa_param->otf_input.bayer_crop_height;
+
+               if (!test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_3aac_start(device,
+                               subdev,
+                               ldr_frame,
+                               queue,
+                               taa_param,
+                               output_crop,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aac_start is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mdbg_pframe("[3AC] ot_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+               }
+
+               /* device address setting */
+               if (fimc_is_ischain_buf_tag(device,
+                               subdev,
+                               ldr_frame,
+                               node,
+                               queue,
+                               framemgr,
+                               output_crop[2], output_crop[3],
+                               scalerUd->taacTargetAddress,
+                               OUT_3AAC_FRAME))
+                       goto p_err;
+       } else {
+               if (test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_3aac_stop(device,
+                               subdev,
+                               ldr_frame,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aac_stop is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       info("[3AC:D:%d] off, %d\n", device->instance, ldr_frame->fcount);
+               }
+
+               scalerUd->taacTargetAddress[0] = 0;
+               scalerUd->taacTargetAddress[1] = 0;
+               scalerUd->taacTargetAddress[2] = 0;
+               node->request = 0;
+       }
+
+       ldr_frame->shot->ctl.entry.lowIndexParam |= lindex;
+       ldr_frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, 0);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_isp_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_subdev *leader_3aa;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+#ifdef ENABLE_BAYER_CROP
+       u32 crop_x, crop_y, crop_width, crop_height;
+       u32 sensor_width, sensor_height, sensor_ratio;
+       u32 chain0_width, chain0_height, chain0_ratio;
+       u32 chain3_width, chain3_height, chain3_ratio;
+       u32 chain1_wmin, chain1_hmin;
+#endif
+       u32 input_crop[4] = {0, };
+       u32 output_crop[4] = {0, };
+       u32 lindex = 0;
+       u32 hindex = 0;
+       u32 indexes = 0;
+
+       BUG_ON(!device);
+       BUG_ON(!device->sensor);
+       BUG_ON(!queue);
+
+       mdbgd_isp("%s()\n", device, __func__);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_isp;
+       if (device->group_3aa.id == GROUP_ID_INVALID)
+               leader_3aa = NULL;
+       else
+               leader_3aa = &device->group_3aa.leader;
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("already start", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* 1. check chain size */
+       if (leader_3aa && (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) ||
+                               GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1))) {
+               if (test_bit(FIMC_IS_SUBDEV_OPEN, &leader_3aa->state) &&
+                               (leader_3aa->output.width != leader->input.width)) {
+                       merr("width size is invalid(%d != %d)", device,
+                                       leader_3aa->output.width, leader->input.width);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (test_bit(FIMC_IS_SUBDEV_OPEN, &leader_3aa->state) &&
+                               (leader_3aa->output.height != leader->input.height)) {
+                       merr("height size is invalid(%d != %d)", device,
+                                       leader_3aa->output.height, leader->input.height);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               /* BDS size */
+               device->chain0_width = leader->input.width;
+               device->chain0_height = leader->input.height;
+       } else {
+               /* BDS size */
+               device->chain0_width = leader->input.width - device->margin_width;
+               device->chain0_height = leader->input.height - device->margin_height;
+       }
+
+       device->dzoom_width = 0;
+       device->bds_width = 0;
+       device->bds_height = 0;
+#ifdef ENABLE_BAYER_CROP
+       /* 2. crop calculation */
+       sensor_width = device->sensor_width;
+       sensor_height = device->sensor_height;
+       chain3_width = device->chain3_width;
+       chain3_height = device->chain3_height;
+       crop_width = sensor_width;
+       crop_height = sensor_height;
+       crop_x = crop_y = 0;
+
+       sensor_ratio = sensor_width * 1000 / sensor_height;
+       chain3_ratio = chain3_width * 1000 / chain3_height;
+
+       if (sensor_ratio == chain3_ratio) {
+               crop_width = sensor_width;
+               crop_height = sensor_height;
+       } else if (sensor_ratio < chain3_ratio) {
+               /*
+                * isp dma input limitation
+                * height : 2 times
+                */
+               crop_height =
+                       (sensor_width * chain3_height) / chain3_width;
+               crop_height = ALIGN(crop_height, 2);
+               crop_y = ((sensor_height - crop_height) >> 1) & 0xFFFFFFFE;
+       } else {
+               /*
+                * isp dma input limitation
+                * width : 4 times
+                */
+               crop_width =
+                       (sensor_height * chain3_width) / chain3_height;
+               crop_width = ALIGN(crop_width, 4);
+               crop_x = ((sensor_width - crop_width) >> 1) & 0xFFFFFFFE;
+       }
+       device->chain0_width = crop_width;
+       device->chain0_height = crop_height;
+
+       device->dzoom_width = crop_width;
+       device->crop_width = crop_width;
+       device->crop_height = crop_height;
+       device->crop_x = crop_x;
+       device->crop_y = crop_y;
+
+       dbg_isp("crop_x : %d, crop y : %d\n", crop_x, crop_y);
+       dbg_isp("crop width : %d, crop height : %d\n",
+               crop_width, crop_height);
+
+       /* 2. scaling calculation */
+       chain1_wmin = (crop_width >> 4) & 0xFFFFFFFE;
+       chain1_hmin = (crop_height >> 4) & 0xFFFFFFFE;
+
+       if (chain1_wmin > device->chain1_width) {
+               printk(KERN_INFO "scc down scale limited : (%d,%d)->(%d,%d)\n",
+                       device->chain1_width, device->chain1_height,
+                       chain1_wmin, chain1_hmin);
+               device->chain1_width = chain1_wmin;
+               device->chain1_height = chain1_hmin;
+               device->chain2_width = chain1_wmin;
+               device->chain2_height = chain1_hmin;
+       }
+#endif
+
+       fimc_is_ischain_s_sensor(device, &lindex, &hindex, &indexes);
+
+       /* init value: perframe parameters are not set before stream on. */
+       input_crop[0] = 0;
+       input_crop[1] = 0;
+       input_crop[2] = fimc_is_sensor_g_bns_width(device->sensor) - device->margin_width;
+       input_crop[3] = fimc_is_sensor_g_bns_height(device->sensor) - device->margin_height;
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)) {
+               /*
+                * In case of dirty bayer capture, reprocessing instance does not use 3aa.
+                * In this case, ischain device has no 3aa group.
+                */
+               if (leader_3aa && test_bit(FIMC_IS_SUBDEV_OPEN, &leader_3aa->state))
+                       fimc_is_ischain_s_3aa_size(device, NULL, input_crop,
+                                       output_crop, &lindex, &hindex, &indexes);
+       } else {
+               output_crop[0] = 0;
+               output_crop[1] = 0;
+               output_crop[2] = device->chain0_width;
+               output_crop[3] = device->chain0_height;
+
+               fimc_is_ischain_s_3aa_size(device, NULL, input_crop,
+                               output_crop, &lindex, &hindex, &indexes);
+       }
+
+       fimc_is_ischain_s_chain0_size(device,
+               NULL, device->chain0_width, device->chain0_height,
+                               &lindex, &hindex, &indexes);
+
+       fimc_is_ischain_s_chain1_size(device,
+               device->chain1_width, device->chain1_height,
+                               &lindex, &hindex, &indexes);
+
+       fimc_is_ischain_s_chain2_size(device,
+               NULL, device->chain2_width, device->chain2_height,
+                               &lindex, &hindex, &indexes);
+
+       fimc_is_ischain_s_chain3_size(device,
+               NULL, device->chain3_width, device->chain3_height,
+                               &lindex, &hindex, &indexes);
+
+       info("[3AA:D:%d] 3AA in size(%d x %d)\n", device->instance, input_crop[2], input_crop[3]);
+       info("[ISC:D:%d] BDS out to SCC in size(%d x %d)\n", device->instance,
+               device->chain0_width, device->chain0_height);
+       info("[ISC:D:%d] SCC out to DIS in size(%d x %d)\n", device->instance,
+               device->chain1_width, device->chain1_height);
+       info("[ISC:D:%d] DIS out to SCP in size(%d x %d)\n", device->instance,
+               device->chain2_width, device->chain2_height);
+       info("[ISC:D:%d] SCP out to FD in size(%d x %d)\n", device->instance,
+               device->chain3_width, device->chain3_height);
+
+
+       fimc_is_ischain_s_path(device, &lindex, &hindex, &indexes);
+
+       fimc_is_ischain_s_color_range(device, device->color_range, &lindex, &hindex, &indexes);
+
+       if (test_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state))
+               fimc_is_itf_sensor_mode(device);
+
+       lindex = 0xFFFFFFFF;
+       hindex = 0xFFFFFFFF;
+       indexes = 64;
+
+       ret = fimc_is_itf_s_param(device , NULL, lindex, hindex, indexes);
+       if (ret) {
+               merr("fimc_is_itf_s_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_f_param(device);
+       if (ret) {
+               merr("fimc_is_itf_f_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_sys_ctl(device, IS_SYS_CLOCK_GATE, sysfs_debug.clk_gate_mode);
+       if (ret) {
+               merr("fimc_is_itf_sys_ctl is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /*
+        * this code is enabled when camera 2.0 feature is enabled
+        * ret = fimc_is_itf_g_capability(device);
+        * if (ret) {
+        *      err("fimc_is_itf_g_capability is fail\n");
+        *      ret = -EINVAL;
+        *      goto p_err;
+        *}
+        */
+
+       ret = fimc_is_itf_init_process_start(device);
+       if (ret) {
+               merr("fimc_is_itf_init_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_group_process_start(groupmgr, group, queue);
+       if (ret) {
+               merr("fimc_is_group_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SUBDEV_START, &leader->state);
+       set_bit(FIMC_IS_ISHCAIN_START, &device->state);
+
+p_err:
+       info("[ISP:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return ret;
+}
+
+int fimc_is_ischain_isp_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!leader);
+       BUG_ON(!queue);
+
+       mdbgd_isp("%s\n", device, __func__);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_isp;
+
+       if (!test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               mwarn("already stop", device);
+               goto p_err;
+       }
+
+       ret = fimc_is_group_process_stop(groupmgr, group, queue);
+       if (ret) {
+               merr("fimc_is_group_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SUBDEV_START, &leader->state);
+       clear_bit(FIMC_IS_ISHCAIN_START, &device->state);
+
+p_err:
+       info("[ISP:D:%d] %s(%d, %d)\n", device->instance, __func__,
+               ret, atomic_read(&group->scount));
+       return ret;
+}
+
+int fimc_is_ischain_isp_reqbufs(struct fimc_is_device_ischain *device,
+       u32 count)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+
+       group = &device->group_isp;
+
+       if (!count) {
+               ret = fimc_is_itf_unmap(device, GROUP_ID(group->id));
+               if (ret)
+                       merr("fimc_is_itf_unmap is fail(%d)", device, ret);
+       }
+
+       return ret;
+}
+
+int fimc_is_ischain_isp_s_format(struct fimc_is_device_ischain *device,
+       u32 width, u32 height)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!device);
+
+       group = &device->group_isp;
+       subdev = &group->leader;
+
+       subdev->input.width = width;
+       subdev->input.height = height;
+
+       return ret;
+}
+
+int fimc_is_ischain_isp_s_input(struct fimc_is_device_ischain *device,
+       u32 input)
+{
+       int ret = 0;
+       struct fimc_is_group *group;
+       struct fimc_is_groupmgr *groupmgr;
+       u32 tax_vindex;
+
+       BUG_ON(!device);
+
+       group = &device->group_isp;
+       groupmgr = device->groupmgr;
+       tax_vindex = (input & TAX_VINDEX_MASK) >> TAX_VINDEX_SHIFT;
+
+
+       /* checking 3ax group connection */
+       if ((GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == true) ||
+               (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == true)) {
+               if (!((tax_vindex == FIMC_IS_VIDEO_3A0C_NUM) ||
+                       (tax_vindex == FIMC_IS_VIDEO_3A0P_NUM) ||
+                       (tax_vindex == FIMC_IS_VIDEO_3A1C_NUM) ||
+                       (tax_vindex == FIMC_IS_VIDEO_3A1P_NUM))) {
+                       merr("TAX_VINDEX(%d) is invalid", device, tax_vindex);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+       }
+
+       mdbgd_ischain("%s() calling fimc_is_group_init\n", device, __func__);
+
+       ret = fimc_is_group_init(groupmgr, group, false, tax_vindex);
+       if (ret) {
+               merr("fimc_is_group_init is fail", device);
+               ret = -EINVAL;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_isp_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!test_bit(FIMC_IS_ISCHAIN_OPEN, &device->state));
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_isp;
+
+       ret = fimc_is_group_buffer_queue(groupmgr, group, queue, index);
+       if (ret) {
+               merr("fimc_is_group_buffer_queue is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_isp_buffer_finish(struct fimc_is_device_ischain *device,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_isp;
+
+       ret = fimc_is_group_buffer_finish(groupmgr, group, index);
+       if (ret)
+               merr("fimc_is_group_buffer_finish is fail(%d)", device, ret);
+
+       return ret;
+}
+
+int fimc_is_ischain_isp_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct isp_param *isp_param;
+       u32 lindex, hindex, indexes;
+       u32 *input_crop;
+       u32 *output_crop;
+       u32 size_change_request = 0;
+
+       BUG_ON(!device);
+       BUG_ON(!device->is_region);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+       BUG_ON(!node);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("ISP TAG(request %d)\n", device, node->request);
+#endif
+
+       lindex = hindex = indexes = 0;
+       isp_param = &device->is_region->parameter.isp;
+       input_crop = node->input.cropRegion;
+       output_crop = node->output.cropRegion;
+
+       if (!GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)) {
+               if (IS_NULL_COORD(output_crop)) {
+                       output_crop[0] = 0;
+                       output_crop[1] = 0;
+                       output_crop[2] = isp_param->otf_output.width;
+                       output_crop[3] = isp_param->otf_output.height;
+               }
+
+               size_change_request = ((output_crop[2] != isp_param->otf_output.width) ||
+                               (output_crop[3] != isp_param->otf_output.height));
+
+               if (size_change_request || device->isp_size_forceset) {
+                       device->isp_size_forceset = 1;
+                       if (size_change_request)
+                               device->isp_size_changed_fcount = ldr_frame->fcount;
+
+                       ret = fimc_is_ischain_s_chain0_size(device,
+                               ldr_frame,
+                               output_crop[2],
+                               output_crop[3],
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_s_chain0_size is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mrinfo("[ISP] out_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+               }
+       } else {
+               if (IS_NULL_COORD(input_crop)) {
+                       input_crop[0] = 0;
+                       input_crop[1] = 0;
+                       input_crop[2] = isp_param->vdma1_input.width;
+                       input_crop[3] = isp_param->vdma1_input.height;
+               }
+
+               size_change_request = ((input_crop[2] != isp_param->vdma1_input.width) ||
+                               (input_crop[3] != isp_param->vdma1_input.height));
+
+               if (size_change_request || device->isp_size_forceset) {
+
+                       device->isp_size_forceset = 1;
+                       if (size_change_request)
+                               device->isp_size_changed_fcount = ldr_frame->fcount;
+
+                       ret = fimc_is_ischain_s_chain0_size(device,
+                               ldr_frame,
+                               input_crop[2],
+                               input_crop[3],
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_s_chain0_size is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mrdbg("[ISP] in_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                                       input_crop[0], input_crop[1], input_crop[2], input_crop[3]);
+               }
+       }
+
+       ldr_frame->shot->ctl.entry.lowIndexParam |= lindex;
+       ldr_frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, 0);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct fimc_is_queue_ops fimc_is_ischain_isp_ops = {
+       .start_streaming        = fimc_is_ischain_isp_start,
+       .stop_streaming         = fimc_is_ischain_isp_stop
+};
+
+static int fimc_is_ischain_scc_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       struct fimc_is_queue *queue,
+       struct scalerc_param *scc_param,
+       u32 *input_crop,
+       u32 *output_crop,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       u32 planes, i, j, buf_index;
+       struct param_dma_output *scc_dma_output;
+       struct param_otf_output *scc_otf_output;
+       struct param_scaler_input_crop *scc_input_crop;
+       struct param_scaler_output_crop *scc_output_crop;
+#ifndef SCALER_PARALLEL_MODE
+       struct param_otf_input *scp_otf_input;
+#endif
+
+       if (output_crop[2] > scc_param->otf_input.width * MAX_ZOOM_LEVEL) {
+               mwarn("Cannot be scaled up beyond %d times(%d -> %d)",
+                       device, MAX_ZOOM_LEVEL, scc_param->otf_input.width, output_crop[2]);
+               output_crop[2] = scc_param->otf_input.width * MAX_ZOOM_LEVEL;
+       }
+
+       if (output_crop[3] > scc_param->otf_input.height * MAX_ZOOM_LEVEL) {
+               mwarn("Cannot be scaled up beyond %d times(%d -> %d)",
+                       device, MAX_ZOOM_LEVEL, scc_param->otf_input.height, output_crop[3]);
+               output_crop[3] = scc_param->otf_input.height * MAX_ZOOM_LEVEL;
+       }
+
+       if (output_crop[2] < (scc_param->otf_input.width + 15) / 16) {
+               mwarn("Cannot be scaled down beyond 1/16 times(%d -> %d)",
+                       device, scc_param->otf_input.width, output_crop[2]);
+               output_crop[2] = (scc_param->otf_input.width + 15) / 16;
+       }
+
+       if (output_crop[3] < (scc_param->otf_input.height + 15) / 16) {
+               mwarn("Cannot be scaled down beyond 1/16 times(%d -> %d)",
+                       device, scc_param->otf_input.height, output_crop[3]);
+               output_crop[3] = (scc_param->otf_input.height + 15) / 16;
+       }
+
+       planes = queue->framecfg.format.num_planes;
+       for (i = 0; i < queue->buf_maxcount; i++) {
+               for (j = 0; j < planes; j++) {
+                       buf_index = i*planes + j;
+                       device->is_region->shared[447+buf_index] = queue->buf_dva[i][j];
+               }
+       }
+
+       mdbgd_ischain("buf_num:%d buf_plane:%d shared[447] : 0x%X\n",
+               device,
+               queue->buf_maxcount,
+               queue->framecfg.format.num_planes,
+               device->imemory.kvaddr_shared + 447 * sizeof(u32));
+
+       /* setting always although otf output is not used. */
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               scc_otf_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OTF_OUTPUT);
+               scc_otf_output->width = output_crop[2];
+               scc_otf_output->height = output_crop[3];
+       } else {
+               scc_otf_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OTF_OUTPUT);
+#ifdef SCALER_PARALLEL_MODE
+               scc_otf_output->width = output_crop[2];
+               scc_otf_output->height = output_crop[3];
+#else
+               scp_otf_input = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_OTF_INPUT);
+               scc_otf_output->width = scp_otf_input->width;
+               scc_otf_output->height = scp_otf_input->height;
+#endif
+       }
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+       (*indexes)++;
+
+       scc_input_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_INPUT_CROP);
+       scc_input_crop->cmd = SCALER_CROP_COMMAND_ENABLE;
+       scc_input_crop->pos_x = input_crop[0];
+       scc_input_crop->pos_y = input_crop[1];
+       scc_input_crop->crop_width = input_crop[2];
+       scc_input_crop->crop_height = input_crop[3];
+       scc_input_crop->in_width = scc_param->otf_input.width;
+       scc_input_crop->in_height = scc_param->otf_input.height;
+       scc_input_crop->out_width = output_crop[2];
+       scc_input_crop->out_height = output_crop[3];
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       (*indexes)++;
+
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+               scc_output_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OUTPUT_CROP);
+               scc_output_crop->cmd = SCALER_CROP_COMMAND_ENABLE;
+               scc_output_crop->pos_x = output_crop[0];
+               scc_output_crop->pos_y = output_crop[1];
+               scc_output_crop->crop_width = output_crop[2];
+               scc_output_crop->crop_height = output_crop[3];
+               *lindex |= LOWBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+               (*indexes)++;
+
+               scc_dma_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_DMA_OUTPUT);
+               scc_dma_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
+               scc_dma_output->buffer_number = queue->buf_maxcount;
+               scc_dma_output->plane = queue->framecfg.format.num_planes - 1;
+               scc_dma_output->buffer_address = device->imemory.dvaddr_shared + 447*sizeof(u32);
+               scc_dma_output->width = output_crop[2];
+               scc_dma_output->height = output_crop[3];
+               scc_dma_output->reserved[0] = SCALER_DMA_OUT_SCALED;
+       } else {
+               scc_output_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OUTPUT_CROP);
+               scc_output_crop->cmd = SCALER_CROP_COMMAND_DISABLE;
+               scc_output_crop->pos_x = output_crop[0];
+               scc_output_crop->pos_y = output_crop[1];
+               scc_output_crop->crop_width = output_crop[2];
+               scc_output_crop->crop_height = output_crop[3];
+               *lindex |= LOWBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+               *hindex |= HIGHBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+               (*indexes)++;
+
+               scc_dma_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_DMA_OUTPUT);
+               scc_dma_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
+               scc_dma_output->buffer_number = queue->buf_maxcount;
+               scc_dma_output->plane = queue->framecfg.format.num_planes - 1;
+               scc_dma_output->buffer_address = device->imemory.dvaddr_shared + 447*sizeof(u32);
+#ifdef SCALER_PARALLEL_MODE
+               scc_dma_output->width = output_crop[2];
+               scc_dma_output->height = output_crop[3];
+               scc_dma_output->reserved[0] = SCALER_DMA_OUT_SCALED;
+#else
+               scc_dma_output->width = input_crop[2];
+               scc_dma_output->height = input_crop[3];
+               scc_dma_output->reserved[0] = SCALER_DMA_OUT_UNSCALED;
+#endif
+       }
+
+       switch (queue->framecfg.format.pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+               scc_dma_output->format = DMA_OUTPUT_FORMAT_YUV422,
+               scc_dma_output->plane = DMA_OUTPUT_PLANE_1;
+               scc_dma_output->order = DMA_OUTPUT_ORDER_CrYCbY;
+               break;
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV21:
+               scc_dma_output->format = OTF_OUTPUT_FORMAT_YUV420,
+               scc_dma_output->plane = DMA_OUTPUT_PLANE_2;
+               scc_dma_output->order = DMA_OUTPUT_ORDER_CbCr;
+               break;
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV12:
+               scc_dma_output->format = OTF_OUTPUT_FORMAT_YUV420,
+               scc_dma_output->plane = DMA_OUTPUT_PLANE_2;
+               scc_dma_output->order = DMA_OUTPUT_ORDER_CrCb;
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               scc_dma_output->format = OTF_OUTPUT_FORMAT_YUV420,
+               scc_dma_output->plane = DMA_OUTPUT_PLANE_3;
+               scc_dma_output->order = DMA_OUTPUT_ORDER_NO;
+               break;
+       default:
+               mwarn("unknown preview pixelformat", device);
+               break;
+       }
+
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_DMA_OUTPUT);
+       (*indexes)++;
+
+       set_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+       return ret;
+}
+
+static int fimc_is_ischain_scc_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       struct scalerc_param *scc_param,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_dma_output *scc_dma_output;
+       struct param_scaler_input_crop *scc_input_crop;
+       struct param_otf_output *scc_otf_output;
+       struct param_scaler_output_crop *scc_output_crop;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+       scc_dma_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_DMA_OUTPUT);
+       scc_dma_output->cmd = DMA_OUTPUT_COMMAND_DISABLE;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_DMA_OUTPUT);
+       (*indexes)++;
+
+       /* If SCC output size is bigger than input,
+        * it takes more time for scale up processing.
+        */
+       scc_input_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_INPUT_CROP);
+       scc_input_crop->out_width = device->chain1_width;
+       scc_input_crop->out_height = device->chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_INPUT_CROP);
+       (*indexes)++;
+
+       /* Even if SCC otf output path is not used,
+        * otf output size should be same with input crop output size.
+        * Otherwise, scaler hang can be induced at digital zoom scenario.
+        */
+       scc_otf_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OTF_OUTPUT);
+       scc_otf_output->width = device->chain1_width;
+       scc_otf_output->height = device->chain1_height;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_OTF_OUTPUT);
+       (*indexes)++;
+
+       scc_output_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERC_OUTPUT_CROP);
+       scc_output_crop->cmd = SCALER_CROP_COMMAND_DISABLE;
+       *lindex |= LOWBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERC_OUTPUT_CROP);
+       (*indexes)++;
+
+       clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+       return ret;
+}
+
+static int fimc_is_ischain_scc_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+       struct fimc_is_framemgr *framemgr;
+       struct camera2_scaler_uctl *scalerUd;
+       struct scalerc_param *scc_param;
+       u32 lindex, hindex, indexes;
+       u32 *input_crop, *output_crop;
+       u32 dma_width, dma_height;
+
+       BUG_ON(!device);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("SCC TAG(request %d)\n", device, node->request);
+#endif
+
+       lindex = hindex = indexes = 0;
+       scc_param = &device->is_region->parameter.scalerc;
+       scalerUd = &ldr_frame->shot->uctl.scalerUd;
+       framemgr = GET_SUBDEV_FRAMEMGR(subdev);
+       if (!framemgr) {
+               merr("framemgr is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       queue = GET_SUBDEV_QUEUE(subdev);
+       if (!queue) {
+               merr("queue is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (node->request) {
+               input_crop = node->input.cropRegion;
+               output_crop = node->output.cropRegion;
+
+               if (!input_crop[0] && !input_crop[1] &&
+                       !input_crop[2] && !input_crop[3]) {
+                       input_crop[0] = scc_param->input_crop.pos_x;
+                       input_crop[1] = scc_param->input_crop.pos_y;
+                       input_crop[2] = scc_param->input_crop.crop_width;
+                       input_crop[3] = scc_param->input_crop.crop_height;
+               }
+
+               if (!output_crop[0] && !output_crop[1] &&
+                       !output_crop[2] && !output_crop[3]) {
+                       output_crop[0] = scc_param->output_crop.pos_x;
+                       output_crop[1] = scc_param->output_crop.pos_y;
+                       output_crop[2] = scc_param->output_crop.crop_width;
+                       output_crop[3] = scc_param->output_crop.crop_height;
+               }
+
+               if ((input_crop[0] != scc_param->input_crop.pos_x) ||
+                       (input_crop[1] != scc_param->input_crop.pos_y) ||
+                       (input_crop[2] != scc_param->input_crop.crop_width) ||
+                       (input_crop[3] != scc_param->input_crop.crop_height) ||
+                       (output_crop[0] != scc_param->output_crop.pos_x) ||
+                       (output_crop[1] != scc_param->output_crop.pos_y) ||
+                       (output_crop[2] != scc_param->output_crop.crop_width) ||
+                       (output_crop[3] != scc_param->output_crop.crop_height) ||
+                       (input_crop[2] != scc_param->dma_output.width) ||
+                       (input_crop[3] != scc_param->dma_output.height) ||
+                       !test_bit(FIMC_IS_SUBDEV_START, &subdev->state) ||
+                       device->isp_size_forceset) {
+
+                       ret = fimc_is_ischain_scc_start(device,
+                               subdev,
+                               ldr_frame,
+                               queue,
+                               scc_param,
+                               input_crop,
+                               output_crop,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_scc_start is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mdbg_pframe("[SCC] in_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               input_crop[0], input_crop[1], input_crop[2], input_crop[3]);
+                       mdbg_pframe("[SCC] ot_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+               }
+
+               if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) {
+                       dma_width = node->output.cropRegion[2];
+                       dma_height = node->output.cropRegion[3];
+               } else {
+#ifdef SCALER_PARALLEL_MODE
+                       dma_width = node->output.cropRegion[2];
+                       dma_height = node->output.cropRegion[3];
+#else
+                       /* in scaler serial mode, use input crop w/h for dma size */
+                       dma_width = node->input.cropRegion[2];
+                       dma_height = node->input.cropRegion[3];
+#endif
+               }
+               /* device address setting */
+               if (fimc_is_ischain_buf_tag(device,
+                               subdev,
+                               ldr_frame,
+                               node,
+                               queue,
+                               framemgr,
+                               dma_width, dma_height,
+                               scalerUd->sccTargetAddress,
+                               OUT_SCC_FRAME))
+                       goto p_err;
+
+       } else {
+               if (test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_scc_stop(device,
+                               subdev,
+                               ldr_frame,
+                               scc_param,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_scc_stop is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       info("[SCC:D:%d] off, %d\n", device->instance, ldr_frame->fcount);
+               }
+
+               scalerUd->sccTargetAddress[0] = 0;
+               scalerUd->sccTargetAddress[1] = 0;
+               scalerUd->sccTargetAddress[2] = 0;
+               node->request = 0;
+       }
+
+       ldr_frame->shot->ctl.entry.lowIndexParam |= lindex;
+       ldr_frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, 0);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_scp_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       struct fimc_is_queue *queue,
+       struct scalerp_param *scp_param,
+       u32 *input_crop,
+       u32 *output_crop,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       u32 planes, i, j, buf_index;
+       struct param_dma_output *scp_dma_output;
+       struct param_scaler_input_crop *scp_input_crop;
+       struct param_scaler_output_crop  *scp_output_crop;
+
+       fimc_is_ischain_scp_adjust_crop(device, scp_param, &output_crop[2], &output_crop[3]);
+
+       planes = queue->framecfg.format.num_planes;
+       for (i = 0; i < queue->buf_maxcount; i++) {
+               for (j = 0; j < planes; j++) {
+                       buf_index = i*planes + j;
+                       device->is_region->shared[400 + buf_index] = queue->buf_dva[i][j];
+               }
+       }
+
+       mdbgd_ischain("buf_num:%d buf_plane:%d shared[400] : 0x%X\n",
+               device,
+               queue->buf_maxcount,
+               queue->framecfg.format.num_planes,
+               device->imemory.kvaddr_shared + 400 * sizeof(u32));
+
+       scp_input_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_INPUT_CROP);
+       scp_input_crop->cmd = SCALER_CROP_COMMAND_ENABLE;
+       scp_input_crop->pos_x = input_crop[0];
+       scp_input_crop->pos_y = input_crop[1];
+       scp_input_crop->crop_width = input_crop[2];
+       scp_input_crop->crop_height = input_crop[3];
+#ifdef SCALER_PARALLEL_MODE
+       scp_input_crop->in_width = device->bds_width;
+       scp_input_crop->in_height = device->bds_height;
+       scp_input_crop->out_width = output_crop[2];
+       scp_input_crop->out_height = output_crop[3];
+#else
+       scp_input_crop->in_width = scp_param->otf_input.width;
+       scp_input_crop->in_height = scp_param->otf_input.height;
+       scp_input_crop->out_width = scp_param->otf_output.width;
+       scp_input_crop->out_height = scp_param->otf_output.height;
+#endif
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_INPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_INPUT_CROP);
+       (*indexes)++;
+
+       /*
+        * scaler can't apply stride to each plane, only y plane.
+        * basically cb, cr plane should be half of y plane,
+        * and it's automatically set
+        *
+        * 3 plane : all plane should be 8 or 16 stride
+        * 2 plane : y plane should be 32, 16 stride, others should be half stride of y
+        * 1 plane : all plane should be 8 stride
+        */
+       /*
+        * limitation of output_crop.pos_x and pos_y
+        * YUV422 3P, YUV420 3P : pos_x and pos_y should be x2
+        * YUV422 1P : pos_x should be x2
+        */
+       scp_output_crop = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_OUTPUT_CROP);
+       scp_output_crop->cmd = SCALER_CROP_COMMAND_ENABLE;
+       scp_output_crop->pos_x = output_crop[0];
+       scp_output_crop->pos_y = output_crop[1];
+       scp_output_crop->crop_width = output_crop[2];
+       scp_output_crop->crop_height = output_crop[3];
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_OUTPUT_CROP);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_OUTPUT_CROP);
+       (*indexes)++;
+
+       scp_dma_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_DMA_OUTPUT);
+       scp_dma_output->cmd = DMA_OUTPUT_COMMAND_ENABLE;
+       scp_dma_output->buffer_number = queue->buf_maxcount;
+       scp_dma_output->plane = queue->framecfg.format.num_planes - 1;
+       scp_dma_output->buffer_address = device->imemory.dvaddr_shared + 400 * sizeof(u32);
+       scp_dma_output->width = output_crop[2];
+       scp_dma_output->height = output_crop[3];
+
+       switch (queue->framecfg.format.pixelformat) {
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               scp_dma_output->format = OTF_OUTPUT_FORMAT_YUV420,
+               scp_dma_output->plane = DMA_OUTPUT_PLANE_3;
+               scp_dma_output->order = DMA_OUTPUT_ORDER_NO;
+               break;
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV21:
+               scp_dma_output->format = OTF_OUTPUT_FORMAT_YUV420,
+               scp_dma_output->plane = DMA_OUTPUT_PLANE_2;
+               scp_dma_output->order = DMA_OUTPUT_ORDER_CbCr;
+               break;
+       default:
+               mwarn("unknown preview pixelformat", device);
+               break;
+       }
+
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_DMA_OUTPUT);
+       (*indexes)++;
+
+       set_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+       return ret;
+}
+
+static int fimc_is_ischain_scp_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *frame,
+       struct scalerp_param *scp_param,
+       u32 *lindex,
+       u32 *hindex,
+       u32 *indexes)
+{
+       int ret = 0;
+       struct param_dma_output *scp_dma_output;
+
+       mdbgd_ischain("%s\n", device, __func__);
+
+       scp_dma_output = fimc_is_itf_g_param(device, frame, PARAM_SCALERP_DMA_OUTPUT);
+       scp_dma_output->cmd = DMA_OUTPUT_COMMAND_DISABLE;
+       *lindex |= LOWBIT_OF(PARAM_SCALERP_DMA_OUTPUT);
+       *hindex |= HIGHBIT_OF(PARAM_SCALERP_DMA_OUTPUT);
+       (*indexes)++;
+
+       clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+       return ret;
+}
+
+int fimc_is_ischain_scp_s_format(struct fimc_is_device_ischain *device,
+       u32 pixelformat, u32 width, u32 height)
+{
+       int ret = 0;
+
+       /* check scaler size limitation */
+       switch (pixelformat) {
+       /*
+        * YUV422 1P, YUV422 2P : x8
+        * YUV422 3P : x16
+        */
+       case V4L2_PIX_FMT_YUV422P:
+               if (width % 8) {
+                       merr("width(%d) of format(%d) is not supported size",
+                               device, width, pixelformat);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               break;
+       /*
+        * YUV420 2P : x8
+        * YUV420 3P : x16
+        */
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV21M:
+               if (width % 8) {
+                       merr("width(%d) of format(%d) is not supported size",
+                               device, width, pixelformat);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               if (width % 16) {
+                       merr("width(%d) of format(%d) is not supported size",
+                               device, width, pixelformat);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               break;
+       default:
+               merr("format(%d) is not supported", device, pixelformat);
+               ret = -EINVAL;
+               goto p_err;
+               break;
+       }
+
+       device->chain1_width = width;
+       device->chain1_height = height;
+       device->chain2_width = width;
+       device->chain2_height = height;
+       device->chain3_width = width;
+       device->chain3_height = height;
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_ischain_scp_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+       struct fimc_is_framemgr *framemgr;
+       struct camera2_scaler_uctl *scalerUd;
+       struct scalerp_param *scp_param;
+       u32 lindex, hindex, indexes;
+       u32 *input_crop, *output_crop;
+
+       BUG_ON(!device);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("SCP TAG(request %d)\n", device, node->request);
+#endif
+
+       lindex = hindex = indexes = 0;
+       scp_param = &device->is_region->parameter.scalerp;
+       scalerUd = &ldr_frame->shot->uctl.scalerUd;
+       framemgr = GET_SUBDEV_FRAMEMGR(subdev);
+       if (!framemgr) {
+               merr("framemgr is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       queue = GET_SUBDEV_QUEUE(subdev);
+       if (!queue) {
+               merr("queue is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (node->request) {
+               input_crop = node->input.cropRegion;
+               output_crop = node->output.cropRegion;
+
+               if (!input_crop[0] && !input_crop[1] &&
+                       !input_crop[2] && !input_crop[3]) {
+                       input_crop[0] = scp_param->input_crop.pos_x;
+                       input_crop[1] = scp_param->input_crop.pos_y;
+                       input_crop[2] = scp_param->input_crop.crop_width;
+                       input_crop[3] = scp_param->input_crop.crop_height;
+               }
+
+               if (!output_crop[0] && !output_crop[1] &&
+                       !output_crop[2] && !output_crop[3]) {
+                       output_crop[0] = scp_param->output_crop.pos_x;
+                       output_crop[1] = scp_param->output_crop.pos_y;
+                       output_crop[2] = scp_param->output_crop.crop_width;
+                       output_crop[3] = scp_param->output_crop.crop_height;
+               }
+
+               if ((input_crop[0] != scp_param->input_crop.pos_x) ||
+                       (input_crop[1] != scp_param->input_crop.pos_y) ||
+                       (input_crop[2] != scp_param->input_crop.crop_width) ||
+                       (input_crop[3] != scp_param->input_crop.crop_height) ||
+                       (output_crop[0] != scp_param->output_crop.pos_x) ||
+                       (output_crop[1] != scp_param->output_crop.pos_y) ||
+                       (output_crop[2] != scp_param->output_crop.crop_width) ||
+                       (output_crop[3] != scp_param->output_crop.crop_height) ||
+                       !test_bit(FIMC_IS_SUBDEV_START, &subdev->state) ||
+                       device->isp_size_forceset) {
+#ifdef SCALER_PARALLEL_MODE
+                       ret = fimc_is_ischain_s_chain2_size(device,
+                               ldr_frame,
+                               input_crop[2],
+                               input_crop[3],
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_s_chain2_size is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       ret = fimc_is_ischain_s_chain3_size(device,
+                               ldr_frame,
+                               output_crop[2],
+                               output_crop[3],
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_s_chain3_size is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+                       mrinfo("[SCPX] xx_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+
+#endif
+                       ret = fimc_is_ischain_scp_start(device,
+                               subdev,
+                               ldr_frame,
+                               queue,
+                               scp_param,
+                               input_crop,
+                               output_crop,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_scp_start is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       mdbg_pframe("[SCP] in_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               input_crop[0], input_crop[1], input_crop[2], input_crop[3]);
+                       mdbg_pframe("[SCP] ot_crop[%d, %d, %d, %d]\n", device, ldr_frame,
+                               output_crop[0], output_crop[1], output_crop[2], output_crop[3]);
+               }
+
+               /* device address setting */
+               if (fimc_is_ischain_buf_tag(device,
+                               subdev,
+                               ldr_frame,
+                               node,
+                               queue,
+                               framemgr,
+                               output_crop[2], output_crop[3],
+                               scalerUd->scpTargetAddress,
+                               OUT_SCP_FRAME))
+                       goto p_err;
+       } else {
+               if (test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_scp_stop(device,
+                               subdev,
+                               ldr_frame,
+                               scp_param,
+                               &lindex,
+                               &hindex,
+                               &indexes);
+                       if (ret) {
+                               merr("fimc_is_ischain_scp_stop is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+
+                       info("[SCP:D:%d] off, %d\n", device->instance, ldr_frame->fcount);
+               }
+
+               scalerUd->scpTargetAddress[0] = 0;
+               scalerUd->scpTargetAddress[1] = 0;
+               scalerUd->scpTargetAddress[2] = 0;
+               node->request = 0;
+       }
+
+       ldr_frame->shot->ctl.entry.lowIndexParam |= lindex;
+       ldr_frame->shot->ctl.entry.highIndexParam |= hindex;
+       ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, 0);
+       if (ret) {
+               mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_dis_start(struct fimc_is_device_ischain *device,
+       bool bypass)
+{
+       int ret = 0;
+       u32 group_id = 0;
+       struct dis_param *dis_param;
+       u32 chain1_width, chain1_height;
+       u32 indexes, lindex, hindex;
+
+       struct fimc_is_group *group;
+       struct fimc_is_groupmgr *groupmgr;
+
+       mdbgd_ischain("%s()\n", device, __func__);
+
+       BUG_ON(!device);
+
+       chain1_width = device->dis_width;
+       chain1_height = device->dis_height;
+       indexes = lindex = hindex = 0;
+       dis_param = &device->is_region->parameter.dis;
+       group_id |= GROUP_ID(device->group_isp.id);
+       group_id |= GROUP_ID(device->group_dis.id);
+
+       group = &device->group_dis;
+       groupmgr = device->groupmgr;
+
+       mdbgd_ischain("%s() calling fimc_is_group_init\n", device, __func__);
+
+       ret = fimc_is_group_init(groupmgr, group, false, 0);
+       if (ret) {
+               merr("fimc_is_group_init is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_process_stop(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_ischain_s_chain1_size(device,
+               chain1_width, chain1_height, &lindex, &hindex, &indexes);
+
+       if (bypass)
+               fimc_is_subdev_dis_bypass(device,
+                       dis_param, &lindex, &hindex, &indexes);
+       else
+               fimc_is_subdev_dis_start(device,
+                       dis_param, &lindex, &hindex, &indexes);
+
+       ret = fimc_is_itf_s_param(device, NULL, lindex, hindex, indexes);
+       if (ret) {
+               merr("fimc_is_itf_s_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_a_param(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_a_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_process_start(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SUBDEV_START, &device->dis.state);
+       mdbgd_ischain("DIS on\n", device);
+
+       device->chain1_width = chain1_width;
+       device->chain1_height = chain1_height;
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_dis_stop(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       u32 group_id = 0;
+       struct dis_param *dis_param;
+       u32 chain1_width, chain1_height;
+       u32 indexes, lindex, hindex;
+
+       mdbgd_ischain("%s()\n", device, __func__);
+
+       chain1_width = device->chain2_width;
+       chain1_height = device->chain2_height;
+       indexes = lindex = hindex = 0;
+       dis_param = &device->is_region->parameter.dis;
+       group_id |= GROUP_ID(device->group_isp.id);
+       group_id |= GROUP_ID(device->group_dis.id);
+
+       ret = fimc_is_itf_process_stop(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_ischain_s_chain1_size(device,
+               chain1_width, chain1_height, &lindex, &hindex, &indexes);
+
+       fimc_is_subdev_dis_bypass(device,
+               dis_param, &lindex, &hindex, &indexes);
+
+       ret = fimc_is_itf_s_param(device, NULL, lindex, hindex, indexes);
+       if (ret) {
+               merr("fimc_is_itf_s_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_a_param(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_a_param is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       group_id = GROUP_ID(device->group_isp.id);
+       ret = fimc_is_itf_process_start(device, group_id);
+       if (ret) {
+               merr("fimc_is_itf_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SUBDEV_START, &device->dis.state);
+       mdbgd_ischain("DIS off\n", device);
+
+       device->chain1_width = chain1_width;
+       device->chain1_height = chain1_height;
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_dis_tag(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_frame *ldr_frame,
+       struct camera2_node *node)
+{
+       int ret = 0;
+       struct fimc_is_framemgr *framemgr;
+       struct camera2_scaler_uctl *scalerUd;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!device);
+       BUG_ON(!subdev);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!ldr_frame->shot);
+
+       scalerUd = &ldr_frame->shot->uctl.scalerUd;
+
+       queue = GET_SUBDEV_QUEUE(subdev);
+       if (!queue) {
+               merr("queue is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr = GET_SUBDEV_FRAMEMGR(subdev);
+       if (!framemgr) {
+               merr("framemgr is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (node->request) {
+               if (!test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_dis_start(device,
+                               ldr_frame->shot_ext->dis_bypass);
+                       if (ret) {
+                               merr("vdisc_start is fail", device);
+                               goto p_err;
+                       }
+               }
+
+               /* device address setting */
+               if (fimc_is_ischain_buf_tag(device,
+                               subdev,
+                               ldr_frame,
+                               node,
+                               queue,
+                               framemgr,
+                               device->chain1_width, device->chain1_height,
+                               scalerUd->disTargetAddress,
+                               OUT_DIS_FRAME))
+                       goto p_err;
+       } else {
+               if (test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+                       ret = fimc_is_ischain_dis_stop(device);
+                       if (ret) {
+                               merr("vdisc_stop is fail", device);
+                               goto p_err;
+                       }
+               }
+
+               scalerUd->disTargetAddress[0] = 0;
+               scalerUd->disTargetAddress[1] = 0;
+               scalerUd->disTargetAddress[2] = 0;
+               node->request = 0;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_vdc_s_format(struct fimc_is_device_ischain *device,
+       u32 width, u32 height)
+{
+       int ret = 0;
+
+       device->dis_width = width;
+       device->dis_height = height;
+
+       return ret;
+}
+
+int fimc_is_ischain_vdo_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_dis;
+
+       ret = fimc_is_group_open(groupmgr, group, GROUP_ID_DIS,
+               device->instance, vctx, device, fimc_is_ischain_dis_callback);
+       if (ret)
+               merr("fimc_is_group_open is fail", device);
+
+       return ret;
+}
+
+int fimc_is_ischain_vdo_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!device);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_dis;
+       leader = &group->leader;
+       queue = GET_SRC_QUEUE(vctx);
+
+       ret = fimc_is_ischain_vdo_stop(device, leader, queue);
+       if (ret)
+               merr("fimc_is_ischain_vdo_stop is fail", device);
+
+       ret = fimc_is_group_close(groupmgr, group);
+       if (ret)
+               merr("fimc_is_group_close is fail", device);
+
+       return ret;
+}
+
+int fimc_is_ischain_vdo_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!leader);
+       BUG_ON(!queue);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_dis;
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("already start", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_group_process_start(groupmgr, group, queue);
+       if (ret) {
+               merr("fimc_is_group_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SUBDEV_START, &leader->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_vdo_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!leader);
+       BUG_ON(!queue);
+
+       groupmgr = device->groupmgr;
+       group = &device->group_dis;
+
+       if (!test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               mwarn("already stop", device);
+               goto p_err;
+       }
+
+       ret = fimc_is_group_process_stop(groupmgr, group, queue);
+       if (ret) {
+               merr("fimc_is_group_process_start is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_itf_process_stop(device, GROUP_ID_DIS);
+       if (ret) {
+               merr("fimc_is_itf_process_stop is fail", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SUBDEV_START, &leader->state);
+
+p_err:
+       info("[DIS:D:%d] %s(%d, %d)\n", device->instance, __func__,
+               ret, atomic_read(&group->scount));
+       return ret;
+}
+
+int fimc_is_ischain_vdo_s_format(struct fimc_is_device_ischain *this,
+       u32 width, u32 height)
+{
+       int ret = 0;
+
+       return ret;
+}
+
+int fimc_is_ischain_vdo_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+       BUG_ON(!test_bit(FIMC_IS_ISCHAIN_OPEN, &device->state));
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_dis;
+
+       ret = fimc_is_group_buffer_queue(groupmgr, group, queue, index);
+       if (ret) {
+               merr("fimc_is_group_buffer_queue is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ischain_vdo_buffer_finish(struct fimc_is_device_ischain *device,
+       u32 index)
+{
+               int ret = 0;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+
+       BUG_ON(!device);
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_dis;
+
+       ret = fimc_is_group_buffer_finish(groupmgr, group, index);
+       if (ret)
+               merr("fimc_is_group_buffer_finish is fail(%d)", device, ret);
+
+       return ret;
+}
+
+const struct fimc_is_queue_ops fimc_is_ischain_vdo_ops = {
+       .start_streaming        = fimc_is_ischain_vdo_start,
+       .stop_streaming         = fimc_is_ischain_vdo_stop
+};
+
+int fimc_is_ischain_g_capability(struct fimc_is_device_ischain *this,
+       u32 user_ptr)
+{
+       int ret = 0;
+
+       ret = copy_to_user((void *)user_ptr, &this->capability,
+               sizeof(struct camera2_sm));
+
+       return ret;
+}
+
+int fimc_is_ischain_print_status(struct fimc_is_device_ischain *device)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_subdev *isp;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_interface *itf;
+
+       isp = &device->group_isp.leader;
+       vctx = isp->vctx;
+       framemgr = GET_SRC_FRAMEMGR(vctx);
+       itf = device->interface;
+
+       fimc_is_frame_print_free_list(framemgr);
+       fimc_is_frame_print_request_list(framemgr);
+       fimc_is_frame_print_process_list(framemgr);
+       fimc_is_frame_print_complete_list(framemgr);
+
+       return ret;
+}
+
+int fimc_is_ischain_3aa_callback(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *check_frame)
+{
+       int ret = 0;
+       u32 capture_id, group_id;
+       unsigned long flags;
+       struct fimc_is_group *group;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       struct fimc_is_subdev *leader, *taac, *taap, *scc, *dis, *scp;
+       struct camera2_node *node, *leader_node;
+
+#ifdef ENABLE_FAST_SHOT
+       uint32_t af_trigger_bk;
+       enum aa_capture_intent captureIntent_bk;
+#endif
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s()\n", device, __func__);
+#endif
+
+       BUG_ON(!device);
+       BUG_ON(!check_frame);
+
+       group = &device->group_3aa;
+       group_id = GROUP_ID(group->id);
+       leader = &group->leader;
+       framemgr = GET_LEADER_FRAMEMGR(leader);
+
+       fimc_is_frame_request_head(framemgr, &frame);
+
+       if (unlikely(!frame)) {
+               merr("frame is NULL", device);
+               return -EINVAL;
+       }
+
+       if (unlikely(frame != check_frame)) {
+               merr("frame checking is fail(%X != %X)", device,
+                       (u32)frame, (u32)check_frame);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!frame->shot)) {
+               merr("frame->shot is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!test_bit(FRAME_MAP_MEM, &frame->memory))) {
+               fimc_is_itf_map(device, group_id, frame->dvaddr_shot, frame->shot_size);
+               set_bit(FRAME_MAP_MEM, &frame->memory);
+       }
+
+       frame->shot->ctl.entry.lowIndexParam = 0;
+       frame->shot->ctl.entry.highIndexParam = 0;
+       frame->shot->dm.entry.lowIndexParam = 0;
+       frame->shot->dm.entry.highIndexParam = 0;
+       leader_node = &frame->shot_ext->node_group.leader;
+
+#ifdef ENABLE_SETFILE
+       if (frame->shot_ext->setfile != device->setfile) {
+               unsigned int setfile = frame->shot_ext->setfile;
+               ret = fimc_is_ischain_chg_setfile(device, setfile);
+               if (ret) {
+                       err("fimc_is_ischain_chg_setfile is fail");
+                       goto p_err;
+               }
+       }
+#endif
+
+#ifdef ENABLE_FAST_SHOT
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               af_trigger_bk = frame->shot->ctl.aa.afTrigger;
+               captureIntent_bk = frame->shot->ctl.aa.captureIntent;
+               memcpy(&frame->shot->ctl.aa, &group->fast_ctl.aa,
+                       sizeof(struct camera2_aa_ctl));
+               memcpy(&frame->shot->ctl.scaler, &group->fast_ctl.scaler,
+                       sizeof(struct camera2_scaler_ctl));
+               frame->shot->ctl.aa.afTrigger = af_trigger_bk;
+               frame->shot->ctl.aa.captureIntent = captureIntent_bk;
+       }
+#endif
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               enum aa_capture_intent captureIntent;
+               captureIntent = group->intent_ctl.aa.captureIntent;
+
+               if (captureIntent != AA_CAPTURE_INTENT_CUSTOM) {
+                       frame->shot->ctl.aa.captureIntent = captureIntent;
+                       group->intent_ctl.aa.captureIntent = AA_CAPTURE_INTENT_CUSTOM;
+               }
+       }
+
+       ret = fimc_is_ischain_3aa_tag(device, leader, frame, leader_node);
+       if (ret) {
+               merr("fimc_is_ischain_3aa_tag is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       for (capture_id = 0; capture_id < CAPTURE_NODE_MAX; ++capture_id) {
+               node = &frame->shot_ext->node_group.capture[capture_id];
+               taac = taap = scc = dis = scp = NULL;
+
+               switch (node->vid) {
+               case 0:
+                       break;
+               case FIMC_IS_VIDEO_3A0C_NUM:
+               case FIMC_IS_VIDEO_3A1C_NUM:
+                       taac = group->subdev[ENTRY_3AAC];
+                       break;
+               case FIMC_IS_VIDEO_3A0P_NUM:
+               case FIMC_IS_VIDEO_3A1P_NUM:
+                       taap = group->subdev[ENTRY_3AAP];
+                       break;
+               case FIMC_IS_VIDEO_SCC_NUM:
+                       scc = group->subdev[ENTRY_SCALERC];
+                       break;
+               case FIMC_IS_VIDEO_VDC_NUM:
+                       dis = group->subdev[ENTRY_DIS];
+                       break;
+               case FIMC_IS_VIDEO_SCP_NUM:
+                       scp = group->subdev[ENTRY_SCALERP];
+                       break;
+               default:
+                       merr("capture0 vid(%d) is invalid", device, node->vid);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (taac) {
+                       ret = fimc_is_ischain_3aac_tag(device, taac, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aac_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+
+               if (taap) {
+                       ret = fimc_is_ischain_3aap_tag(device, taap, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_3aap_tag is fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+
+               if (scc) {
+                       ret = fimc_is_ischain_scc_tag(device, scc, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_scc_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+
+               if (dis) {
+                       ret = fimc_is_ischain_dis_tag(device, dis, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_dis_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+
+               if (scp) {
+                       ret = fimc_is_ischain_scp_tag(device, scp, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_scp_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+       }
+
+p_err:
+       if (ret) {
+               merr("3aa shot(index : %d) is skipped(error : %d)", device,
+                               frame->index, ret);
+       } else {
+               framemgr_e_barrier_irqs(framemgr, 0, flags);
+               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+               framemgr_x_barrier_irqr(framemgr, 0, flags);
+               set_bit(REQ_3AA_SHOT, &frame->req_flag);
+               fimc_is_itf_grp_shot(device, group, frame);
+       }
+
+       return ret;
+}
+
+int fimc_is_ischain_isp_callback(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *check_frame)
+{
+       int ret = 0;
+       u32 capture_id, group_id;
+       unsigned long flags;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       struct fimc_is_subdev *leader, *scc, *dis, *dnr, *scp, *fd;
+       struct camera2_node *node, *leader_node;
+
+       BUG_ON(!device);
+       BUG_ON(!check_frame);
+       BUG_ON(device->instance_sensor >= FIMC_IS_MAX_NODES);
+
+#ifdef DBG_STREAMING
+       mdbgd_isp("%s\n", device, __func__);
+#endif
+
+       groupmgr = device->groupmgr;
+       group = &device->group_isp;
+       group_id = GROUP_ID(group->id);
+       leader = &group->leader;
+       dnr = group->subdev[ENTRY_TDNR];
+       fd = group->subdev[ENTRY_LHFD];
+       framemgr = GET_LEADER_FRAMEMGR(leader);
+
+       /*
+          BE CAREFUL WITH THIS
+       1. buffer queue, all compoenent stop, so it's good
+       2. interface callback, all component will be stop until new one is came
+          therefore, i expect lock object is not necessary in here
+       */
+
+       BUG_ON(!framemgr);
+
+       fimc_is_frame_request_head(framemgr, &frame);
+
+       if (unlikely(!frame)) {
+               merr("frame is NULL", device);
+               return -EINVAL;
+       }
+
+       if (unlikely(frame != check_frame)) {
+               merr("frame checking is fail(%X != %X)", device,
+                       (u32)frame, (u32)check_frame);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!frame->shot)) {
+               merr("frame->shot is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* HACK */
+       if ((GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0) &&
+               (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0))
+               group_id = GROUP_ID(GROUP_ID_3A0);
+
+       if (unlikely(!test_bit(FRAME_MAP_MEM, &frame->memory))) {
+               fimc_is_itf_map(device, group_id, frame->dvaddr_shot, frame->shot_size);
+               set_bit(FRAME_MAP_MEM, &frame->memory);
+       }
+
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0) {
+               frame->shot->uctl.scalerUd.taapTargetAddress[0] =
+                       frame->dvaddr_buffer[0];
+               frame->shot->uctl.scalerUd.taapTargetAddress[1] = 0;
+               frame->shot->uctl.scalerUd.taapTargetAddress[2] = 0;
+       }
+
+       frame->shot->ctl.entry.lowIndexParam = 0;
+       frame->shot->ctl.entry.highIndexParam = 0;
+       frame->shot->dm.entry.lowIndexParam = 0;
+       frame->shot->dm.entry.highIndexParam = 0;
+       leader_node = &frame->shot_ext->node_group.leader;
+
+#ifdef ENABLE_SETFILE
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                       GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0) {
+               if (frame->shot_ext->setfile != device->setfile) {
+                       unsigned int setfile = frame->shot_ext->setfile;
+                       ret = fimc_is_ischain_chg_setfile(device, setfile);
+                       if (ret) {
+                               err("fimc_is_ischain_chg_setfile is fail");
+                               goto p_err;
+                       }
+               }
+       }
+#endif
+
+#ifdef ENABLE_DRC
+       if (frame->shot_ext->drc_bypass) {
+               if (test_bit(FIMC_IS_SUBDEV_START, &device->drc.state)) {
+                       ret = fimc_is_ischain_drc_bypass(device, frame, true);
+                       if (ret) {
+                               err("fimc_is_ischain_drc_bypass(1) is fail");
+                               goto p_err;
+                       }
+               }
+       } else {
+               if (!test_bit(FIMC_IS_SUBDEV_START, &device->drc.state)) {
+                       ret = fimc_is_ischain_drc_bypass(device, frame, false);
+                       if (ret) {
+                               err("fimc_is_ischain_drc_bypass(0) is fail");
+                               goto p_err;
+                       }
+               }
+       }
+#endif
+
+#ifdef ENABLE_TDNR
+       if (dnr) {
+               if (frame->shot_ext->dnr_bypass) {
+                       if (test_bit(FIMC_IS_SUBDEV_START, &dnr->state)) {
+                               ret = fimc_is_ischain_dnr_bypass(device, frame, true);
+                               if (ret) {
+                                       merr("dnr_bypass(1) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               } else {
+                       if (!test_bit(FIMC_IS_SUBDEV_START, &dnr->state)) {
+                               ret = fimc_is_ischain_dnr_bypass(device, frame, false);
+                               if (ret) {
+                                       merr("dnr_bypass(0) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               }
+       }
+#endif
+
+#ifdef ENABLE_FD
+       if (fd) {
+               if (frame->shot_ext->fd_bypass) {
+                       if (test_bit(FIMC_IS_SUBDEV_START, &fd->state)) {
+                               ret = fimc_is_ischain_fd_bypass(device, true);
+                               if (ret) {
+                                       merr("fd_bypass(1) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               } else {
+                       if (!test_bit(FIMC_IS_SUBDEV_START, &fd->state)) {
+                               ret = fimc_is_ischain_fd_bypass(device, false);
+                               if (ret) {
+                                       merr("fd_bypass(0) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               }
+       }
+#endif
+
+#ifdef SCALER_CROP_DZOOM
+       crop_width = frame->shot->ctl.scaler.cropRegion[2];
+       /* Digital zoom is not supported in multiple sensor mode */
+       if (crop_width && (crop_width != device->dzoom_width)) {
+               ret = fimc_is_ischain_s_dzoom(device,
+                       frame->shot->ctl.scaler.cropRegion[0],
+                       frame->shot->ctl.scaler.cropRegion[1],
+                       frame->shot->ctl.scaler.cropRegion[2]);
+               if (ret) {
+                       err("fimc_is_ischain_s_dzoom(%d, %d, %d) is fail",
+                               frame->shot->ctl.scaler.cropRegion[0],
+                               frame->shot->ctl.scaler.cropRegion[1],
+                               frame->shot->ctl.scaler.cropRegion[2]);
+                       goto exit;
+               }
+       }
+#endif
+
+       if (!GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)) {
+               ret = fimc_is_ischain_3aa_tag(device, leader, frame, leader_node);
+               if (ret) {
+                       merr("fimc_is_ischain_3aa_tag is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       }
+
+       ret = fimc_is_ischain_isp_tag(device, leader, frame, leader_node);
+       if (ret) {
+               merr("fimc_is_ischain_isp_tag is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       for (capture_id = 0; capture_id < CAPTURE_NODE_MAX; ++capture_id) {
+               node = &frame->shot_ext->node_group.capture[capture_id];
+               scc = dis = scp = NULL;
+
+               switch (node->vid) {
+               case 0:
+                       break;
+               case FIMC_IS_VIDEO_SCC_NUM:
+                       scc = group->subdev[ENTRY_SCALERC];
+                       break;
+               case FIMC_IS_VIDEO_VDC_NUM:
+                       dis = group->subdev[ENTRY_DIS];
+                       break;
+               case FIMC_IS_VIDEO_SCP_NUM:
+                       scp = group->subdev[ENTRY_SCALERP];
+                       break;
+               case FIMC_IS_VIDEO_3A0C_NUM:
+               case FIMC_IS_VIDEO_3A1C_NUM:
+               case FIMC_IS_VIDEO_3A0P_NUM:
+               case FIMC_IS_VIDEO_3A1P_NUM:
+               default:
+                       merr("capture0 vid(%d) is invalid", device, node->vid);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (scc) {
+                       ret = fimc_is_ischain_scc_tag(device, scc, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_scc_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+
+               if (dis) {
+                       ret = fimc_is_ischain_dis_tag(device, dis, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_dis_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+
+               if (scp) {
+                       ret = fimc_is_ischain_scp_tag(device, scp, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_scp_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+       }
+
+#ifdef PRINT_PARAM
+       if (frame->fcount == 1) {
+               fimc_is_hw_memdump(device->interface,
+                       (u32) &device->is_region->parameter,
+                       (u32) &device->is_region->parameter + sizeof(device->is_region->parameter));
+       }
+#endif
+
+p_err:
+       if (ret) {
+               merr("isp shot(index : %d) is skipped(error : %d)",
+                               device, frame->index, ret);
+       } else {
+               framemgr_e_barrier_irqs(framemgr, 0, flags);
+               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+               framemgr_x_barrier_irqr(framemgr, 0, flags);
+               set_bit(REQ_ISP_SHOT, &frame->req_flag);
+               fimc_is_itf_grp_shot(device, group, frame);
+       }
+
+       return ret;
+}
+
+int fimc_is_ischain_dis_callback(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *check_frame)
+{
+       int ret = 0;
+       unsigned long flags;
+       u32 capture_id;
+       bool dis_req, scp_req;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_group *group;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       struct fimc_is_subdev *leader, *dnr, *scp, *fd;
+       struct camera2_node *node;
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s()\n", device, __func__);
+#endif
+
+       BUG_ON(!device);
+       BUG_ON(!check_frame);
+
+       group = &device->group_dis;
+       vctx = group->leader.vctx;
+       framemgr = GET_SRC_FRAMEMGR(vctx);
+       dis_req = scp_req = false;
+       leader = &group->leader;
+       dnr = group->subdev[ENTRY_TDNR];
+       fd = group->subdev[ENTRY_LHFD];
+
+       fimc_is_frame_request_head(framemgr, &frame);
+
+       if (frame != check_frame) {
+               merr("grp_frame is invalid(%X != %X)", device,
+                       (u32)frame, (u32)check_frame);
+               return -EINVAL;
+       }
+
+       frame->shot->ctl.entry.lowIndexParam = 0;
+       frame->shot->ctl.entry.highIndexParam = 0;
+       frame->shot->dm.entry.lowIndexParam = 0;
+       frame->shot->dm.entry.highIndexParam = 0;
+
+#ifdef ENABLE_TDNR
+       if (dnr) {
+               if (frame->shot_ext->dnr_bypass) {
+                       if (test_bit(FIMC_IS_SUBDEV_START, &dnr->state)) {
+                               ret = fimc_is_ischain_dnr_bypass(device, frame, true);
+                               if (ret) {
+                                       merr("dnr_bypass(1) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               } else {
+                       if (!test_bit(FIMC_IS_SUBDEV_START, &dnr->state)) {
+                               ret = fimc_is_ischain_dnr_bypass(device, frame, false);
+                               if (ret) {
+                                       merr("dnr_bypass(0) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               }
+       }
+#endif
+
+#ifdef ENABLE_FD
+       if (fd) {
+               if (frame->shot_ext->fd_bypass) {
+                       if (test_bit(FIMC_IS_SUBDEV_START, &fd->state)) {
+                               ret = fimc_is_ischain_fd_bypass(device, true);
+                               if (ret) {
+                                       merr("fd_bypass(1) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               } else {
+                       if (!test_bit(FIMC_IS_SUBDEV_START, &fd->state)) {
+                               ret = fimc_is_ischain_fd_bypass(device, false);
+                               if (ret) {
+                                       merr("fd_bypass(0) is fail", device);
+                                       goto p_err;
+                               }
+                       }
+               }
+       }
+#endif
+
+       for (capture_id = 0; capture_id < CAPTURE_NODE_MAX; ++capture_id) {
+               node = &frame->shot_ext->node_group.capture[capture_id];
+               scp = NULL;
+
+               switch (node->vid) {
+               case 0:
+                       break;
+               case FIMC_IS_VIDEO_SCP_NUM:
+                       scp = group->subdev[ENTRY_SCALERP];
+                       break;
+               case FIMC_IS_VIDEO_SCC_NUM:
+               case FIMC_IS_VIDEO_VDC_NUM:
+               case FIMC_IS_VIDEO_3A0C_NUM:
+               case FIMC_IS_VIDEO_3A1C_NUM:
+               case FIMC_IS_VIDEO_3A0P_NUM:
+               case FIMC_IS_VIDEO_3A1P_NUM:
+               default:
+                       merr("capture0 vid(%d) is invalid", device, node->vid);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (scp) {
+                       ret = fimc_is_ischain_scp_tag(device, scp, frame, node);
+                       if (ret) {
+                               merr("fimc_is_ischain_scp_tag fail(%d)", device, ret);
+                               goto p_err;
+                       }
+               }
+       }
+
+p_err:
+       if (ret) {
+               err("dis shot(index : %d) is skipped(error : %d)",
+                               frame->index, ret);
+       } else {
+               framemgr_e_barrier_irqs(framemgr, 0, flags);
+               fimc_is_frame_trans_req_to_pro(framemgr, frame);
+               framemgr_x_barrier_irqr(framemgr, 0, flags);
+               set_bit(REQ_DIS_SHOT, &frame->req_flag);
+               fimc_is_itf_grp_shot(device, group, frame);
+       }
+
+       return ret;
+}
+
+int fimc_is_ischain_camctl(struct fimc_is_device_ischain *this,
+       struct fimc_is_frame *frame,
+       u32 fcount)
+{
+       int ret = 0;
+#ifdef ENABLE_SENSOR_DRIVER
+       struct fimc_is_interface *itf;
+       struct camera2_uctl *applied_ctl;
+
+       struct camera2_sensor_ctl *isp_sensor_ctl;
+       struct camera2_lens_ctl *isp_lens_ctl;
+       struct camera2_flash_ctl *isp_flash_ctl;
+
+       u32 index;
+
+#ifdef DBG_STREAMING
+       mdbgd_ischain("%s()\n", device, __func__);
+#endif
+
+       itf = this->interface;
+       isp_sensor_ctl = &itf->isp_peri_ctl.sensorUd.ctl;
+       isp_lens_ctl = &itf->isp_peri_ctl.lensUd.ctl;
+       isp_flash_ctl = &itf->isp_peri_ctl.flashUd.ctl;
+
+       /*lens*/
+       index = (fcount + 0) & SENSOR_MAX_CTL_MASK;
+       applied_ctl = &this->peri_ctls[index];
+       applied_ctl->lensUd.ctl.focusDistance = isp_lens_ctl->focusDistance;
+
+       /*sensor*/
+       index = (fcount + 1) & SENSOR_MAX_CTL_MASK;
+       applied_ctl = &this->peri_ctls[index];
+       applied_ctl->sensorUd.ctl.exposureTime = isp_sensor_ctl->exposureTime;
+       applied_ctl->sensorUd.ctl.frameDuration = isp_sensor_ctl->frameDuration;
+       applied_ctl->sensorUd.ctl.sensitivity = isp_sensor_ctl->sensitivity;
+
+       /*flash*/
+       index = (fcount + 0) & SENSOR_MAX_CTL_MASK;
+       applied_ctl = &this->peri_ctls[index];
+       applied_ctl->flashUd.ctl.flashMode = isp_flash_ctl->flashMode;
+       applied_ctl->flashUd.ctl.firingPower = isp_flash_ctl->firingPower;
+       applied_ctl->flashUd.ctl.firingTime = isp_flash_ctl->firingTime;
+#endif
+       return ret;
+}
+
+int fimc_is_ischain_tag(struct fimc_is_device_ischain *ischain,
+       struct fimc_is_frame *frame)
+{
+       int ret = 0;
+#ifdef ENABLE_SENSOR_DRIVER
+       struct camera2_uctl *applied_ctl;
+       struct timeval curtime;
+       u32 fcount;
+
+       fcount = frame->fcount;
+       applied_ctl = &ischain->peri_ctls[fcount & SENSOR_MAX_CTL_MASK];
+
+       do_gettimeofday(&curtime);
+
+       /* Request */
+       frame->shot->dm.request.frameCount = fcount;
+
+       /* Lens */
+       frame->shot->dm.lens.focusDistance =
+               applied_ctl->lensUd.ctl.focusDistance;
+
+       /* Sensor */
+       frame->shot->dm.sensor.exposureTime =
+               applied_ctl->sensorUd.ctl.exposureTime;
+       frame->shot->dm.sensor.sensitivity =
+               applied_ctl->sensorUd.ctl.sensitivity;
+       frame->shot->dm.sensor.frameDuration =
+               applied_ctl->sensorUd.ctl.frameDuration;
+       frame->shot->dm.sensor.timeStamp =
+               (uint64_t)curtime.tv_sec*1000000 + curtime.tv_usec;
+
+       /* Flash */
+       frame->shot->dm.flash.flashMode =
+               applied_ctl->flashUd.ctl.flashMode;
+       frame->shot->dm.flash.firingPower =
+               applied_ctl->flashUd.ctl.firingPower;
+       frame->shot->dm.flash.firingTime =
+               applied_ctl->flashUd.ctl.firingTime;
+#else
+       struct timespec curtime;
+
+       do_posix_clock_monotonic_gettime(&curtime);
+
+       frame->shot->dm.request.frameCount = frame->fcount;
+       frame->shot->dm.sensor.timeStamp = fimc_is_get_timestamp();
+#endif
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-ischain.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-ischain.h
new file mode 100644 (file)
index 0000000..9c0f281
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_ISCHAIN_H
+#define FIMC_IS_DEVICE_ISCHAIN_H
+
+#include <linux/pm_qos.h>
+
+#include "fimc-is-mem.h"
+#include "fimc-is-subdev-ctrl.h"
+#include "fimc-is-groupmgr.h"
+#include "fimc-is-resourcemgr.h"
+
+#define SENSOR_MAX_CTL                 0x10
+#define SENSOR_MAX_CTL_MASK            (SENSOR_MAX_CTL-1)
+
+#define REPROCESSING_FLAG              0x80000000
+#define REPROCESSING_MASK              0xF0000000
+#define REPROCESSING_SHIFT             28
+#define OTF_3AA_MASK                   0x0F000000
+#define OTF_3AA_SHIFT                  24
+#define SSX_VINDEX_MASK                        0x00FF0000
+#define SSX_VINDEX_SHIFT               16
+#define TAX_VINDEX_MASK                        0x0000FF00
+#define TAX_VINDEX_SHIFT               8
+#define MODULE_MASK                    0x000000FF
+
+#define FIMC_IS_SETFILE_MASK           0x0000FFFF
+#define FIMC_IS_ISP_CRANGE_MASK                0x0F000000
+#define FIMC_IS_ISP_CRANGE_SHIFT       24
+#define FIMC_IS_SCC_CRANGE_MASK                0x00F00000
+#define FIMC_IS_SCC_CRANGE_SHIFT       20
+#define FIMC_IS_SCP_CRANGE_MASK                0x000F0000
+#define FIMC_IS_SCP_CRANGE_SHIFT       16
+#define FIMC_IS_CRANGE_FULL            0
+#define FIMC_IS_CRANGE_LIMITED         1
+
+#if defined(CONFIG_SOC_EXYNOS5422)
+#define FIMC_IS_SPI_PINNAME "14000000.pinctrl"
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+#define FIMC_IS_SPI_PINNAME "14cc0000.pinctrl"
+#endif
+#define FIMC_IS_SPI_OUTPUT     1
+#define FIMC_IS_SPI_FUNC       2
+
+/*global state*/
+enum fimc_is_ischain_state {
+       FIMC_IS_ISCHAIN_OPEN,
+       FIMC_IS_ISCHAIN_LOADED,
+       FIMC_IS_ISCHAIN_POWER_ON,
+       FIMC_IS_ISCHAIN_OPEN_SENSOR,
+       FIMC_IS_ISHCAIN_START,
+       FIMC_IS_ISCHAIN_REPROCESSING,
+};
+
+enum fimc_is_camera_device {
+       CAMERA_SINGLE_REAR,
+       CAMERA_SINGLE_FRONT,
+};
+
+#ifdef CONFIG_COMPANION_USE
+enum fimc_is_companion_sensor {
+       COMPANION_SENSOR_2P2 = 1,
+       COMPANION_SENSOR_IMX240 = 2,
+};
+#endif
+
+struct fimc_is_from_info {
+       u32             bin_start_addr;
+       u32             bin_end_addr;
+       u32             oem_start_addr;
+       u32             oem_end_addr;
+       u32             awb_start_addr;
+       u32             awb_end_addr;
+       u32             shading_start_addr;
+       u32             shading_end_addr;
+       u32             setfile_start_addr;
+       u32             setfile_end_addr;
+#ifdef CONFIG_COMPANION_USE
+       u32             concord_master_setfile_start_addr;
+       u32             concord_master_setfile_end_addr;
+       u32             concord_mode_setfile_start_addr;
+       u32             concord_mode_setfile_end_addr;
+       u32             lsc_gain_start_addr;
+       u32             lsc_gain_end_addr;
+       u32             pdaf_start_addr;
+       u32             pdaf_end_addr;
+       u32             coefficient_cal_start_addr;
+       u32             coefficient_cal_end_addr;
+       u32             pdaf_cal_start_addr;
+       u32             pdaf_cal_end_addr;
+       u32             concord_cal_start_addr;
+       u32             concord_cal_end_addr;
+       u32             concord_bin_start_addr;
+       u32             concord_bin_end_addr;
+       u32             lsc_i0_gain_addr;
+       u32             lsc_j0_gain_addr;
+       u32             lsc_a_gain_addr;
+       u32             lsc_k4_gain_addr;
+       u32             lsc_scale_gain_addr;
+       u32             wcoefficient1_addr;
+       u32             coef1_start;
+       u32             coef1_end;
+       u32             coef2_start;
+       u32             coef2_end;
+       u32             coef3_start;
+       u32             coef3_end;
+       u32             coef4_start;
+       u32             coef4_end;
+       u32             coef5_start;
+       u32             coef5_end;
+       u32             coef6_start;
+       u32             coef6_end;
+       u32             af_inf_addr;
+       u32             af_macro_addr;
+       u32             lsc_gain_crc_addr;
+       u32             pdaf_crc_addr;
+       u32             coef1_crc_addr;
+       u32             coef2_crc_addr;
+       u32             coef3_crc_addr;
+       u32             coef4_crc_addr;
+       u32             coef5_crc_addr;
+       u32             coef6_crc_addr;
+       char            concord_header_ver[12];
+       bool            is_c1_caldata_read;
+       char            load_c1_fw_name[50];
+       char            load_c1_mastersetf_name[50];
+       char            load_c1_modesetf_name[50];
+       int             sensor_id;
+#endif
+       char            header_ver[12];
+       char            cal_map_ver[4];
+       char            setfile_ver[7];
+       char            oem_ver[12];
+       char            awb_ver[12];
+       char            shading_ver[12];
+       char            load_fw_name[50];
+       char            load_setfile_name[50];
+       char            project_name[9];
+       bool            is_caldata_read;
+};
+
+#ifdef CONFIG_OIS_USE
+struct fimc_is_ois_info {
+       char            header_ver[7];
+       char            load_fw_name[50];
+};
+#endif
+
+struct fimc_is_ishcain_mem {
+       /* buffer base */
+       dma_addr_t              base;
+       /* total length */
+       size_t                  size;
+       /* buffer base */
+       dma_addr_t              vaddr_base;
+       /* current addr */
+       dma_addr_t              vaddr_curr;
+       void                    *fw_cookie;
+
+       /* fw memory base */
+       u32                     dvaddr;
+       u32                     kvaddr;
+       /* debug part of fw memory */
+       u32                     dvaddr_debug;
+       u32                     kvaddr_debug;
+       /* is region part of fw memory */
+       u32                     offset_region;
+       u32                     dvaddr_region;
+       u32                     kvaddr_region;
+       /* shared part of is region */
+       u32                     offset_shared;
+       u32                     dvaddr_shared;
+       u32                     kvaddr_shared;
+       /* internal memory for ODC */
+       u32                     dvaddr_odc;
+       u32                     kvaddr_odc;
+       /* internal memory for DIS */
+       u32                     dvaddr_dis;
+       u32                     kvaddr_dis;
+       /* internal memory for 3DNR */
+       u32                     dvaddr_3dnr;
+       u32                     kvaddr_3dnr;
+
+       struct is_region        *is_region;
+};
+
+struct fimc_is_device_ischain {
+       struct platform_device                  *pdev;
+       struct exynos_platform_fimc_is          *pdata;
+       void __iomem                            *regs;
+
+       struct fimc_is_resourcemgr              *resourcemgr;
+       struct fimc_is_groupmgr                 *groupmgr;
+       struct fimc_is_interface                *interface;
+       struct fimc_is_mem                      *mem;
+
+       u32                                     instance;
+       u32                                     instance_sensor;
+       u32                                     module;
+       struct fimc_is_ishcain_mem              imemory;
+       struct fimc_is_from_info                finfo;
+       struct fimc_is_from_info                pinfo;
+       struct is_region                        *is_region;
+
+       bool                                    force_down;
+       unsigned long                           state;
+       struct mutex                            mutex_state;
+
+       u32                                     dzoom_width;
+       u32                                     bds_width;
+       u32                                     bds_height;
+       u32                                     setfile;
+       u32                                     color_range;
+
+       struct camera2_sm                       capability;
+       struct camera2_uctl                     cur_peri_ctl;
+       struct camera2_uctl                     peri_ctls[SENSOR_MAX_CTL];
+
+       /*isp margin*/
+       u32                                     margin_left;
+       u32                                     margin_right;
+       u32                                     margin_width;
+       u32                                     margin_top;
+       u32                                     margin_bottom;
+       u32                                     margin_height;
+
+       /* chain0 : isp ~ scc */
+       struct fimc_is_group                    group_3aa;
+       struct fimc_is_subdev                   taac;
+       struct fimc_is_subdev                   taap;
+
+       u32                                     taa_size_forceset;
+       u32                                     taa_size_changed_fcount;
+
+       struct fimc_is_group                    group_isp;
+       u32                                     chain0_width;
+       u32                                     chain0_height;
+       struct fimc_is_subdev                   drc;
+
+       u32                                     isp_size_forceset;
+       u32                                     isp_size_changed_fcount;
+
+       /* chain1 : scc ~ dis */
+       struct fimc_is_subdev                   scc;
+       u32                                     chain1_width;
+       u32                                     chain1_height;
+       u32                                     crop_x;
+       u32                                     crop_y;
+       u32                                     crop_width;
+       u32                                     crop_height;
+       struct fimc_is_subdev                   dis;
+       u32                                     dis_width;
+       u32                                     dis_height;
+
+       /* chain2 : dis ~ scp */
+       struct fimc_is_group                    group_dis;
+       u32                                     chain2_width;
+       u32                                     chain2_height;
+       struct fimc_is_subdev                   dnr;
+
+       /* chain3 : scp ~ fd */
+       struct fimc_is_subdev                   scp;
+       u32                                     chain3_width;
+       u32                                     chain3_height;
+       struct fimc_is_subdev                   fd;
+
+       u32                                     private_data;
+       struct fimc_is_device_sensor            *sensor;
+       struct pm_qos_request                   user_qos;
+};
+
+/*global function*/
+int fimc_is_ischain_probe(struct fimc_is_device_ischain *device,
+       struct fimc_is_interface *interface,
+       struct fimc_is_resourcemgr *resourcemgr,
+       struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_mem *mem,
+       struct platform_device *pdev,
+       u32 instance,
+       u32 regs);
+int fimc_is_ischain_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx,
+       struct fimc_is_minfo *minfo);
+int fimc_is_ischain_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_init_wrap(struct fimc_is_device_ischain *device,
+       u32 input);
+int fimc_is_ischain_g_capability(struct fimc_is_device_ischain *this,
+       u32 user_ptr);
+int fimc_is_ischain_print_status(struct fimc_is_device_ischain *this);
+void fimc_is_ischain_meta_invalid(struct fimc_is_frame *frame);
+
+/* 3AA subdev */
+int fimc_is_ischain_3aa_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_3aa_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_3aa_s_input(struct fimc_is_device_ischain *device,
+       u32 input);
+int fimc_is_ischain_3aa_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue);
+int fimc_is_ischain_3aa_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue);
+int fimc_is_ischain_3aa_reqbufs(struct fimc_is_device_ischain *device,
+       u32 count);
+int fimc_is_ischain_3aa_s_format(struct fimc_is_device_ischain *device,
+       u32 width, u32 height);
+int fimc_is_ischain_3aa_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index);
+int fimc_is_ischain_3aa_buffer_finish(struct fimc_is_device_ischain *device,
+       u32 index);
+
+/* isp subdev */
+int fimc_is_ischain_isp_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue);
+int fimc_is_ischain_isp_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue);
+int fimc_is_ischain_isp_reqbufs(struct fimc_is_device_ischain *device,
+       u32 count);
+int fimc_is_ischain_isp_s_format(struct fimc_is_device_ischain *this,
+       u32 width, u32 height);
+int fimc_is_ischain_isp_s_input(struct fimc_is_device_ischain *this,
+       u32 input);
+int fimc_is_ischain_isp_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index);
+int fimc_is_ischain_isp_buffer_finish(struct fimc_is_device_ischain *this,
+       u32 index);
+
+/*scc subdev*/
+/*scp subdev*/
+int fimc_is_ischain_scp_s_format(struct fimc_is_device_ischain *device,
+       u32 pixelformat, u32 width, u32 height);
+
+/* vdisc subdev */
+int fimc_is_ischain_dis_start(struct fimc_is_device_ischain *this,
+       bool bypass);
+int fimc_is_ischain_dis_stop(struct fimc_is_device_ischain *this);
+int fimc_is_ischain_vdc_s_format(struct fimc_is_device_ischain *this,
+       u32 width, u32 height);
+
+/* vdiso subdev */
+int fimc_is_ischain_vdo_open(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_vdo_close(struct fimc_is_device_ischain *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_ischain_vdo_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue);
+int fimc_is_ischain_vdo_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *leader,
+       struct fimc_is_queue *queue);
+int fimc_is_ischain_vdo_s_format(struct fimc_is_device_ischain *this,
+       u32 width, u32 height);
+int fimc_is_ischain_vdo_buffer_queue(struct fimc_is_device_ischain *device,
+       struct fimc_is_queue *queue,
+       u32 index);
+int fimc_is_ischain_vdo_buffer_finish(struct fimc_is_device_ischain *this,
+       u32 index);
+
+/*special api for sensor*/
+int fimc_is_ischain_3aa_callback(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame);
+int fimc_is_ischain_isp_callback(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame);
+int fimc_is_ischain_dis_callback(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame);
+int fimc_is_ischain_camctl(struct fimc_is_device_ischain *this,
+       struct fimc_is_frame *frame,
+       u32 fcount);
+int fimc_is_ischain_tag(struct fimc_is_device_ischain *ischain,
+       struct fimc_is_frame *frame);
+
+int fimc_is_itf_stream_on(struct fimc_is_device_ischain *this);
+int fimc_is_itf_stream_off(struct fimc_is_device_ischain *this);
+int fimc_is_itf_process_start(struct fimc_is_device_ischain *device,
+       u32 group);
+int fimc_is_itf_process_stop(struct fimc_is_device_ischain *device,
+       u32 group);
+int fimc_is_itf_force_stop(struct fimc_is_device_ischain *device,
+       u32 group);
+int fimc_is_itf_map(struct fimc_is_device_ischain *device,
+       u32 group, u32 shot_addr, u32 shot_size);
+int fimc_is_itf_i2c_lock(struct fimc_is_device_ischain *this,
+       int i2c_clk, bool lock);
+
+extern const struct fimc_is_queue_ops fimc_is_ischain_3aa_ops;
+extern const struct fimc_is_queue_ops fimc_is_ischain_isp_ops;
+extern const struct fimc_is_queue_ops fimc_is_ischain_vdo_ops;
+extern const struct fimc_is_queue_ops fimc_is_ischain_sub_ops;
+
+int fimc_is_itf_power_down(struct fimc_is_interface *interface);
+int fimc_is_ischain_power(struct fimc_is_device_ischain *this, int on);
+void fimc_is_ischain_savefirm(struct fimc_is_device_ischain *this);
+
+#define IS_ISCHAIN_OTF(device)                         \
+       (test_bit(FIMC_IS_GROUP_OTF_INPUT, &(device)->group_3aa.state))
+#define IS_EQUAL_COORD(i, o)                           \
+       (((i)[0] != (o)[0]) || ((i)[1] != (o)[1]) ||    \
+        ((i)[2] != (o)[2]) || ((i)[3] != (o)[3]))
+#define IS_NULL_COORD(c)                               \
+       (!(c)[0] && !(c)[1] && !(c)[2] && !(c)[3])
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-ois.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-ois.c
new file mode 100644 (file)
index 0000000..f1bbe3f
--- /dev/null
@@ -0,0 +1,1535 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#include <mach/exynos-fimc-is-sensor.h>
+#include <mach/pinctrl-samsung.h>
+#ifdef CONFIG_OIS_FW_UPDATE_THREAD_USE
+#include <linux/kthread.h>
+#endif
+
+#include "fimc-is-core.h"
+#include "fimc-is-interface.h"
+#include "fimc-is-sec-define.h"
+#include "fimc-is-device-ischain.h"
+#include "fimc-is-dt.h"
+#include "fimc-is-device-ois.h"
+#ifdef CONFIG_AF_HOST_CONTROL
+#include "fimc-is-device-af.h"
+#endif
+
+#define FIMC_IS_OIS_SDCARD_PATH                "/data/media/0/"
+#define FIMC_IS_OIS_DEV_NAME           "exynos-fimc-is-ois"
+#define FIMC_OIS_FW_NAME_SEC           "fimc_is_ois_63B.bin"
+#define FIMC_OIS_FW_NAME_DOM           "fimc_is_ois_63A.bin"
+#define OIS_BOOT_FW_SIZE       (1024 * 4)
+#define OIS_PROG_FW_SIZE       (1024 * 24)
+#define FW_GYRO_SENSOR         0
+#define FW_DRIVER_IC           1
+#define FW_CORE_VERSION                2
+#define FW_RELEASE_MONTH               3
+#define FW_RELEASE_COUNT               4
+#define FW_TRANS_SIZE          256
+#define OIS_VER_OFFSET 14
+#define OIS_BIN_LEN            28672
+#define OIS_BIN_HEADER         28658
+#define OIS_FW_HEADER_SIZE             6
+static u8 bootCode[OIS_BOOT_FW_SIZE] = {0,};
+static u8 progCode[OIS_PROG_FW_SIZE] = {0,};
+
+static struct fimc_is_ois_info ois_minfo;
+static struct fimc_is_ois_info ois_pinfo;
+static struct fimc_is_ois_info ois_uinfo;
+static struct fimc_is_ois_exif ois_exif_data;
+static bool fw_sdcard;
+static bool not_crc_bin;
+#ifdef CONFIG_OIS_FW_UPDATE_THREAD_USE
+static struct task_struct *ois_ts;
+#endif
+
+static void fimc_is_ois_i2c_config(struct i2c_client *client, bool onoff)
+{
+       struct pinctrl *pinctrl_i2c = NULL;
+       struct device *i2c_dev = client->dev.parent->parent;
+       struct fimc_is_device_ois *ois_device = i2c_get_clientdata(client);
+
+       if (ois_device->ois_hsi2c_status != onoff) {
+               info("%s : ois_hsi2c_stauts(%d),onoff(%d)\n",__func__,
+                       ois_device->ois_hsi2c_status, onoff);
+
+               if (onoff) {
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 0));
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 0));
+
+                       pinctrl_i2c = devm_pinctrl_get_select(i2c_dev, "on_i2c");
+                       if (IS_ERR_OR_NULL(pinctrl_i2c)) {
+                               printk(KERN_ERR "%s: Failed to configure i2c pin\n", __func__);
+                       } else {
+                               devm_pinctrl_put(pinctrl_i2c);
+                       }
+               } else {
+                       pinctrl_i2c = devm_pinctrl_get_select(i2c_dev, "off_i2c");
+                       if (IS_ERR_OR_NULL(pinctrl_i2c)) {
+                               printk(KERN_ERR "%s: Failed to configure i2c pin\n", __func__);
+                       } else {
+                               devm_pinctrl_put(pinctrl_i2c);
+                       }
+
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+                       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, 2));
+               }
+               ois_device->ois_hsi2c_status = onoff;
+       }
+}
+
+int fimc_is_ois_i2c_read(struct i2c_client *client, u16 addr, u8 *data)
+{
+       int err;
+       u8 txbuf[2], rxbuf[1];
+       struct i2c_msg msg[2];
+
+       *data = 0;
+       txbuf[0] = (addr & 0xff00) >> 8;
+       txbuf[1] = (addr & 0xff);
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = txbuf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 1;
+       msg[1].buf = rxbuf;
+
+       err = i2c_transfer(client->adapter, msg, 2);
+       if (unlikely(err != 2)) {
+               err("%s: register read fail err = %d\n", __func__, err);
+               return -EIO;
+       }
+
+       *data = rxbuf[0];
+       return 0;
+}
+
+int fimc_is_ois_i2c_write(struct i2c_client *client ,u16 addr, u8 data)
+{
+        int retries = I2C_RETRY_COUNT;
+        int ret = 0, err = 0;
+        u8 buf[3] = {0,};
+        struct i2c_msg msg = {
+                .addr   = client->addr,
+                .flags  = 0,
+                .len    = 3,
+                .buf    = buf,
+        };
+
+        buf[0] = (addr & 0xff00) >> 8;
+        buf[1] = addr & 0xff;
+        buf[2] = data;
+
+#if 0
+        pr_info("%s : W(0x%02X%02X %02X)\n",__func__, buf[0], buf[1], buf[2]);
+#endif
+
+        do {
+                ret = i2c_transfer(client->adapter, &msg, 1);
+                if (likely(ret == 1))
+                        break;
+
+                usleep_range(10000,11000);
+                err = ret;
+        } while (--retries > 0);
+
+        /* Retry occured */
+        if (unlikely(retries < I2C_RETRY_COUNT)) {
+                err("i2c_write: error %d, write (%04X, %04X), retry %d\n",
+                        err, addr, data, I2C_RETRY_COUNT - retries);
+        }
+
+        if (unlikely(ret != 1)) {
+                err("I2C does not work\n\n");
+                return -EIO;
+        }
+
+        return 0;
+}
+
+int fimc_is_ois_i2c_write_multi(struct i2c_client *client ,u16 addr, u8 *data, size_t size)
+{
+       int retries = I2C_RETRY_COUNT;
+       int ret = 0, err = 0, i = 0;
+       u8 buf[258] = {0,};
+       struct i2c_msg msg = {
+                .addr   = client->addr,
+                .flags  = 0,
+                .len    = size,
+                .buf    = buf,
+       };
+
+       buf[0] = (addr & 0xFF00) >> 8;
+       buf[1] = addr & 0xFF;
+
+       for (i = 0; i < size - 2; i++) {
+               buf[i + 2] = *(data + i);
+       }
+#if 0
+        pr_info("OISLOG %s : W(0x%02X%02X%02X)\n", __func__, buf[0], buf[1], buf[2]);
+#endif
+        do {
+                ret = i2c_transfer(client->adapter, &msg, 1);
+                if (likely(ret == 1))
+                        break;
+
+                usleep_range(10000,11000);
+                err = ret;
+        } while (--retries > 0);
+
+        /* Retry occured */
+        if (unlikely(retries < I2C_RETRY_COUNT)) {
+                err("i2c_write: error %d, write (%04X, %04X), retry %d\n",
+                        err, addr, *data, I2C_RETRY_COUNT - retries);
+        }
+
+        if (unlikely(ret != 1)) {
+                err("I2C does not work\n\n");
+                return -EIO;
+       }
+
+        return 0;
+}
+
+static int fimc_is_ois_i2c_read_multi(struct i2c_client *client, u16 addr, u8 *data, size_t size)
+{
+       int err;
+       u8 rxbuf[256], txbuf[2];
+       struct i2c_msg msg[2];
+
+       txbuf[0] = (addr & 0xff00) >> 8;
+       txbuf[1] = (addr & 0xff);
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = txbuf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = size;
+       msg[1].buf = rxbuf;
+
+       err = i2c_transfer(client->adapter, msg, 2);
+       if (unlikely(err != 2)) {
+               pr_err("%s: register read fail\n", __func__);
+               return -EIO;
+       }
+
+       memcpy(data, rxbuf, size);
+       return 0;
+}
+
+int fimc_is_ois_gpio_on(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!pdata->gpio_cfg) {
+               err("gpio_cfg is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->gpio_cfg(device->pdev, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON);
+       if (ret) {
+               err("gpio_cfg is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_ois_gpio_off(struct fimc_is_device_companion *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!pdata->gpio_cfg) {
+               err("gpio_cfg is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->gpio_cfg(device->pdev, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF);
+       if (ret) {
+               err("gpio_cfg is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+void fimc_is_ois_enable(struct fimc_is_core *core)
+{
+       int ret = 0;
+
+       pr_info("%s : E\n", __FUNCTION__);
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x02, 0x00);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x00, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+       pr_info("%s : X\n", __FUNCTION__);
+}
+
+int fimc_is_ois_sine_mode(struct fimc_is_core *core, int mode)
+{
+       int ret = 0;
+
+       pr_info("%s : E\n", __FUNCTION__);
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       if (mode == OPTICAL_STABILIZATION_MODE_SINE_X) {
+               ret = fimc_is_ois_i2c_write(core->client1, 0x18, 0x01);
+       } else if (mode == OPTICAL_STABILIZATION_MODE_SINE_Y) {
+               ret = fimc_is_ois_i2c_write(core->client1, 0x18, 0x02);
+       }
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x19, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x1A, 0x1E);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x02, 0x03);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       msleep(20);
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x00, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, false);
+       }
+       pr_info("%s : X\n", __FUNCTION__);
+
+       return ret;
+}
+EXPORT_SYMBOL(fimc_is_ois_sine_mode);
+
+void fimc_is_ois_version(struct fimc_is_core *core)
+{
+       int ret = 0;
+       u8 val_c = 0, val_d = 0;
+       u16 version = 0;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x00FC, &val_c);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x00FD, &val_d);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       version = (val_d << 8) | val_c;
+       pr_info("OIS version = 0x%04x\n", version);
+}
+
+void fimc_is_ois_offset_test(struct fimc_is_core *core, long *raw_data_x, long *raw_data_y)
+{
+       int ret = 0, i = 0;
+       u8 val = 0, x = 0, y = 0;
+       int x_sum = 0, y_sum = 0, sum = 0;
+       int retries = 0, avg_count = 20;
+
+       pr_info("%s : E\n", __FUNCTION__);
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x0014, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       retries = avg_count;
+       do {
+               ret = fimc_is_ois_i2c_read(core->client1, 0x0014, &val);
+               if (ret != 0) {
+                       break;
+               }
+               msleep(10);
+               if (--retries < 0) {
+                       err("Read register failed!!!!, data = 0x%04x\n", val);
+                       break;
+               }
+       } while (val);
+
+       sum = 0;
+       retries = avg_count;
+       for (i = 0; i < retries; retries--) {
+               fimc_is_ois_i2c_read(core->client1, 0x0248, &val);
+               x = val;
+               fimc_is_ois_i2c_read(core->client1, 0x0249, &val);
+               x_sum = (val << 8) | x;
+               if (x_sum > 0x7FFF) {
+                       x_sum = -((x_sum ^ 0xFFFF) + 1);
+               }
+               sum += x_sum;
+       }
+       sum = sum * 10 / avg_count;
+       *raw_data_x = sum * 1000 / 175 / 10;
+
+       retries = avg_count;
+       for (i = 0; i < retries; retries--) {
+               fimc_is_ois_i2c_read(core->client1, 0x024A, &val);
+               y = val;
+               fimc_is_ois_i2c_read(core->client1, 0x024B, &val);
+               y_sum = (val << 8) | y;
+               if (y_sum > 0x7FFF) {
+                       y_sum = -((y_sum ^ 0xFFFF) + 1);
+               }
+               sum += y_sum;
+       }
+       sum = sum * 10 / avg_count;
+       *raw_data_y = sum * 1000 / 175 / 10;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       fimc_is_ois_version(core);
+       pr_info("%s : X\n", __FUNCTION__);
+       return;
+}
+
+void fimc_is_ois_get_offset_data(struct fimc_is_core *core, long *raw_data_x, long *raw_data_y)
+{
+       int i = 0;
+       u8 val = 0, x = 0, y = 0;
+       int x_sum = 0, y_sum = 0, sum = 0;
+       int retries = 0, avg_count = 20;
+
+       pr_info("%s : E\n", __FUNCTION__);
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       retries = avg_count;
+       for (i = 0; i < retries; retries--) {
+               fimc_is_ois_i2c_read(core->client1, 0x0248, &val);
+               x = val;
+               fimc_is_ois_i2c_read(core->client1, 0x0249, &val);
+               x_sum = (val << 8) | x;
+               if (x_sum > 0x7FFF) {
+                       x_sum = -((x_sum ^ 0xFFFF) + 1);
+               }
+               sum += x_sum;
+       }
+       sum = sum * 10 / avg_count;
+       *raw_data_x = sum * 1000 / 175 / 10;
+
+       sum = 0;
+       retries = avg_count;
+       for (i = 0; i < retries; retries--) {
+               fimc_is_ois_i2c_read(core->client1, 0x024A, &val);
+               y = val;
+               fimc_is_ois_i2c_read(core->client1, 0x024B, &val);
+               y_sum = (val << 8) | y;
+               if (y_sum > 0x7FFF) {
+                       y_sum = -((y_sum ^ 0xFFFF) + 1);
+               }
+               sum += y_sum;
+       }
+       sum = sum * 10 / avg_count;
+       *raw_data_y = sum * 1000 / 175 / 10;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       fimc_is_ois_version(core);
+       pr_info("%s : X\n", __FUNCTION__);
+       return;
+}
+
+int fimc_is_ois_self_test(struct fimc_is_core *core)
+{
+       int ret = 0;
+       u8 val = 0;
+       int retries = 20;
+
+       pr_info("%s : E\n", __FUNCTION__);
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x0014, 0x08);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       do {
+               ret = fimc_is_ois_i2c_read(core->client1, 0x0014, &val);
+               if (ret != 0) {
+                       val = -EIO;
+                       break;
+               }
+               msleep(10);
+               if (--retries < 0) {
+                       err("Read register failed!!!!, data = 0x%04x\n", val);
+                       break;
+               }
+       } while (val);
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0004, &val);
+       if (ret != 0) {
+               val = -EIO;
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       pr_info("%s(%d) : X\n", __FUNCTION__, val);
+       return (int)val;
+}
+
+bool fimc_is_ois_diff_test(struct fimc_is_core *core, int *x_diff, int *y_diff)
+{
+       int ret = 0;
+       u8 val = 0, x = 0, y = 0;
+       u16 x_min = 0, y_min = 0, x_max = 0, y_max = 0;
+       int retries = 20, default_diff = 1100;
+       u8 read_x[2], read_y[2];
+
+       pr_info("(%s) : E\n", __FUNCTION__);
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+#ifdef CONFIG_AF_HOST_CONTROL
+       fimc_is_af_move_lens(core);
+       msleep(30);
+#endif
+       ret = fimc_is_ois_i2c_read_multi(core->client1, 0x021A, read_x, 2);
+       ret |= fimc_is_ois_i2c_read_multi(core->client1, 0x021C, read_y, 2);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write_multi(core->client1, 0x0022, read_x, 4);
+       ret |= fimc_is_ois_i2c_write_multi(core->client1, 0x0024, read_y, 4);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0002, 0x02);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0000, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+       msleep(400);
+       pr_info("(%s) : OIS Position = Center\n", __FUNCTION__);
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x0000, 0x00);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       do {
+               ret = fimc_is_ois_i2c_read(core->client1, 0x0001, &val);
+               if (ret != 0) {
+                       break;
+               }
+               msleep(10);
+               if (--retries < 0) {
+                       err("Read register failed!!!!, data = 0x%04x\n", val);
+                       break;
+               }
+       } while (val != 1);
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x0034, 0x64);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0230, 0x64);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0231, 0x00);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0232, 0x64);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0233, 0x00);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0034, &val);
+       err("OIS[read_val_0x0034::0x%04x]\n", val);
+       ret |= fimc_is_ois_i2c_read(core->client1, 0x0230, &val);
+       err("OIS[read_val_0x0230::0x%04x]\n", val);
+       ret |= fimc_is_ois_i2c_read(core->client1, 0x0231, &val);
+       err("OIS[read_val_0x0231::0x%04x]\n", val);
+       ret |= fimc_is_ois_i2c_read(core->client1, 0x0232, &val);
+       err("OIS[read_val_0x0232::0x%04x]\n", val);
+       ret |= fimc_is_ois_i2c_read(core->client1, 0x0233, &val);
+       err("OIS[read_val_0x0233::0x%04x]\n", val);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write(core->client1, 0x020E, 0x00);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x020F, 0x00);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0210, 0x50);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0211, 0x50);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+       ret = fimc_is_ois_i2c_write(core->client1, 0x0013, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+#if 0
+       ret = fimc_is_ois_i2c_write(core->client1, 0x0012, 0x01);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       retries = 30;
+       do { //polarity check
+               ret = fimc_is_ois_i2c_read(core->client1, 0x0012, &val);
+               if (ret != 0) {
+                       break;
+               }
+               msleep(100);
+               if (--retries < 0) {
+                       err("Polarity check is not done or not [read_val_0x0012::0x%04x]\n", val);
+                       break;
+               }
+       } while (val);
+       fimc_is_ois_i2c_read(core->client1, 0x0200, &val);
+       err("OIS[read_val_0x0200::0x%04x]\n", val);
+#endif
+
+       retries = 120;
+       do {
+               ret = fimc_is_ois_i2c_read(core->client1, 0x0013, &val);
+               if (ret != 0) {
+                       break;
+               }
+               msleep(100);
+               if (--retries < 0) {
+                       err("Read register failed!!!!, data = 0x%04x\n", val);
+                       break;
+               }
+       } while (val);
+
+       fimc_is_ois_i2c_read(core->client1, 0x0212, &val);
+       x = val;
+       fimc_is_ois_i2c_read(core->client1, 0x0213, &val);
+       x_max = (val << 8) | x;
+       fimc_is_ois_i2c_read(core->client1, 0x0214, &val);
+       x = val;
+       fimc_is_ois_i2c_read(core->client1, 0x0215, &val);
+       x_min = (val << 8) | x;
+
+       fimc_is_ois_i2c_read(core->client1, 0x0216, &val);
+       y = val;
+       fimc_is_ois_i2c_read(core->client1, 0x0217, &val);
+       y_max = (val << 8) | y;
+       fimc_is_ois_i2c_read(core->client1, 0x0218, &val);
+       y = val;
+       fimc_is_ois_i2c_read(core->client1, 0x0219, &val);
+       y_min = (val << 8) | y;
+
+       *x_diff = abs(x_max - x_min);
+       *y_diff = abs(y_max - y_min);
+
+       pr_info("(%s) : X (default_diff:%d)(%d,%d)\n", __FUNCTION__,
+                       default_diff, *x_diff, *y_diff);
+
+       ret = fimc_is_ois_i2c_read_multi(core->client1, 0x021A, read_x, 2);
+       ret |= fimc_is_ois_i2c_read_multi(core->client1, 0x021C, read_y, 2);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_write_multi(core->client1, 0x0022, read_x, 4);
+       ret |= fimc_is_ois_i2c_write_multi(core->client1, 0x0024, read_y, 4);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0002, 0x02);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0000, 0x01);
+       msleep(400);
+       ret |= fimc_is_ois_i2c_write(core->client1, 0x0000, 0x00);
+       if (ret) {
+               err("i2c write fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       if (*x_diff > default_diff  && *y_diff > default_diff) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
+u16 fimc_is_ois_calc_checksum(u8 *data, int size)
+{
+       int i = 0;
+       u16 result = 0;
+
+       for(i = 0; i < size; i += 2) {
+               result = result + (0xFFFF & (((*(data + i + 1)) << 8) | (*(data + i))));
+       }
+
+       return result;
+}
+
+void fimc_is_ois_exif_data(struct fimc_is_core *core)
+{
+       int ret = 0;
+       u8 error_reg[2], status_reg;
+       u16 error_sum;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0004, &error_reg[0]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0005, &error_reg[1]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       error_sum = (error_reg[1] << 8) | error_reg[0];
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0001, &status_reg);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       ois_exif_data.error_data = error_sum;
+       ois_exif_data.status_data = status_reg;
+
+       return;
+}
+
+int fimc_is_ois_get_exif_data(struct fimc_is_ois_exif **exif_info)
+{
+       *exif_info = &ois_exif_data;
+       return 0;
+}
+
+void fimc_is_ois_fw_version(struct fimc_is_core *core)
+{
+       int ret = 0;
+       char version[7] = {0, };
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x00F9, &version[0]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x00F8, &version[1]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x007C, &version[2]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x007D, &version[3]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x007E, &version[4]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x007F, &version[5]);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       memcpy(ois_minfo.header_ver, version, 6);
+       core->ois_ver_read = true;
+
+       return;
+}
+
+int fimc_is_ois_get_module_version(struct fimc_is_ois_info **minfo)
+{
+       *minfo = &ois_minfo;
+       return 0;
+}
+
+int fimc_is_ois_get_phone_version(struct fimc_is_ois_info **pinfo)
+{
+       *pinfo = &ois_pinfo;
+       return 0;
+}
+
+int fimc_is_ois_get_user_version(struct fimc_is_ois_info **uinfo)
+{
+       *uinfo = &ois_uinfo;
+       return 0;
+}
+
+
+int fimc_is_ois_fw_revision(char *fw_ver)
+{
+       int revision = 0;
+       revision = revision + ((int)fw_ver[FW_RELEASE_MONTH] - 64) * 100;
+       revision = revision + ((int)fw_ver[FW_RELEASE_COUNT] - 48) * 10;
+       revision = revision + (int)fw_ver[FW_RELEASE_COUNT + 1] - 48;
+
+       return revision;
+}
+
+bool fimc_is_ois_version_compare(char *fw_ver1, char *fw_ver2, char *fw_ver3)
+{
+       if (fw_ver1[FW_GYRO_SENSOR] != fw_ver2[FW_GYRO_SENSOR]
+               || fw_ver1[FW_DRIVER_IC] != fw_ver2[FW_DRIVER_IC]
+               || fw_ver1[FW_CORE_VERSION] != fw_ver2[FW_CORE_VERSION]) {
+               return false;
+       }
+
+       if (fw_ver2[FW_GYRO_SENSOR] != fw_ver3[FW_GYRO_SENSOR]
+               || fw_ver2[FW_DRIVER_IC] != fw_ver3[FW_DRIVER_IC]
+               || fw_ver2[FW_CORE_VERSION] != fw_ver3[FW_CORE_VERSION]) {
+               return false;
+       }
+
+       return true;
+}
+
+bool fimc_is_ois_version_compare_default(char *fw_ver1, char *fw_ver2)
+{
+       if (fw_ver1[FW_GYRO_SENSOR] != fw_ver2[FW_GYRO_SENSOR]
+               || fw_ver1[FW_DRIVER_IC] != fw_ver2[FW_DRIVER_IC]
+               || fw_ver1[FW_CORE_VERSION] != fw_ver2[FW_CORE_VERSION]) {
+               return false;
+       }
+
+       return true;
+}
+
+bool fimc_is_ois_read_userdata(struct fimc_is_core *core)
+{
+       u8 SendData[2], RcvData[256];
+       struct i2c_client *client = core->client1;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       fimc_is_ois_i2c_write(client ,0x000F, 0x40);
+       SendData[0] = 0x00;
+       SendData[1] = 0x00;
+       fimc_is_ois_i2c_write_multi(client, 0x0010, SendData, 4);
+       fimc_is_ois_i2c_write(client ,0x000E, 0x04);
+
+       fimc_is_ois_i2c_read(client, 0x000E, &RcvData[0]);
+       if (RcvData[0] == 0x14) {
+               fimc_is_ois_i2c_read_multi(client, 0x0100, RcvData, FW_TRANS_SIZE);
+               if (core->use_ois_hsi2c) {
+                       fimc_is_ois_i2c_config(core->client1, false);
+               }
+               memcpy(ois_uinfo.header_ver, RcvData, 6);
+               return true;
+       } else {
+               if (core->use_ois_hsi2c) {
+                       fimc_is_ois_i2c_config(core->client1, false);
+               }
+               return false;
+       }
+}
+
+int fimc_is_ois_open_fw(struct fimc_is_core *core, char *name, u8 **buf)
+{
+       int ret = 0;
+       u32 size = 0;
+       const struct firmware *fw_blob = NULL;
+       static char fw_name[100];
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long nread;
+       int fw_requested = 1;
+       int retry_count = 0;
+
+       fw_sdcard = false;
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       snprintf(fw_name, sizeof(fw_name), "%s%s", FIMC_IS_OIS_SDCARD_PATH, name);
+       fp = filp_open(fw_name, O_RDONLY, 0);
+       if (IS_ERR_OR_NULL(fp)) {
+               err("failed to open SDCARD fw!!!");
+               goto request_fw;
+       }
+
+       fw_requested = 0;
+       size = fp->f_path.dentry->d_inode->i_size;
+       pr_info("start read sdcard, file path %s, size %d Bytes\n", fw_name, size);
+
+       *buf = vmalloc(size);
+       if (!(*buf)) {
+               err("failed to allocate memory");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       nread = vfs_read(fp, (char __user *)(*buf), size, &fp->f_pos);
+       if (nread != size) {
+               err("failed to read firmware file, %ld Bytes\n", nread);
+               ret = -EIO;
+               goto p_err;
+       }
+
+       memcpy(ois_pinfo.header_ver, *buf + OIS_BIN_HEADER, OIS_FW_HEADER_SIZE);
+       memcpy(bootCode, *buf, OIS_BOOT_FW_SIZE);
+       memcpy(progCode, *buf + OIS_BIN_LEN - OIS_PROG_FW_SIZE, OIS_PROG_FW_SIZE);
+       fw_sdcard = true;
+       if (OIS_BIN_LEN >= nread) {
+               not_crc_bin = true;
+               err("ois fw binary size = %ld.\n", nread);
+       }
+
+request_fw:
+       if (fw_requested) {
+               snprintf(fw_name, sizeof(fw_name), "%s", name);
+               set_fs(old_fs);
+               retry_count = 3;
+               ret = request_firmware(&fw_blob, fw_name, &core->companion->pdev->dev);
+               while (--retry_count && ret == -EAGAIN) {
+                       err("request_firmware retry(count:%d)", retry_count);
+                       ret = request_firmware(&fw_blob, fw_name, &core->companion->pdev->dev);
+               }
+
+               if (ret) {
+                       err("request_firmware is fail(ret:%d)", ret);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!fw_blob) {
+                       err("fw_blob is NULL");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!fw_blob->data) {
+                       err("fw_blob->data is NULL");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               size = fw_blob->size;
+
+               *buf = vmalloc(size);
+               if (!(*buf)) {
+                       err("failed to allocate memory");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+               memcpy((void *)(*buf), fw_blob->data, size);
+               memcpy(ois_pinfo.header_ver, *buf + OIS_BIN_HEADER, OIS_FW_HEADER_SIZE);
+               memcpy(bootCode, *buf, OIS_BOOT_FW_SIZE);
+               memcpy(progCode, *buf + OIS_BIN_LEN - OIS_PROG_FW_SIZE, OIS_PROG_FW_SIZE);
+               if (OIS_BIN_LEN >= size) {
+                       not_crc_bin = true;
+                       err("ois fw binary size = 0x%08x.\n", size);
+               }
+               pr_info("OIS firmware is loaded from Phone binary.\n");
+       }
+
+p_err:
+       if (!fw_requested) {
+               if (!IS_ERR_OR_NULL(fp)) {
+                       filp_close(fp, current->files);
+               }
+               set_fs(old_fs);
+       } else {
+               if (!IS_ERR_OR_NULL(fw_blob)) {
+                       release_firmware(fw_blob);
+               }
+       }
+
+       return ret;
+}
+
+void fimc_is_ois_check_fw(struct fimc_is_core *core)
+{
+       u8 *buf = NULL;
+       int ret = 0;
+
+       fimc_is_ois_fw_version(core);
+       fimc_is_ois_read_userdata(core);
+
+       if (ois_minfo.header_ver[2] == 'A') {
+               ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_DOM, &buf);
+       } else if (ois_minfo.header_ver[2] == 'B') {
+               ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC, &buf);
+       }
+       if (ret) {
+               err("fimc_is_ois_open_fw failed(%d)\n", ret);
+       }
+
+       if (buf) {
+               vfree(buf);
+       }
+
+       return;
+}
+
+u8 fimc_is_ois_read_status(struct fimc_is_core *core)
+{
+       int ret = 0;
+       u8 status = 0;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0006, &status);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       return status;
+}
+
+u8 fimc_is_ois_read_cal_checksum(struct fimc_is_core *core)
+{
+       int ret = 0;
+       u8 status = 0;
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       ret = fimc_is_ois_i2c_read(core->client1, 0x0005, &status);
+       if (ret) {
+               err("i2c read fail\n");
+       }
+
+       if (core->use_ois_hsi2c) {
+           fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       return status;
+}
+
+void fimc_is_ois_fw_status(struct fimc_is_core *core, u8 *checksum, u8 *caldata)
+{
+       *checksum = fimc_is_ois_read_status(core);
+       *caldata = fimc_is_ois_read_cal_checksum(core);
+
+       return;
+}
+
+bool fimc_is_ois_crc_check(struct fimc_is_core *core, char *buf)
+{
+       u8 check_8[4] = {0, };
+       u32 *buf32 = NULL;
+       u32 checksum;
+       u32 checksum_bin;
+
+       if (not_crc_bin) {
+               err("ois binary does not conatin crc checksum.\n");
+               return false;
+       }
+
+       if (buf == NULL) {
+               err("buf is NULL. CRC check failed.");
+               return false;
+       }
+
+       buf32 = (u32 *)buf;
+
+       memcpy(check_8, buf + OIS_BIN_LEN, 4);
+       checksum_bin = (check_8[3] << 24) | (check_8[2] << 16) | (check_8[1] << 8) | (check_8[0]);
+
+       checksum = getCRC((u16 *)&buf32[0], OIS_BIN_LEN / 2, NULL, NULL);
+       if (checksum != checksum_bin) {
+               return false;
+       } else {
+               return true;
+       }
+}
+
+void fimc_is_ois_fw_update(struct fimc_is_core *core)
+{
+       u8 SendData[256], RcvData;
+       u16 RcvDataShort = 0;
+       u8 data[2] = {0, };
+       int block, i, position = 0;
+       u16 checkSum;
+       u8 *buf = NULL;
+       int ret = 0, sum_size = 0, retry_count = 3;
+       int module_ver = 0, binary_ver = 0;
+       u8 error_status = 0;
+       bool forced_update = false, crc_result = false;
+       bool need_reset = false;
+       struct i2c_client *client = core->client1;
+
+       /* OIS Status Check */
+       error_status = fimc_is_ois_read_status(core);
+       if (error_status == 0x01) {
+               forced_update = true;
+       }
+
+       fimc_is_ois_fw_version(core);
+       fimc_is_ois_read_userdata(core);
+       if (ois_minfo.header_ver[2] == 'A') {
+               ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_DOM, &buf);
+       } else if (ois_minfo.header_ver[2] == 'B') {
+               ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC, &buf);
+       }
+       if (ret) {
+               err("fimc_is_ois_open_fw failed(%d)", ret);
+               goto p_err;
+       }
+
+       if (buf == NULL) {
+               err("buf is NULL. OIS FW Update failed.");
+               return;
+       }
+
+       if (!forced_update) {
+               if (ois_uinfo.header_ver[0] == 0xFF && ois_uinfo.header_ver[1] == 0xFF &&
+                       ois_uinfo.header_ver[2] == 0xFF) {
+                       err("OIS userdata is not valid.");
+                       goto p_err;
+               }
+       }
+
+       /*Update OIS FW when Gyro sensor/Driver IC/ Core version is same*/
+       if (!forced_update) {
+               if (!fimc_is_ois_version_compare(ois_minfo.header_ver, ois_pinfo.header_ver,
+                       ois_uinfo.header_ver)) {
+                       err("Does not update ois fw. OIS module ver = %s, binary ver = %s, userdata ver = %s",
+                               ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);
+                       goto p_err;
+               }
+       } else {
+               if (!fimc_is_ois_version_compare_default(ois_minfo.header_ver, ois_pinfo.header_ver)) {
+                       err("Does not update ois fw. OIS module ver = %s, binary ver = %s",
+                               ois_minfo.header_ver, ois_pinfo.header_ver);
+                       goto p_err;
+               }
+       }
+
+       crc_result = fimc_is_ois_crc_check(core, buf);
+       if (crc_result == false) {
+               err("OIS CRC32 error.\n");
+               goto p_err;
+       }
+
+       if (!fw_sdcard && !forced_update) {
+               module_ver = fimc_is_ois_fw_revision(ois_minfo.header_ver);
+               binary_ver = fimc_is_ois_fw_revision(ois_pinfo.header_ver);
+               if (binary_ver <= module_ver) {
+                       err("OIS module ver = %d, binary ver = %d", module_ver, binary_ver);
+                       goto p_err;
+               }
+       }
+       info("OIS fw update started. module ver = %s, binary ver = %s, userdata ver = %s\n",
+               ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);
+
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+retry:
+       if (need_reset) {
+               fimc_is_ois_gpio_off(core->companion);
+               msleep(30);
+               fimc_is_ois_gpio_on(core->companion);
+               msleep(150);
+       }
+
+       fimc_is_ois_i2c_read(client, 0x01, &RcvData); /* OISSTS Read */
+
+       if (RcvData != 0x01) {/* OISSTS != IDLE */
+               err("RCV data return!!");
+               goto p_err;
+       }
+
+       /* Update a Boot Program */
+       /* SET FWUP_CTRL REG */
+       fimc_is_ois_i2c_write(client ,0x000C, 0x0B);
+       msleep(20);
+
+       position = 0;
+       /* Write Boot Data */
+       for (block = 4; block < 8; block++) {       /* 0x1000 - 0x1FFF */
+               for (i = 0; i < 4; i++) {
+                       memcpy(SendData, bootCode + position, FW_TRANS_SIZE);
+                       fimc_is_ois_i2c_write_multi(client, 0x0100, SendData, FW_TRANS_SIZE + 2);
+                       position += FW_TRANS_SIZE;
+                       if (i == 0 ) {
+                               msleep(20);
+                       } else if ((i == 1) || (i == 2)) {       /* Wait Erase and Write process */
+                                msleep(10);            /* Wait Write process */
+                       } else {
+                               msleep(15); /* Wait Write and Verify process */
+                       }
+               }
+       }
+
+       /* CHECKSUM (Boot) */
+       sum_size = OIS_BOOT_FW_SIZE;
+       checkSum = fimc_is_ois_calc_checksum(&bootCode[0], sum_size);
+       SendData[0] = (checkSum & 0x00FF);
+       SendData[1] = (checkSum & 0xFF00) >> 8;
+       SendData[2] = 0x00;
+       SendData[3] = 0x00;
+       fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);
+       msleep(10);                      /* (RUMBA Self Reset) */
+
+       fimc_is_ois_i2c_read_multi(client, 0x06, data, 2); /* Error Status read */
+       info("%s: OISSTS Read = 0x%02x%02x\n", __func__, data[1], data[0]);
+
+       if (data[1] == 0x00 && data[0] == 0x01) {                                       /* Boot F/W Update Error check */
+               /* Update a User Program */
+               /* SET FWUP_CTRL REG */
+               position = 0;
+               SendData[0] = 0x09;             /* FWUP_DSIZE=256Byte, FWUP_MODE=PROG, FWUPEN=Start */
+               fimc_is_ois_i2c_write(client, 0x0C, SendData[0]);               /* FWUPCTRL REG(0x000C) 1Byte Send */
+
+               /* Write UserProgram Data */
+               for (block = 4; block <= 27; block++) {         /* 0x1000 -0x 6FFF (RUMBA-SA)*/
+                       for (i = 0; i < 4; i++) {
+                               memcpy(SendData, &progCode[position], (size_t)FW_TRANS_SIZE);
+                               fimc_is_ois_i2c_write_multi(client, 0x100, SendData, FW_TRANS_SIZE + 2); /* FLS_DATA REG(0x0100) 256Byte Send */
+                               position += FW_TRANS_SIZE;
+                               if (i ==0 ) {
+                                       msleep(20);             /* Wait Erase and Write process */
+                               } else if ((i==1) || (i==2)) {
+                                       msleep(10);             /* Wait Write process */
+                               } else {
+                                       msleep(15);             /* Wait Write and Verify process */
+                               }
+                       }
+               }
+
+               /* CHECKSUM (Program) */
+               sum_size = OIS_PROG_FW_SIZE;
+               checkSum = fimc_is_ois_calc_checksum(&progCode[0], sum_size);
+               SendData[0] = (checkSum & 0x00FF);
+               SendData[1] = (checkSum & 0xFF00) >> 8;
+               SendData[2] = 0;                /* Don't Care */
+               SendData[3] = 0x80;             /* Self Reset Request */
+
+               fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);  /* FWUP_CHKSUM REG(0x0008) 4Byte Send */
+               msleep(20);             /* (Wait RUMBA Self Reset) */
+               fimc_is_ois_i2c_read(client, 0x6, (u8*)&RcvDataShort); /* Error Status read */
+
+               if (RcvDataShort == 0x0000) {
+                       /* F/W Update Success Process */
+                       info("%s: OISLOG OIS program update success", __func__);
+               } else {
+                       /* Retry Process */
+                       if (retry_count > 0) {
+                               err("OISLOG OIS program update fail, retry update. count = %d", retry_count);
+                               retry_count--;
+                               need_reset = true;
+                               goto retry;
+                       }
+
+                       /* F/W Update Error Process */
+                       err("OISLOG OIS program update fail");
+                       goto p_err;
+               }
+       } else {
+               /* Retry Process */
+               if (retry_count > 0) {
+                       err("OISLOG OIS boot update fail, retry update. count = %d", retry_count);
+                       retry_count--;
+                       need_reset = true;
+                       goto retry;
+               }
+
+               /* Error Process */
+               err("CAN'T process OIS program update");
+               goto p_err;
+       }
+
+       /* S/W Reset */
+       fimc_is_ois_i2c_write(client ,0x000D, 0x01);
+       fimc_is_ois_i2c_write(client ,0x000E, 0x06);
+
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       msleep(30);
+       fimc_is_ois_fw_version(core);
+
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, true);
+       }
+
+       if (!fimc_is_ois_version_compare_default(ois_minfo.header_ver, ois_pinfo.header_ver)) {
+               err("After update ois fw is not correct. OIS module ver = %s, binary ver = %s",
+                       ois_minfo.header_ver, ois_pinfo.header_ver);
+               goto p_err;
+       }
+
+       /* Param init - Flash to Rumba */
+       fimc_is_ois_i2c_write(client ,0x0036, 0x03);
+       msleep(30);
+
+p_err:
+       info("OIS module ver = %s, binary ver = %s, userdata ver = %s\n",
+               ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);
+
+       if (core->use_ois_hsi2c) {
+               fimc_is_ois_i2c_config(core->client1, false);
+       }
+
+       if (buf) {
+               vfree(buf);
+       }
+       return;
+}
+
+#ifdef CONFIG_OIS_FW_UPDATE_THREAD_USE
+int fimc_is_ois_thread(void *data)
+{
+       struct fimc_is_core *core = data;
+
+       fimc_is_ois_gpio_on(core->companion);
+       msleep(150);
+       fimc_is_ois_fw_update(core);
+       fimc_is_ois_gpio_off(core->companion);
+
+       return 0;
+}
+
+void fimc_is_ois_init_thread(struct fimc_is_core *core)
+{
+       pr_info("OIS fimc_is_ois_init_thread\n");
+
+       ois_ts = kthread_run(fimc_is_ois_thread, core, "ois_thread");
+       if (IS_ERR_OR_NULL(ois_ts))
+               err("failed to create a thread for ois fw update\n");
+
+       return;
+}
+#endif /* CONFIG_OIS_FW_UPDATE_THREAD_USE */
+
+static int fimc_is_ois_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct fimc_is_device_ois *device;
+       struct ois_i2c_platform_data *pdata;
+       struct fimc_is_core *core;
+       struct device *i2c_dev;
+       struct pinctrl *pinctrl_i2c = NULL;
+
+       if (fimc_is_dev == NULL) {
+               warn("fimc_is_dev is not yet probed");
+               client->dev.init_name = FIMC_IS_OIS_DEV_NAME;
+               return -EPROBE_DEFER;
+       }
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core)
+               return -EINVAL;
+
+       if (client->dev.of_node) {
+               pdata = devm_kzalloc(&client->dev,
+                       sizeof(struct ois_i2c_platform_data), GFP_KERNEL);
+               if (!pdata) {
+                       err("Failed to allocate memory\n");
+                       return -ENOMEM;
+               }
+       } else {
+               pdata = client->dev.platform_data;
+       }
+
+       if (pdata == NULL) {
+               err("%s : ois probe fail\n", __func__);
+               return -ENODEV;
+       }
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               err("No I2C functionality found\n");
+               devm_kfree(&client->dev, pdata);
+               return -ENODEV;
+       }
+
+       device = kzalloc(sizeof(struct fimc_is_device_ois), GFP_KERNEL);
+       if (!device) {
+               err("fimc_is_device_companion is NULL");
+               devm_kfree(&client->dev, pdata);
+               return -ENOMEM;
+       }
+
+       device->ois_hsi2c_status = false;
+       core->client1 = client;
+       i2c_set_clientdata(client, device);
+       fw_sdcard = false;
+       core->ois_ver_read = false;
+       not_crc_bin = false;
+
+       /* Initial i2c pin */
+       i2c_dev = client->dev.parent->parent;
+       pinctrl_i2c = devm_pinctrl_get_select(i2c_dev, "off_i2c");
+       if (IS_ERR_OR_NULL(pinctrl_i2c)) {
+               printk(KERN_ERR "%s: Failed to configure i2c pin\n", __func__);
+       } else {
+               devm_pinctrl_put(pinctrl_i2c);
+       }
+
+       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+               PINCFG_PACK(PINCFG_TYPE_FUNC, 0));
+       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+               PINCFG_PACK(PINCFG_TYPE_FUNC, 0));
+       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-2",
+               PINCFG_PACK(PINCFG_TYPE_PUD, 0));
+       pin_config_set(FIMC_IS_SPI_PINNAME, "gpc2-3",
+               PINCFG_PACK(PINCFG_TYPE_PUD, 0));
+
+       return 0;
+}
+
+static int fimc_is_ois_remove(struct i2c_client *client)
+{
+#ifdef CONFIG_OIS_FW_UPDATE_THREAD_USE
+       if (ois_ts) {
+               kthread_stop(ois_ts);
+               ois_ts = NULL;
+       }
+#endif
+
+       return 0;
+}
+
+static const struct i2c_device_id ois_id[] = {
+       {FIMC_IS_OIS_DEV_NAME, 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, ois_id);
+
+#ifdef CONFIG_OF
+static struct of_device_id ois_dt_ids[] = {
+       { .compatible = "rumba,ois",},
+       {},
+};
+#endif
+
+static struct i2c_driver ois_i2c_driver = {
+       .driver = {
+                  .name = FIMC_IS_OIS_DEV_NAME,
+                  .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+                  .of_match_table = ois_dt_ids,
+#endif
+       },
+       .probe = fimc_is_ois_probe,
+       .remove = fimc_is_ois_remove,
+       .id_table = ois_id,
+};
+module_i2c_driver(ois_i2c_driver);
+
+MODULE_DESCRIPTION("OIS driver for Rumba");
+MODULE_AUTHOR("kyoungho yun <kyoungho.yun@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-ois.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-ois.h
new file mode 100644 (file)
index 0000000..b5785c4
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS OIS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+struct fimc_is_device_ois {
+       struct v4l2_device                              v4l2_dev;
+       struct platform_device                          *pdev;
+       unsigned long                                   state;
+       struct exynos_platform_fimc_is_sensor           *pdata;
+       struct i2c_client                       *client;
+       int ois_en;
+       bool ois_hsi2c_status;
+};
+
+struct ois_i2c_platform_data {
+       int ois_en;
+};
+
+struct fimc_is_ois_exif {
+       int error_data;
+       int status_data;
+};
+
+int fimc_is_ois_i2c_read(struct i2c_client *client, u16 addr, u8 *data);
+int fimc_is_ois_i2c_write(struct i2c_client *client ,u16 addr, u8 data);
+void fimc_is_ois_enable(struct fimc_is_core *core);
+void fimc_is_ois_offset_test(struct fimc_is_core *core, long *raw_data_x, long *raw_data_y);
+int fimc_is_ois_self_test(struct fimc_is_core *core);
+int fimc_is_ois_gpio_on(struct fimc_is_device_companion *device);
+int fimc_is_ois_gpio_off(struct fimc_is_device_companion *device);
+void fimc_is_ois_fw_update(struct fimc_is_core *core);
+void fimc_is_ois_fw_version(struct fimc_is_core *core);
+int fimc_is_ois_get_module_version(struct fimc_is_ois_info **minfo);
+int fimc_is_ois_get_phone_version(struct fimc_is_ois_info **minfo);
+int fimc_is_ois_get_user_version(struct fimc_is_ois_info **uinfo);
+void fimc_is_ois_get_offset_data(struct fimc_is_core *core, long *raw_data_x, long *raw_data_y);
+void fimc_is_ois_check_fw(struct fimc_is_core *core);
+bool fimc_is_ois_diff_test(struct fimc_is_core *core, int *x_diff, int *y_diff);
+#ifdef CONFIG_OIS_FW_UPDATE_THREAD_USE
+void fimc_is_ois_init_thread(struct fimc_is_core *core);
+#endif
+bool fimc_is_ois_read_userdata(struct fimc_is_core *core);
+void fimc_is_ois_exif_data(struct fimc_is_core *core);
+int fimc_is_ois_get_exif_data(struct fimc_is_ois_exif **exif_info);
+void fimc_is_ois_fw_status(struct fimc_is_core *core, u8 *checksum, u8 *caldata);
\ No newline at end of file
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-sensor.c b/drivers/media/platform/exynos/fimc-is/fimc-is-device-sensor.c
new file mode 100644 (file)
index 0000000..d4ec99e
--- /dev/null
@@ -0,0 +1,2431 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+#include <linux/i2c.h>
+
+#include <mach/map.h>
+#include <mach/devfreq.h>
+#include <mach/regs-clock.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-dt.h"
+#include "fimc-is-dvfs.h"
+
+#include "sensor/fimc-is-device-6b2.h"
+#include "sensor/fimc-is-device-imx134.h"
+#include "sensor/fimc-is-device-imx135.h"
+#include "fimc-is-device-sensor.h"
+#ifdef CONFIG_COMPANION_USE
+#include "fimc-is-companion-dt.h"
+#endif
+
+extern struct device *camera_front_dev;
+extern struct device *camera_rear_dev;
+int fimc_is_sensor_runtime_resume(struct device *dev);
+int fimc_is_sensor_runtime_suspend(struct device *dev);
+
+extern int fimc_is_sen_video_probe(void *data);
+struct pm_qos_request exynos_sensor_qos_cam;
+struct pm_qos_request exynos_sensor_qos_int;
+struct pm_qos_request exynos_sensor_qos_mem;
+
+extern u32 __iomem *notify_fcount_sen0;
+extern u32 __iomem *notify_fcount_sen1;
+extern u32 __iomem *notify_fcount_sen2;
+u32 notify_fcount_sen0_fw;
+u32 notify_fcount_sen1_fw;
+u32 notify_fcount_sen2_fw;
+u32 notify_fcount_dummy;
+
+#define BINNING(x, y) roundup((x) * 1000 / (y), 250)
+
+int fimc_is_sensor_read8(struct i2c_client *client,
+       u16 addr, u8 *val)
+{
+       int ret = 0;
+       struct i2c_msg msg[2];
+       u8 wbuf[2];
+
+       if (!client->adapter) {
+               err("Could not find adapter!\n");
+               ret = -ENODEV;
+               goto p_err;
+       }
+
+       /* 1. I2C operation for writing. */
+       msg[0].addr = client->addr;
+       msg[0].flags = 0; /* write : 0, read : 1 */
+       msg[0].len = 2;
+       msg[0].buf = wbuf;
+       /* TODO : consider other size of buffer */
+       wbuf[0] = (addr & 0xFF00) >> 8;
+       wbuf[1] = (addr & 0xFF);
+
+       /* 2. I2C operation for reading data. */
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 1;
+       msg[1].buf = val;
+
+       ret = i2c_transfer(client->adapter, msg, 2);
+       if (ret < 0) {
+               err("i2c treansfer fail");
+               goto p_err;
+       }
+
+#ifdef PRINT_I2CCMD
+       info("I2CR08(%d) [0x%04X] : 0x%04X\n", client->addr, addr, *val);
+#endif
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_read16(struct i2c_client *client,
+       u16 addr, u16 *val)
+{
+       int ret = 0;
+       struct i2c_msg msg[2];
+       u8 wbuf[2], rbuf[2];
+
+       if (!client->adapter) {
+               err("Could not find adapter!\n");
+               ret = -ENODEV;
+               goto p_err;
+       }
+
+       /* 1. I2C operation for writing. */
+       msg[0].addr = client->addr;
+       msg[0].flags = 0; /* write : 0, read : 1 */
+       msg[0].len = 2;
+       msg[0].buf = wbuf;
+       /* TODO : consider other size of buffer */
+       wbuf[0] = (addr & 0xFF00) >> 8;
+       wbuf[1] = (addr & 0xFF);
+
+       /* 2. I2C operation for reading data. */
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 2;
+       msg[1].buf = rbuf;
+
+       ret = i2c_transfer(client->adapter, msg, 2);
+       if (ret < 0) {
+               err("i2c treansfer fail");
+               goto p_err;
+       }
+
+       *val = ((rbuf[0] << 8) | rbuf[1]);
+
+#ifdef PRINT_I2CCMD
+       info("I2CR16(%d) [0x%04X] : 0x%04X\n", client->addr, addr, *val);
+#endif
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_write(struct i2c_client *client,
+       u8 *buf, u32 size)
+{
+       int ret = 0;
+       int retry_count = 5;
+       struct i2c_msg msg = {client->addr, 0, size, buf};
+
+       do {
+               ret = i2c_transfer(client->adapter, &msg, 1);
+               if (likely(ret == 1))
+                       break;
+               msleep(10);
+       } while (retry_count-- > 0);
+
+       if (ret != 1) {
+               dev_err(&client->dev, "%s: I2C is not working.\n", __func__);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int fimc_is_sensor_write8(struct i2c_client *client,
+       u16 addr, u8 val)
+{
+       int ret = 0;
+       struct i2c_msg msg[1];
+       u8 wbuf[3];
+
+       if (!client->adapter) {
+               err("Could not find adapter!\n");
+               ret = -ENODEV;
+               goto p_err;
+       }
+
+       msg->addr = client->addr;
+       msg->flags = 0;
+       msg->len = 3;
+       msg->buf = wbuf;
+       wbuf[0] = (addr & 0xFF00) >> 8;
+       wbuf[1] = (addr & 0xFF);
+       wbuf[2] = val;
+
+       ret = i2c_transfer(client->adapter, msg, 1);
+       if (ret < 0) {
+               err("i2c treansfer fail(%d)", ret);
+               goto p_err;
+       }
+
+#ifdef PRINT_I2CCMD
+       info("I2CW08(%d) [0x%04X] : 0x%04X\n", client->addr, addr, val);
+#endif
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_write16(struct i2c_client *client,
+       u16 addr, u16 val)
+{
+       int ret = 0;
+       struct i2c_msg msg[1];
+       u8 wbuf[4];
+
+       if (!client->adapter) {
+               err("Could not find adapter!\n");
+               ret = -ENODEV;
+               goto p_err;
+       }
+
+       msg->addr = client->addr;
+       msg->flags = 0;
+       msg->len = 4;
+       msg->buf = wbuf;
+       wbuf[0] = (addr & 0xFF00) >> 8;
+       wbuf[1] = (addr & 0xFF);
+       wbuf[2] = (val & 0xFF00) >> 8;
+       wbuf[3] = (val & 0xFF);
+
+       ret = i2c_transfer(client->adapter, msg, 1);
+       if (ret < 0) {
+               err("i2c treansfer fail(%d)", ret);
+               goto p_err;
+       }
+
+#ifdef PRINT_I2CCMD
+       info("I2CW16(%d) [0x%04X] : 0x%04X\n", client->addr, addr, val);
+#endif
+
+p_err:
+       return ret;
+}
+
+#if defined(CONFIG_PM_DEVFREQ)
+inline static void fimc_is_sensor_set_qos_init(struct fimc_is_device_sensor *device, bool on)
+{
+       int cam_qos = 0;
+       int int_qos = 0;
+       int mif_qos = 0;
+       struct fimc_is_core *core =
+               (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+
+       cam_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CAM, START_DVFS_LEVEL);
+#if 0 /* For vision of L_version */
+       int_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_INT, START_DVFS_LEVEL);
+#endif
+       if (on) {
+               /* DEVFREQ lock */
+               if (cam_qos > 0) {
+                       if (device->request_cam_qos == false) {
+                               pm_qos_add_request(&exynos_sensor_qos_cam, PM_QOS_CAM_THROUGHPUT, cam_qos);
+                               device->request_cam_qos = true;
+                       } else {
+                               err("Adding sensor cam_qos is not allowed");
+                       }
+               }
+
+               if (int_qos > 0) {
+                       if (device->request_int_qos == false) {
+                               pm_qos_add_request(&exynos_sensor_qos_int, PM_QOS_DEVICE_THROUGHPUT, int_qos);
+                               device->request_int_qos = true;
+                       } else {
+                               err("Adding sensor int_qos is not allowed");
+                       }
+               }
+
+               if (mif_qos > 0) {
+                       if (device->request_mif_qos == false) {
+                               pm_qos_add_request(&exynos_sensor_qos_mem, PM_QOS_BUS_THROUGHPUT, mif_qos);
+                               device->request_mif_qos = true;
+                       } else {
+                               err("Adding sensor mif_qos is not allowed");
+                       }
+               }
+               minfo("[SEN:D] %s: QoS LOCK [INT(%d), MIF(%d), CAM(%d)]\n", device,
+                               __func__, int_qos, mif_qos, cam_qos);
+       } else {
+               /* DEVFREQ unlock */
+               if (cam_qos > 0) {
+                       if (device->request_cam_qos == true) {
+                               pm_qos_remove_request(&exynos_sensor_qos_cam);
+                               device->request_cam_qos = false;
+                       } else {
+                               err("Removing sensor cam_qos is not allowed");
+                       }
+               }
+
+               if (int_qos > 0) {
+                       if (device->request_int_qos == true) {
+                               pm_qos_remove_request(&exynos_sensor_qos_int);
+                               device->request_int_qos = false;
+                       } else {
+                               err("Removing sensor int_qos is not allowed");
+                       }
+               }
+
+               if (mif_qos > 0) {
+                       if (device->request_mif_qos == true) {
+                               pm_qos_remove_request(&exynos_sensor_qos_mem);
+                               device->request_mif_qos = false;
+                       } else {
+                               err("Removing sensor mif_qos is not allowed");
+                       }
+               }
+               minfo("[SEN:D] %s: QoS UNLOCK\n", device, __func__);
+       }
+}
+
+inline static void fimc_is_sensor_set_qos_update(struct fimc_is_device_sensor *device, u32 scenario)
+{
+       int cam_qos = 0;
+       int int_qos = 0;
+       int mif_qos = 0;
+       struct fimc_is_core *core =
+               (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+
+       /* HACK: This is considerated only front camera vision scenario. */
+       if (scenario == SENSOR_SCENARIO_VISION) {
+               cam_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CAM, FIMC_IS_SN_FRONT_PREVIEW);
+               int_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_INT, FIMC_IS_SN_FRONT_PREVIEW);
+       }
+
+       /* DEVFREQ update */
+       if (cam_qos > 0)
+               pm_qos_update_request(&exynos_sensor_qos_cam, cam_qos);
+       if (int_qos > 0)
+               pm_qos_update_request(&exynos_sensor_qos_int, int_qos);
+       if (mif_qos > 0)
+               pm_qos_update_request(&exynos_sensor_qos_mem, mif_qos);
+
+       minfo("[SEN:D] %s: QoS UPDATE(%d) [INT(%d), MIF(%d), CAM(%d)]\n", device,
+                       __func__, scenario, int_qos, mif_qos, cam_qos);
+}
+#endif
+
+static int get_sensor_mode(struct fimc_is_sensor_cfg *cfg,
+       u32 cfgs, u32 width, u32 height, u32 framerate)
+{
+       int mode = -1;
+       int idx = -1;
+       u32 i;
+
+       /* find sensor mode by w/h and fps range */
+       for (i = 0; i < cfgs; i++) {
+               if ((cfg[i].width == width) &&
+                               (cfg[i].height == height)) {
+                       if (cfg[i].framerate == framerate) {
+                               /* You don't need to find another sensor mode */
+                               mode = cfg[i].mode;
+                               idx = i;
+                               break;
+                       } else if (cfg[i].framerate > framerate) {
+                               /* try to find framerate smaller than previous */
+                               if (mode < 0) {
+                                       mode = cfg[i].mode;
+                                       idx = i;
+                               } else {
+                                       /* try to compare previous with current */
+                                       if (cfg[idx].framerate > cfg[i].framerate) {
+                                               mode = cfg[i].mode;
+                                               idx = i;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (idx < 0)
+               err("could not find proper sensor mode: %dx%d@%dfps",
+                       width, height, framerate);
+       else
+               pr_info("sensor mode(%dx%d@%d) = %d\n",
+                       cfg[idx].width,
+                       cfg[idx].height,
+                       cfg[idx].framerate,
+                       cfg[idx].mode);
+
+       return mode;
+}
+
+static int fimc_is_sensor_mclk_on(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (test_bit(FIMC_IS_SENSOR_MCLK_ON, &device->state)) {
+               merr("%s : already clk on", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->mclk_on) {
+               merr("mclk_on is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->mclk_on(device->pdev, pdata->scenario, pdata->mclk_ch);
+       if (ret) {
+               merr("mclk_on is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SENSOR_MCLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_mclk_off(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_SENSOR_MCLK_ON, &device->state)) {
+               merr("%s : already clk off", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->mclk_off) {
+               merr("mclk_off is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->mclk_off(device->pdev, pdata->scenario, pdata->mclk_ch);
+       if (ret) {
+               merr("mclk_off is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SENSOR_MCLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_iclk_on(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_core *core;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+       BUG_ON(!device->private_data);
+
+       core = device->private_data;
+       pdata = device->pdata;
+
+       if (test_bit(FIMC_IS_SENSOR_ICLK_ON, &device->state)) {
+               merr("%s : already clk on", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->iclk_cfg) {
+               merr("iclk_cfg is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!pdata->iclk_on) {
+               merr("iclk_on is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->iclk_cfg(core->pdev, pdata->scenario, pdata->csi_ch);
+       if (ret) {
+               merr("iclk_cfg is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = pdata->iclk_on(core->pdev, pdata->scenario, pdata->csi_ch);
+       if (ret) {
+               merr("iclk_on is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SENSOR_ICLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_iclk_off(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_core *core;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+       BUG_ON(!device->private_data);
+
+       core = device->private_data;
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_SENSOR_ICLK_ON, &device->state)) {
+               merr("%s : already clk off", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->iclk_off) {
+               merr("iclk_off is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->iclk_off(core->pdev, pdata->scenario, pdata->csi_ch);
+       if (ret) {
+               merr("iclk_off is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SENSOR_ICLK_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_gpio_on(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (test_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state)) {
+               merr("%s : already gpio on", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->gpio_cfg) {
+               merr("gpio_cfg is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (pdata->id == 0) {
+               core->running_rear_camera = true;
+       } else {
+               core->running_front_camera = true;
+       }
+
+       ret = pdata->gpio_cfg(device->pdev, pdata->scenario, GPIO_SCENARIO_ON);
+       if (ret) {
+               merr("gpio_cfg is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_gpio_off(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state)) {
+               merr("%s : already gpio off", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->gpio_cfg) {
+               merr("gpio_cfg is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->gpio_cfg(device->pdev, pdata->scenario, GPIO_SCENARIO_OFF);
+       if (ret) {
+               merr("gpio_cfg is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state);
+
+p_err:
+       if (pdata->id == 0) {
+               core->running_rear_camera = false;
+       } else {
+               core->running_front_camera = false;
+       }
+       return ret;
+}
+
+#ifdef ENABLE_DTP
+static void fimc_is_sensor_dtp(unsigned long data)
+{
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_sensor *device = (struct fimc_is_device_sensor *)data;
+       struct fimc_is_queue *queue;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+       unsigned long flags;
+       u32 i;
+
+       BUG_ON(!device);
+
+       err("forcely reset due to 0x%08lx", device->force_stop);
+       device->force_stop = 0;
+
+       set_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state);
+       set_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state);
+
+       if (device->ischain) {
+               set_bit(FIMC_IS_GROUP_FORCE_STOP, &device->ischain->group_3aa.state);
+               set_bit(FIMC_IS_GROUP_FORCE_STOP, &device->ischain->group_isp.state);
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &device->ischain->group_3aa.state))
+                       up(&device->ischain->group_3aa.smp_trigger);
+       }
+
+       vctx = device->vctx;
+       if (!vctx) {
+               err("vctx is NULL");
+               return;
+       }
+
+       queue = GET_DST_QUEUE(vctx);
+       framemgr = &queue->framemgr;
+       if ((framemgr->frame_cnt == 0) || (framemgr->frame_cnt > FRAMEMGR_MAX_REQUEST)) {
+               err("frame count of framemgr is invalid(%d)", framemgr->frame_cnt);
+               return;
+       }
+
+       framemgr_e_barrier_irqs(framemgr, 0, flags);
+
+       for (i = 0; i < framemgr->frame_cnt; i++) {
+               frame = &framemgr->frame[i];
+               if (frame->state == FIMC_IS_FRAME_STATE_REQUEST) {
+                       err("buffer done1!!!! %d", i);
+                       fimc_is_frame_trans_req_to_com(framemgr, frame);
+                       queue_done(vctx, queue, i, VB2_BUF_STATE_ERROR);
+               } else if (frame->state == FIMC_IS_FRAME_STATE_PROCESS) {
+                       err("buffer done2!!!! %d", i);
+                       fimc_is_frame_trans_pro_to_com(framemgr, frame);
+                       queue_done(vctx, queue, i, VB2_BUF_STATE_ERROR);
+               }
+       }
+
+       framemgr_x_barrier_irqr(framemgr, 0, flags);
+}
+#endif
+
+static int fimc_is_sensor_start(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       BUG_ON(!device);
+
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state)) {
+               struct v4l2_subdev *subdev;
+
+               subdev = device->subdev_module;
+               if (!subdev) {
+                       merr("subdev is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               ret = v4l2_subdev_call(subdev, video, s_stream, true);
+               if (ret) {
+                       merr("v4l2_subdev_call(s_stream) is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       } else {
+               struct fimc_is_device_ischain *ischain;
+
+               ischain = device->ischain;
+               if (!ischain) {
+                       merr("ischain is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               ret = fimc_is_itf_stream_on(ischain);
+               if (ret) {
+                       merr("fimc_is_itf_stream_on is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_stop(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+
+       BUG_ON(!device);
+
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state)) {
+               struct v4l2_subdev *subdev;
+
+               subdev = device->subdev_module;
+               if (!subdev) {
+                       merr("subdev is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               ret = v4l2_subdev_call(subdev, video, s_stream, false);
+               if (ret) {
+                       merr("v4l2_subdev_call(s_stream) is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       } else {
+               struct fimc_is_device_ischain *ischain;
+
+               ischain = device->ischain;
+               if (!ischain) {
+                       merr("ischain is NULL", device);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               ret = fimc_is_itf_stream_off(ischain);
+               if (ret) {
+                       merr("fimc_is_itf_stream_off is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_tag(struct fimc_is_device_sensor *device,
+       struct fimc_is_frame *frame)
+{
+       int ret = 0;
+       frame->shot->dm.request.frameCount = frame->fcount;
+       frame->shot->dm.sensor.timeStamp = fimc_is_get_timestamp();
+
+       return ret;
+}
+
+static void fimc_is_sensor_control(struct work_struct *data)
+{
+/*
+ * HAL can't send meta data for vision
+ * We accepted vision control by s_ctrl
+ */
+#if 0
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct camera2_sensor_ctl *rsensor_ctl;
+       struct camera2_sensor_ctl *csensor_ctl;
+       struct fimc_is_device_sensor *device;
+
+       device = container_of(data, struct fimc_is_device_sensor, control_work);
+       subdev_module = device->subdev_module;
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               return;
+       }
+
+       module = v4l2_get_subdevdata(subdev_module);
+       rsensor_ctl = &device->control_frame->shot->ctl.sensor;
+       csensor_ctl = &device->sensor_ctl;
+
+       if (rsensor_ctl->exposureTime != csensor_ctl->exposureTime) {
+               CALL_MOPS(module, s_exposure, subdev_module, rsensor_ctl->exposureTime);
+               csensor_ctl->exposureTime = rsensor_ctl->exposureTime;
+       }
+
+       if (rsensor_ctl->frameDuration != csensor_ctl->frameDuration) {
+               CALL_MOPS(module, s_duration, subdev_module, rsensor_ctl->frameDuration);
+               csensor_ctl->frameDuration = rsensor_ctl->frameDuration;
+       }
+
+       if (rsensor_ctl->sensitivity != csensor_ctl->sensitivity) {
+               CALL_MOPS(module, s_again, subdev_module, rsensor_ctl->sensitivity);
+               csensor_ctl->sensitivity = rsensor_ctl->sensitivity;
+       }
+#endif
+}
+
+static int fimc_is_sensor_notify_by_fstr(struct fimc_is_device_sensor *device, void *arg)
+{
+       int ret = 0;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!device);
+       BUG_ON(!arg);
+
+       device->fcount = *(u32 *)arg;
+       framemgr = GET_DST_FRAMEMGR(device->vctx);
+
+       if (device->instant_cnt) {
+               device->instant_cnt--;
+               if (device->instant_cnt == 0)
+                       wake_up(&device->instant_wait);
+       }
+
+       framemgr_e_barrier(framemgr, 0);
+
+       fimc_is_frame_process_head(framemgr, &frame);
+       if (frame) {
+#ifdef MEASURE_TIME
+#ifdef EXTERNAL_TIME
+               do_gettimeofday(&frame->tzone[TM_FLITE_STR]);
+#endif
+#endif
+               if (frame->has_fcount) {
+                       struct list_head *temp;
+                       struct fimc_is_frame *next_frame;
+                       bool finded = false;
+
+                       list_for_each(temp, &framemgr->frame_process_head) {
+                               next_frame = list_entry(temp, struct fimc_is_frame, list);
+                               if (next_frame->has_fcount) {
+                                       continue;
+                               } else {
+                                       finded = true;
+                                       break;
+                               }
+                       }
+
+                       if (finded) {
+                               /* finded frame in processing frame list */
+                               next_frame->has_fcount = true;
+                               next_frame->fcount = device->fcount;
+                               fimc_is_sensor_tag(device, next_frame);
+                       }
+               } else {
+                       frame->fcount = device->fcount;
+                       fimc_is_sensor_tag(device, frame);
+                       frame->has_fcount = true;
+               }
+       }
+#ifdef TASKLET_MSG
+       if (!frame) {
+               merr("[SEN] process is empty", device);
+               fimc_is_frame_print_all(framemgr);
+       }
+#endif
+
+       framemgr_x_barrier(framemgr, 0);
+
+       return ret;
+}
+
+static int fimc_is_sensor_notify_by_fend(struct fimc_is_device_sensor *device, void *arg)
+{
+       int ret = 0;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!device);
+       BUG_ON(!device->vctx);
+
+#ifdef ENABLE_DTP
+       if (device->dtp_check) {
+               device->dtp_check = false;
+               del_timer(&device->dtp_timer);
+       }
+
+       if (device->force_stop)
+               fimc_is_sensor_dtp((unsigned long)device);
+#endif
+
+       frame = (struct fimc_is_frame *)arg;
+       if (frame) {
+               frame->has_fcount = false;
+               buffer_done(device->vctx, frame->index);
+
+               /* device driving */
+               if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state)) {
+                       device->control_frame = frame;
+                       schedule_work(&device->control_work);
+               }
+       }
+
+       return ret;
+}
+
+static void fimc_is_sensor_notify(struct v4l2_subdev *subdev,
+       unsigned int notification,
+       void *arg)
+{
+       int ret = 0;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!subdev);
+
+       device = v4l2_get_subdev_hostdata(subdev);
+
+       switch(notification) {
+       case FLITE_NOTIFY_FSTART:
+               ret = fimc_is_sensor_notify_by_fstr(device, arg);
+               if (ret)
+                       merr("fimc_is_sensor_notify_by_fstr is fail(%d)", device, ret);
+               break;
+       case FLITE_NOTIFY_FEND:
+               ret = fimc_is_sensor_notify_by_fend(device, arg);
+               if (ret)
+                       merr("fimc_is_sensor_notify_by_fend is fail(%d)", device, ret);
+               break;
+       }
+}
+
+static void fimc_is_sensor_instanton(struct work_struct *data)
+{
+       int ret = 0;
+       u32 instant_cnt;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!data);
+
+       device = container_of(data, struct fimc_is_device_sensor, instant_work);
+       instant_cnt = device->instant_cnt;
+
+       clear_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state);
+       clear_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state);
+
+       ret = fimc_is_sensor_start(device);
+       if (ret) {
+               merr("fimc_is_sensor_start is fail(%d)\n", device, ret);
+               goto p_err;
+       }
+       set_bit(FIMC_IS_SENSOR_FRONT_START, &device->state);
+
+#ifdef ENABLE_DTP
+       if (device->dtp_check) {
+               setup_timer(&device->dtp_timer, fimc_is_sensor_dtp, (unsigned long)device);
+               mod_timer(&device->dtp_timer, jiffies +  msecs_to_jiffies(300));
+               info("DTP checking...\n");
+       }
+#endif
+
+       if (instant_cnt) {
+               u32 timetowait, timetoelapse, timeout;
+
+               timeout = FIMC_IS_FLITE_STOP_TIMEOUT + msecs_to_jiffies(instant_cnt*60);
+               timetowait = wait_event_timeout(device->instant_wait,
+                       (device->instant_cnt == 0),
+                       timeout);
+               if (!timetowait) {
+                       merr("wait_event_timeout is invalid", device);
+                       ret = -ETIME;
+               }
+
+               fimc_is_sensor_front_stop(device);
+
+               timetoelapse = (jiffies_to_msecs(timeout) - jiffies_to_msecs(timetowait));
+               info("[FRT:D:%d] instant off(fcount : %d, time : %dms)", device->instance,
+                       device->instant_cnt,
+                       timetoelapse);
+       }
+
+p_err:
+       device->instant_ret = ret;
+}
+
+static int fimc_is_sensor_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       u32 instance = -1;
+       atomic_t device_id;
+       struct fimc_is_core *core;
+       struct fimc_is_device_sensor *device;
+       struct device *dev;
+       void *pdata;
+
+       BUG_ON(!pdev);
+
+       if (fimc_is_dev == NULL) {
+               warn("fimc_is_dev is not yet probed");
+               pdev->dev.init_name = FIMC_IS_SENSOR_DEV_NAME;
+               return -EPROBE_DEFER;
+       }
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_OF
+#ifdef CONFIG_COMPANION_USE
+       ret = fimc_is_sensor_parse_dt_with_companion(pdev);
+       if (ret) {
+               err("parsing device tree is fail(%d)", ret);
+               goto p_err;
+       }
+#else
+       ret = fimc_is_sensor_parse_dt(pdev);
+       if (ret) {
+               err("parsing device tree is fail(%d)", ret);
+               goto p_err;
+       }
+#endif /* CONFIG_COMPANION_USE */
+#endif /* CONFIG_OF */
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+               err("pdata is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* 1. get device */
+       atomic_set(&device_id, pdev->id);
+       device = &core->sensor[pdev->id];
+
+       /* v4l2 device and device init */
+       memset(&device->v4l2_dev, 0, sizeof(struct v4l2_device));
+       instance = v4l2_device_set_name(&device->v4l2_dev, FIMC_IS_SENSOR_DEV_NAME, &device_id);
+       device->v4l2_dev.notify = fimc_is_sensor_notify;
+       device->instance = instance;
+       device->resourcemgr = &core->resourcemgr;
+       device->pdev = pdev;
+       device->private_data = core;
+       device->pdata = pdata;
+       platform_set_drvdata(pdev, device);
+       init_waitqueue_head(&device->instant_wait);
+       INIT_WORK(&device->instant_work, fimc_is_sensor_instanton);
+       INIT_WORK(&device->control_work, fimc_is_sensor_control);
+       spin_lock_init(&device->slock_state);
+       device_init_wakeup(&pdev->dev, true);
+
+       /* 3. state init*/
+       clear_bit(FIMC_IS_SENSOR_OPEN, &device->state);
+       clear_bit(FIMC_IS_SENSOR_MCLK_ON, &device->state);
+       clear_bit(FIMC_IS_SENSOR_ICLK_ON, &device->state);
+       clear_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state);
+       clear_bit(FIMC_IS_SENSOR_DRIVING, &device->state);
+       clear_bit(FIMC_IS_SENSOR_FRONT_START, &device->state);
+       clear_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state);
+       clear_bit(FIMC_IS_SENSOR_BACK_START, &device->state);
+       clear_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state);
+
+#ifdef ENABLE_DTP
+       device->dtp_check = false;
+#endif
+
+       ret = fimc_is_mem_probe(&device->mem, device->pdev);
+       if (ret) {
+               merr("fimc_is_mem_probe is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (device->mem.alloc_ctx)
+               vb2_ion_attach_iommu(device->mem.alloc_ctx);
+#endif
+#endif
+
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_enable(&pdev->dev);
+#endif
+
+       ret = v4l2_device_register(&pdev->dev, &device->v4l2_dev);
+       if (ret) {
+               merr("v4l2_device_register is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_csi_probe(device, device->pdata->csi_ch);
+       if (ret) {
+               merr("fimc_is_csi_probe is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_flite_probe(device, device->pdata->flite_ch);
+       if (ret) {
+               merr("fimc_is_flite_probe is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_sen_video_probe(device);
+       if (ret) {
+               merr("fimc_is_sensor_video_probe is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       dev = pdev->id ? camera_front_dev : camera_rear_dev;
+       if (dev)
+               dev_set_drvdata(dev, device->pdata);
+
+p_err:
+       info("[%d][SEN:D] %s(%d)\n", instance, __func__, ret);
+       return ret;
+}
+
+static int fimc_is_sensor_remove(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       info("%s\n", __func__);
+
+       return ret;
+}
+
+int fimc_is_sensor_open(struct fimc_is_device_sensor *device,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_csi);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (test_bit(FIMC_IS_SENSOR_OPEN, &device->state)) {
+               merr("already open", device);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SENSOR_MCLK_ON, &device->state);
+       clear_bit(FIMC_IS_SENSOR_ICLK_ON, &device->state);
+       clear_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state);
+       clear_bit(FIMC_IS_SENSOR_DRIVING, &device->state);
+       clear_bit(FIMC_IS_SENSOR_FRONT_START, &device->state);
+       clear_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state);
+       clear_bit(FIMC_IS_SENSOR_BACK_START, &device->state);
+       set_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state);
+
+       device->vctx = vctx;
+       device->fcount = 0;
+       device->instant_cnt = 0;
+       device->instant_ret = 0;
+       device->ischain = NULL;
+       device->subdev_module = NULL;
+       device->exposure_time = 0;
+       device->frame_duration = 0;
+       device->force_stop = 0;
+       device->request_cam_qos = 0;
+       device->request_int_qos = 0;
+       device->request_mif_qos = 0;
+       memset(&device->sensor_ctl, 0, sizeof(struct camera2_sensor_ctl));
+       memset(&device->lens_ctl, 0, sizeof(struct camera2_lens_ctl));
+       memset(&device->flash_ctl, 0, sizeof(struct camera2_flash_ctl));
+
+       if (pdata->id == 0) {
+               core->running_rear_camera = true;
+               core->id = SENSOR_POSITION_REAR;
+       } else {
+               core->running_front_camera = true;
+               core->id = SENSOR_POSITION_FRONT;
+       }
+
+       /* for mediaserver force close */
+       ret = fimc_is_resource_get(device->resourcemgr, device->instance);
+       if (ret) {
+               merr("fimc_is_resource_get is fail", device);
+               goto p_err;
+       }
+
+       ret = fimc_is_csi_open(device->subdev_csi);
+       if (ret) {
+               merr("fimc_is_csi_open is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_flite_open(device->subdev_flite, GET_DST_FRAMEMGR(vctx));
+       if (ret) {
+               merr("fimc_is_flite_open is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+#ifdef CONFIG_PM_RUNTIME
+       pm_runtime_get_sync(&device->pdev->dev);
+#else
+       fimc_is_sensor_runtime_resume(&device->pdev->dev);
+#endif
+
+#ifdef ENABLE_DTP
+       device->dtp_check = true;
+#endif
+
+       set_bit(FIMC_IS_SENSOR_OPEN, &device->state);
+
+p_err:
+       info("[SEN:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return ret;
+}
+
+int fimc_is_sensor_close(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *ischain;
+       struct fimc_is_group *group_3aa;
+       struct fimc_is_core *core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_SENSOR_OPEN, &device->state)) {
+               merr("already close", device);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       /* for mediaserver force close */
+       ischain = device->ischain;
+       if (ischain) {
+               group_3aa = &ischain->group_3aa;
+               if (test_bit(FIMC_IS_GROUP_READY, &group_3aa->state)) {
+                       info("media server is dead, 3ax forcely done\n");
+                       set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group_3aa->state);
+               }
+       }
+
+       ret = fimc_is_sensor_back_stop(device);
+       if (ret)
+               merr("fimc_is_sensor_back_stop is fail(%d)", device, ret);
+
+       ret = fimc_is_sensor_front_stop(device);
+       if (ret)
+               merr("fimc_is_sensor_front_stop is fail(%d)", device, ret);
+
+       ret = fimc_is_csi_close(device->subdev_csi);
+       if (ret)
+               merr("fimc_is_flite_close is fail(%d)", device, ret);
+
+       ret = fimc_is_flite_close(device->subdev_flite);
+       if (ret)
+               merr("fimc_is_flite_close is fail(%d)", device, ret);
+
+#if defined(CONFIG_PM_RUNTIME)
+       pm_runtime_put_sync(&device->pdev->dev);
+#else
+       fimc_is_sensor_runtime_suspend(&device->pdev->dev);
+#endif
+
+       /* cancel a work and wait for it to finish */
+       cancel_work_sync(&device->control_work);
+       cancel_work_sync(&device->instant_work);
+
+       if (device->subdev_module) {
+               v4l2_device_unregister_subdev(device->subdev_module);
+               device->subdev_module = NULL;
+       }
+
+       /* for mediaserver force close */
+       ret = fimc_is_resource_put(device->resourcemgr, device->instance);
+       if (ret)
+               merr("fimc_is_resource_put is fail", device);
+
+       clear_bit(FIMC_IS_SENSOR_OPEN, &device->state);
+       set_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state);
+
+p_err:
+       if (pdata->id == 0) {
+               core->running_rear_camera = false;
+       } else {
+               core->running_front_camera = false;
+       }
+       info("[SEN:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return ret;
+}
+
+int fimc_is_sensor_s_input(struct fimc_is_device_sensor *device,
+       u32 input,
+       u32 scenario)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+       struct v4l2_subdev *subdev_csi;
+       struct v4l2_subdev *subdev_flite;
+       struct fimc_is_module_enum *module = NULL;
+       u32 sensor_ch, actuator_ch;
+#if defined(CONFIG_OIS_USE)
+       u32 ois_ch, ois_addr;
+#endif
+       u32 sensor_addr, actuator_addr;
+       u32 i = 0;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdata);
+       BUG_ON(!device->subdev_csi);
+       BUG_ON(input >= SENSOR_NAME_END);
+
+       for (i = 0; i < SENSOR_MAX_ENUM; i++) {
+               if (&device->module_enum[i] &&
+                       device->module_enum[i].id == input) {
+                       module = &device->module_enum[i];
+
+                       /*
+                        * If it is not normal scenario,
+                        * try to find proper sensor module which has a i2c client
+                        */
+                       if (scenario != SENSOR_SCENARIO_NORMAL &&
+                               module->client == NULL)
+                               continue;
+                       else
+                               break;
+               }
+       }
+
+       if (i >= SENSOR_MAX_ENUM) {
+               merr("module is not probed", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       subdev_module = module->subdev;
+       if (!subdev_module) {
+               merr("module is not probed", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* change i2c channel info */
+       if (module->ext.sensor_con.peri_type == SE_I2C) {
+               sensor_ch = device->pdata->i2c_ch & SENSOR_I2C_CH_MASK;
+               sensor_ch >>= SENSOR_I2C_CH_SHIFT;
+               sensor_addr = device->pdata->i2c_addr & SENSOR_I2C_ADDR_MASK;
+               sensor_addr >>= SENSOR_I2C_ADDR_SHIFT;
+               module->ext.sensor_con.peri_setting.i2c.channel = sensor_ch;
+               module->ext.sensor_con.peri_setting.i2c.slave_address = sensor_addr;
+       }
+
+       if (module->ext.actuator_con.peri_type == SE_I2C) {
+               actuator_ch = device->pdata->i2c_ch & ACTUATOR_I2C_CH_MASK;
+               actuator_ch >>= ACTUATOR_I2C_CH_SHIFT;
+               actuator_addr = device->pdata->i2c_addr & ACTUATOR_I2C_ADDR_MASK;
+               actuator_addr >>= ACTUATOR_I2C_ADDR_SHIFT;
+               module->ext.actuator_con.peri_setting.i2c.channel = actuator_ch;
+               module->ext.actuator_con.peri_setting.i2c.slave_address = actuator_addr;
+       }
+
+#if defined(CONFIG_OIS_USE)
+       if (module->ext.ois_con.peri_type == SE_I2C) {
+               ois_ch = device->pdata->i2c_ch & OIS_I2C_CH_MASK;
+               ois_ch >>= OIS_I2C_CH_SHIFT;
+               ois_addr = device->pdata->i2c_addr & OIS_I2C_ADDR_MASK;
+               ois_addr >>= OIS_I2C_ADDR_SHIFT;
+               module->ext.ois_con.peri_setting.i2c.channel = ois_ch;
+               module->ext.ois_con.peri_setting.i2c.slave_address = ois_addr;
+       }
+#endif
+
+       /* send csi chennel to FW */
+       module->ext.sensor_con.csi_ch = device->pdata->csi_ch;
+       module->ext.sensor_con.csi_ch |= 0x0100;
+
+       module->ext.flash_con.peri_setting.gpio.first_gpio_port_no = device->pdata->flash_first_gpio;
+       module->ext.flash_con.peri_setting.gpio.second_gpio_port_no = device->pdata->flash_second_gpio;
+
+#ifdef CONFIG_COMPANION_USE
+       /* Data Type For Comapnion:
+        * Companion use user defined data type.
+        */
+       if (module->ext.companion_con.product_name &&
+       module->ext.companion_con.product_name != COMPANION_NAME_NOTHING)
+               device->image.format.field = V4L2_FIELD_INTERLACED;
+#endif
+
+       subdev_csi = device->subdev_csi;
+       subdev_flite = device->subdev_flite;
+       device->image.framerate = min_t(u32, SENSOR_DEFAULT_FRAMERATE, module->max_framerate);
+       device->image.window.width = module->pixel_width;
+       device->image.window.height = module->pixel_height;
+       device->image.window.o_width = device->image.window.width;
+       device->image.window.o_height = device->image.window.height;
+
+       if (scenario) {
+               device->pdata->scenario = scenario;
+               set_bit(FIMC_IS_SENSOR_DRIVING, &device->state);
+       } else {
+               device->pdata->scenario = SENSOR_SCENARIO_NORMAL;
+               clear_bit(FIMC_IS_SENSOR_DRIVING, &device->state);
+       }
+
+       if (device->subdev_module) {
+               mwarn("subdev_module is already registered", device);
+               v4l2_device_unregister_subdev(device->subdev_module);
+       }
+
+       ret = v4l2_device_register_subdev(&device->v4l2_dev, subdev_module);
+       if (ret) {
+               merr("v4l2_device_register_subdev is fail(%d)", device, ret);
+               goto p_err;
+       } else {
+               device->subdev_module = subdev_module;
+       }
+
+#if defined(CONFIG_PM_DEVFREQ)
+       /* DEVFREQ set */
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state))
+               fimc_is_sensor_set_qos_init(device, true);
+#endif
+
+       /* configuration clock control */
+       ret = fimc_is_sensor_iclk_on(device);
+       if (ret) {
+               merr("fimc_is_sensor_iclk_on is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+#if defined(CONFIG_PM_DEVFREQ)
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state))
+               fimc_is_sensor_set_qos_update(device, device->pdata->scenario);
+#endif
+
+       /* Sensor power on */
+       ret = fimc_is_sensor_gpio_on(device);
+       if (ret) {
+               merr("fimc_is_sensor_gpio_on is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = v4l2_subdev_call(subdev_flite, core, init, device->pdata->csi_ch);
+       if (ret) {
+               merr("v4l2_flite_call(init) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = v4l2_subdev_call(subdev_csi, core, init, (u32)module);
+       if (ret) {
+               merr("v4l2_csi_call(init) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state)) {
+               ret = v4l2_subdev_call(subdev_module, core, init, 0);
+               if (ret) {
+                       merr("v4l2_module_call(init) is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+
+       minfo("[SEN:D] %s(%d, %d, %d)\n", device, __func__, input, scenario, ret);
+       return ret;
+}
+
+int fimc_is_sensor_s_format(struct fimc_is_device_sensor *device,
+       struct fimc_is_fmt *format,
+       u32 width,
+       u32 height)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+       struct v4l2_subdev *subdev_csi;
+       struct v4l2_subdev *subdev_flite;
+       struct fimc_is_module_enum *module;
+       struct v4l2_mbus_framefmt subdev_format;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_module);
+       BUG_ON(!device->subdev_csi);
+       BUG_ON(!device->subdev_flite);
+       BUG_ON(!device->subdev_module);
+       BUG_ON(!format);
+
+       subdev_module = device->subdev_module;
+       subdev_csi = device->subdev_csi;
+       subdev_flite = device->subdev_flite;
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev_module);
+       if (!module) {
+               merr("module is NULL", device);
+               goto p_err;
+       }
+
+       /* Data Type For Comapnion:
+        * Companion use user defined data type.
+        */
+       if (device->image.format.field == V4L2_FIELD_INTERLACED)
+               format->field = V4L2_FIELD_INTERLACED;
+
+       device->image.format = *format;
+       device->image.window.offs_h = 0;
+       device->image.window.offs_v = 0;
+       device->image.window.width = width;
+       device->image.window.o_width = width;
+       device->image.window.height = height;
+       device->image.window.o_height = height;
+
+       subdev_format.code = format->pixelformat;
+       subdev_format.field = format->field;
+       subdev_format.width = width;
+       subdev_format.height = height;
+
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state)) {
+               ret = v4l2_subdev_call(subdev_module, video, s_mbus_fmt, &subdev_format);
+               if (ret) {
+                       merr("v4l2_module_call(s_format) is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       }
+
+       ret = v4l2_subdev_call(subdev_csi, video, s_mbus_fmt, &subdev_format);
+       if (ret) {
+               merr("v4l2_csi_call(s_format) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       ret = v4l2_subdev_call(subdev_flite, video, s_mbus_fmt, &subdev_format);
+       if (ret) {
+               merr("v4l2_flite_call(s_format) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       /* if sensor is driving mode, skip finding sensor mode */
+       if (!test_bit(FIMC_IS_SENSOR_DRIVING, &device->state))
+               device->mode = get_sensor_mode(module->cfg, module->cfgs,
+                               device->image.window.width, device->image.window.height,
+                               device->image.framerate);
+       else
+               device->mode = 0;
+
+       /* can't find proper sensor mode */
+       if (device->mode < 0) {
+               ret = -EINVAL;
+               goto p_err;
+       }
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_s_framerate(struct fimc_is_device_sensor *device,
+       struct v4l2_streamparm *param)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+       struct v4l2_subdev *subdev_csi;
+       struct fimc_is_module_enum *module;
+       struct v4l2_captureparm *cp;
+       struct v4l2_fract *tpf;
+       u32 framerate = 0;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_module);
+       BUG_ON(!device->subdev_csi);
+       BUG_ON(!param);
+
+       cp = &param->parm.capture;
+       tpf = &cp->timeperframe;
+
+       if (!tpf->numerator) {
+               merr("numerator is 0", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framerate = tpf->denominator / tpf->numerator;
+       subdev_module = device->subdev_module;
+       subdev_csi = device->subdev_csi;
+
+       if (framerate == 0) {
+               mwarn("frame rate 0 request is ignored", device);
+               goto p_err;
+       }
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev_module);
+       if (!module) {
+               merr("module is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state)) {
+               merr("front is already stream on", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               merr("type is invalid(%d)", device, param->type);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (framerate > module->max_framerate) {
+               merr("framerate is invalid(%d > %d)", device, framerate, module->max_framerate);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = v4l2_subdev_call(subdev_csi, video, s_parm, param);
+       if (ret) {
+               merr("v4l2_csi_call(s_param) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state)) {
+               ret = v4l2_subdev_call(subdev_module, video, s_parm, param);
+               if (ret) {
+                       merr("v4l2_module_call(s_param) is fail(%d)", device, ret);
+                       goto p_err;
+               }
+       }
+
+       device->image.framerate = framerate;
+
+       device->mode = get_sensor_mode(module->cfg, module->cfgs,
+                       device->image.window.width, device->image.window.height,
+                       framerate);
+
+       info("[SEN:D:%d] framerate: req@%dfps, cur@%dfps\n", device->instance,
+               framerate, device->image.framerate);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_s_ctrl(struct fimc_is_device_sensor *device,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_module);
+       BUG_ON(!device->subdev_csi);
+       BUG_ON(!ctrl);
+
+       subdev_module = device->subdev_module;
+
+       ret = v4l2_subdev_call(subdev_module, core, s_ctrl, ctrl);
+       if (ret) {
+               err("s_ctrl is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_s_bns(struct fimc_is_device_sensor *device,
+       u32 ratio)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_flite;
+       u32 sensor_width, sensor_height;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_flite);
+
+       subdev_flite = device->subdev_flite;
+
+       sensor_width = fimc_is_sensor_g_width(device);
+       sensor_height = fimc_is_sensor_g_height(device);
+       if (!sensor_width || !sensor_height) {
+               merr("Sensor size is zero. Sensor set_format first.\n", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device->image.window.otf_width
+               = rounddown((sensor_width * 1000 / ratio), 4);
+       device->image.window.otf_height
+               = rounddown((sensor_height * 1000 / ratio), 2);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_s_frame_duration(struct fimc_is_device_sensor *device,
+       u32 framerate)
+{
+       int ret = 0;
+       u64 frame_duration;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!device);
+
+       subdev_module = device->subdev_module;
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       module = v4l2_get_subdevdata(subdev_module);
+       if (!module) {
+               err("module is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* unit : nano */
+       frame_duration = (1000 * 1000 * 1000) / framerate;
+       if (frame_duration <= 0) {
+               err("it is wrong frame duration(%lld)", frame_duration);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (device->frame_duration != frame_duration) {
+               CALL_MOPS(module, s_duration, subdev_module, frame_duration);
+               device->frame_duration = frame_duration;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_s_exposure_time(struct fimc_is_device_sensor *device,
+       u32 exposure_time)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!device);
+
+       subdev_module = device->subdev_module;
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       module = v4l2_get_subdevdata(subdev_module);
+       if (!module) {
+               err("module is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (exposure_time <= 0) {
+               err("it is wrong exposure time (%d)", exposure_time);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (device->exposure_time != exposure_time) {
+               CALL_MOPS(module, s_exposure, subdev_module, exposure_time);
+               device->exposure_time = exposure_time;
+       }
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_g_ctrl(struct fimc_is_device_sensor *device,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_module);
+       BUG_ON(!device->subdev_csi);
+       BUG_ON(!ctrl);
+
+       subdev_module = device->subdev_module;
+
+       ret = v4l2_subdev_call(subdev_module, core, g_ctrl, ctrl);
+       if (ret) {
+               err("g_ctrl is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+
+int fimc_is_sensor_g_instance(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+       return device->instance;
+}
+
+int fimc_is_sensor_g_fcount(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+       return device->fcount;
+}
+
+int fimc_is_sensor_g_framerate(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+       return device->image.framerate;
+}
+
+int fimc_is_sensor_g_width(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+       return device->image.window.width;
+}
+
+int fimc_is_sensor_g_height(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+       return device->image.window.height;
+}
+
+int fimc_is_sensor_g_bns_width(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+
+       if (device->image.window.otf_width)
+               return device->image.window.otf_width;
+
+       return device->image.window.width;
+}
+
+int fimc_is_sensor_g_bns_height(struct fimc_is_device_sensor *device)
+{
+       BUG_ON(!device);
+       if (device->image.window.otf_height)
+               return device->image.window.otf_height;
+
+       return device->image.window.height;
+}
+
+int fimc_is_sensor_g_bns_ratio(struct fimc_is_device_sensor *device)
+{
+       int binning = 0;
+       u32 sensor_width, sensor_height;
+       u32 bns_width, bns_height;
+
+       BUG_ON(!device);
+
+       sensor_width = fimc_is_sensor_g_width(device);
+       sensor_height = fimc_is_sensor_g_height(device);
+       bns_width = fimc_is_sensor_g_bns_width(device);
+       bns_height = fimc_is_sensor_g_bns_height(device);
+
+       binning = min(BINNING(sensor_width, bns_width),
+               BINNING(sensor_height, bns_height));
+
+       return binning;
+}
+
+int fimc_is_sensor_g_bratio(struct fimc_is_device_sensor *device)
+{
+       int binning = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_module);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(device->subdev_module);
+       if (!module) {
+               merr("module is NULL", device);
+               goto p_err;
+       }
+
+       binning = min(BINNING(module->active_width, device->image.window.width),
+               BINNING(module->active_height, device->image.window.height));
+
+p_err:
+       return binning;
+}
+
+int fimc_is_sensor_g_module(struct fimc_is_device_sensor *device,
+       struct fimc_is_module_enum **module)
+{
+       int ret = 0;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_module);
+
+       *module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(device->subdev_module);
+       if (!*module) {
+               merr("module is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_buffer_queue(struct fimc_is_device_sensor *device,
+       u32 index)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_frame *frame;
+       struct fimc_is_framemgr *framemgr;
+
+       if (index >= FRAMEMGR_MAX_REQUEST) {
+               err("index(%d) is invalid", index);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr = &device->vctx->q_dst->framemgr;
+       if (framemgr == NULL) {
+               err("framemgr is null\n");
+               ret = EINVAL;
+               goto p_err;
+       }
+
+       frame = &framemgr->frame[index];
+       if (frame == NULL) {
+               err("frame is null\n");
+               ret = EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!test_bit(FRAME_INI_MEM, &frame->memory))) {
+               err("frame %d is NOT init", index);
+               ret = EINVAL;
+               goto p_err;
+       }
+
+       framemgr_e_barrier_irqs(framemgr, FMGR_IDX_2 + index, flags);
+
+       if (frame->state == FIMC_IS_FRAME_STATE_FREE) {
+               fimc_is_frame_trans_fre_to_req(framemgr, frame);
+       } else {
+               err("frame(%d) is not free state(%d)", index, frame->state);
+               fimc_is_frame_print_all(framemgr);
+       }
+
+       framemgr_x_barrier_irqr(framemgr, FMGR_IDX_2 + index, flags);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_buffer_finish(struct fimc_is_device_sensor *device,
+       u32 index)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_frame *frame;
+       struct fimc_is_framemgr *framemgr;
+
+       if (index >= FRAMEMGR_MAX_REQUEST) {
+               err("index(%d) is invalid", index);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       framemgr = &device->vctx->q_dst->framemgr;
+       frame = &framemgr->frame[index];
+
+       framemgr_e_barrier_irqs(framemgr, FMGR_IDX_3 + index, flags);
+
+       if (frame->state == FIMC_IS_FRAME_STATE_COMPLETE) {
+               if (!frame->shot->dm.request.frameCount)
+                       err("request.frameCount is 0\n");
+               fimc_is_frame_trans_com_to_fre(framemgr, frame);
+
+               frame->shot_ext->free_cnt = framemgr->frame_fre_cnt;
+               frame->shot_ext->request_cnt = framemgr->frame_req_cnt;
+               frame->shot_ext->process_cnt = framemgr->frame_pro_cnt;
+               frame->shot_ext->complete_cnt = framemgr->frame_com_cnt;
+       } else {
+               err("frame(%d) is not com state(%d)", index, frame->state);
+               fimc_is_frame_print_all(framemgr);
+               ret = -EINVAL;
+       }
+
+       framemgr_x_barrier_irqr(framemgr, FMGR_IDX_3 + index, flags);
+
+exit:
+       return ret;
+}
+
+int fimc_is_sensor_back_start(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       int enable;
+       struct v4l2_subdev *subdev_flite;
+       struct fimc_is_device_flite *flite;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_flite);
+
+       subdev_flite = device->subdev_flite;
+       enable = FLITE_ENABLE_FLAG;
+
+       if (test_bit(FIMC_IS_SENSOR_BACK_START, &device->state)) {
+               err("already back start");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       flite = (struct fimc_is_device_flite *)v4l2_get_subdevdata(subdev_flite);
+       if (!flite) {
+               merr("flite is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* to determine flite buffer done mode (early/normal) when not vision mode */
+       if (!test_bit(FIMC_IS_SENSOR_DRIVING, &device->state) && flite->chk_early_buf_done) {
+               flite->chk_early_buf_done(flite, device->image.framerate,
+                       device->pdev->id);
+       }
+
+       ret = v4l2_subdev_call(subdev_flite, video, s_stream, enable);
+       if (ret) {
+               merr("v4l2_flite_call(s_stream) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_SENSOR_BACK_START, &device->state);
+
+p_err:
+       minfo("[SEN:D] %s(%dx%d, %d)\n", device, __func__,
+               device->image.window.width, device->image.window.height, ret);
+       return ret;
+}
+
+int fimc_is_sensor_back_stop(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       int enable;
+       struct v4l2_subdev *subdev_flite;
+
+       BUG_ON(!device);
+       BUG_ON(!device->subdev_flite);
+
+       enable = 0;
+       subdev_flite = device->subdev_flite;
+
+       if (!test_bit(FIMC_IS_SENSOR_BACK_START, &device->state)) {
+               warn("already back stop");
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state)) {
+               warn("fimc_is_flite_stop, no waiting...");
+               enable = FLITE_NOWAIT_FLAG << FLITE_NOWAIT_SHIFT;
+       }
+
+       ret = v4l2_subdev_call(subdev_flite, video, s_stream, enable);
+       if (ret) {
+               merr("v4l2_flite_call(s_stream) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SENSOR_BACK_START, &device->state);
+
+p_err:
+       minfo("[BAK:D] %s(%d)\n", device, __func__, ret);
+       return ret;
+}
+
+int fimc_is_sensor_front_start(struct fimc_is_device_sensor *device,
+       u32 instant_cnt,
+       u32 nonblock)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_module;
+       struct v4l2_subdev *subdev_csi;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdata);
+       BUG_ON(!device->subdev_csi);
+
+       if (test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state)) {
+               merr("already front start", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device->instant_cnt = instant_cnt;
+       subdev_csi = device->subdev_csi;
+       subdev_module = device->subdev_module;
+       if (!subdev_module) {
+               merr("subdev_module is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev_module);
+       if (!module) {
+               merr("module is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = v4l2_subdev_call(subdev_csi, video, s_stream, IS_ENABLE_STREAM);
+       if (ret) {
+               merr("v4l2_csi_call(s_stream) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       mdbgd_sensor("%s(snesor id : %d, csi ch : %d, size : %d x %d)\n", device,
+               __func__,
+               module->id,
+               device->pdata->csi_ch,
+               device->image.window.width,
+               device->image.window.height);
+
+       if (nonblock) {
+               schedule_work(&device->instant_work);
+       } else {
+               fimc_is_sensor_instanton(&device->instant_work);
+               if (device->instant_ret) {
+                       merr("fimc_is_sensor_instanton is fail(%d)", device, device->instant_ret);
+                       ret = device->instant_ret;
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_sensor_front_stop(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct v4l2_subdev *subdev_csi;
+
+       BUG_ON(!device);
+
+       if (!test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state)) {
+               warn("already front stop");
+               goto p_err;
+       }
+
+       subdev_csi = device->subdev_csi;
+
+       ret = fimc_is_sensor_stop(device);
+       if (ret)
+               merr("sensor stream off is failed(%d)\n", device, ret);
+
+       ret = v4l2_subdev_call(subdev_csi, video, s_stream, IS_DISABLE_STREAM);
+       if (ret)
+               merr("v4l2_csi_call(s_stream) is fail(%d)", device, ret);
+
+       set_bit(FIMC_IS_SENSOR_BACK_NOWAIT_STOP, &device->state);
+       clear_bit(FIMC_IS_SENSOR_FRONT_START, &device->state);
+
+p_err:
+       minfo("[FRT:D] %s(%d)\n", device, __func__, ret);
+       return ret;
+}
+
+int fimc_is_sensor_gpio_off_softlanding(struct fimc_is_device_sensor *device)
+{
+       int ret = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+
+       BUG_ON(!device);
+       BUG_ON(!device->pdev);
+       BUG_ON(!device->pdata);
+
+       pdata = device->pdata;
+
+       if (!test_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state)) {
+               merr("%s : already gpio off", device, __func__);
+               goto p_err;
+       }
+
+       if (!pdata->gpio_cfg) {
+               merr("gpio_cfg is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = pdata->gpio_cfg(device->pdev, pdata->scenario, GPIO_SCENARIO_OFF);
+       if (ret) {
+               merr("gpio_cfg is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       clear_bit(FIMC_IS_SENSOR_GPIO_ON, &device->state);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sensor_suspend(struct device *dev)
+{
+       int ret = 0;
+
+       info("%s\n", __func__);
+
+       return ret;
+}
+
+static int fimc_is_sensor_resume(struct device *dev)
+{
+       int ret = 0;
+
+       info("%s\n", __func__);
+
+       return ret;
+}
+
+int fimc_is_sensor_runtime_suspend(struct device *dev)
+{
+       int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_device_sensor *device;
+       struct v4l2_subdev *subdev_csi;
+
+       info("%s\n", __func__);
+
+       BUG_ON(!pdev);
+
+       device = (struct fimc_is_device_sensor *)platform_get_drvdata(pdev);
+       if (!device) {
+               err("device is NULL");
+               return -EINVAL;
+       }
+
+#if !(defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433))
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (device->mem.alloc_ctx)
+               vb2_ion_detach_iommu(device->mem.alloc_ctx);
+#endif
+#endif
+
+       subdev_csi = device->subdev_csi;
+       if (!subdev_csi)
+               mwarn("subdev_csi is NULL", device);
+
+       /* gpio uninit */
+       if(device->pdata->is_softlanding == false) {
+               ret = fimc_is_sensor_gpio_off(device);
+               if (ret) {
+                       mwarn("fimc_is_sensor_gpio_off is fail(%d)", device, ret);
+               }
+       }
+
+       /* GSCL internal clock off */
+       ret = fimc_is_sensor_iclk_off(device);
+       if (ret)
+               mwarn("fimc_is_sensor_iclk_off is fail(%d)", device, ret);
+
+       /* Sensor clock on */
+       ret = fimc_is_sensor_mclk_off(device);
+       if (ret)
+               mwarn("fimc_is_sensor_mclk_off is fail(%d)", device, ret);
+
+       ret = v4l2_subdev_call(subdev_csi, core, s_power, 0);
+       if (ret)
+               mwarn("v4l2_csi_call(s_power) is fail(%d)", device, ret);
+
+#if defined(CONFIG_PM_DEVFREQ)
+       /* DEVFREQ set */
+       if (test_bit(FIMC_IS_SENSOR_DRIVING, &device->state))
+               fimc_is_sensor_set_qos_init(device, false);
+#endif
+
+       info("[SEN:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return 0;
+}
+
+int fimc_is_sensor_runtime_resume(struct device *dev)
+{
+       int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_device_sensor *device;
+       struct v4l2_subdev *subdev_csi;
+
+       device = (struct fimc_is_device_sensor *)platform_get_drvdata(pdev);
+       if (!device) {
+               err("device is NULL");
+               return -EINVAL;
+       }
+
+       subdev_csi = device->subdev_csi;
+       if (!subdev_csi) {
+               merr("subdev_csi is NULL", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+/* HACK */
+/* at xyref 4415, when runtime_suspend operating, isp0 power is off thoroughly
+   so it needs to power on operation at sensor_runtime_resume operation */
+#if defined(CONFOG_SOC_EXYNOS4415) && !defined(CONFIG_PM_RUNTIME)
+       {
+               u32 val;
+               /* ISP0 */
+               /* 1. set feedback mode */
+               val = __raw_readl(PMUREG_ISP0_OPTION);
+               val = (val & ~(0x3<< 0)) | (0x2 << 0);
+               __raw_writel(val, PMUREG_ISP0_OPTION);
+
+               /* 2. power on isp0 */
+               val = __raw_readl(PMUREG_ISP0_CONFIGURATION);
+               val = (val & ~(0x7 << 0)) | (0x7 << 0);
+               __raw_writel(val, PMUREG_ISP0_CONFIGURATION);
+       }
+#endif
+
+       /* 1. Enable MIPI */
+       ret = v4l2_subdev_call(subdev_csi, core, s_power, 1);
+       if (ret) {
+               merr("v4l2_csi_call(s_power) is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+       /* 2. Sensor clock on */
+       ret = fimc_is_sensor_mclk_on(device);
+       if (ret) {
+               merr("fimc_is_sensor_mclk_on is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+#if !(defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433))
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (device->mem.alloc_ctx)
+               vb2_ion_attach_iommu(device->mem.alloc_ctx);
+       pr_debug("FIMC_IS runtime resume - ion attach complete\n");
+#endif
+#endif
+
+p_err:
+       info("[SEN:D:%d] %s(%d)\n", device->instance, __func__, ret);
+       return ret;
+}
+
+static const struct dev_pm_ops fimc_is_sensor_pm_ops = {
+       .suspend                = fimc_is_sensor_suspend,
+       .resume                 = fimc_is_sensor_resume,
+       .runtime_suspend        = fimc_is_sensor_runtime_suspend,
+       .runtime_resume         = fimc_is_sensor_runtime_resume,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_sensor_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-sensor",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_fimc_is_sensor_match);
+
+static struct platform_driver fimc_is_sensor_driver = {
+       .probe  = fimc_is_sensor_probe,
+       .remove = fimc_is_sensor_remove,
+       .driver = {
+               .name   = FIMC_IS_SENSOR_DEV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &fimc_is_sensor_pm_ops,
+               .of_match_table = exynos_fimc_is_sensor_match,
+       }
+};
+
+module_platform_driver(fimc_is_sensor_driver);
+#else
+static struct platform_device_id fimc_is_sensor_driver_ids[] = {
+       {
+               .name           = FIMC_IS_SENSOR_DEV_NAME,
+               .driver_data    = 0,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, fimc_is_sensor_driver_ids);
+
+static struct platform_driver fimc_is_sensor_driver = {
+       .probe    = fimc_is_sensor_probe,
+       .remove   = __devexit_p(fimc_is_sensor_remove),
+       .id_table = fimc_is_sensor_driver_ids,
+       .driver   = {
+               .name   = FIMC_IS_SENSOR_DEV_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &fimc_is_sensor_pm_ops,
+       }
+};
+
+static int __init fimc_is_sensor_init(void)
+{
+       int ret = 0;
+
+       ret = platform_driver_register(&fimc_is_sensor_driver);
+       if (ret)
+               err("platform_driver_register failed: %d\n", ret);
+
+       return ret;
+}
+
+static void __exit fimc_is_sensor_exit(void)
+{
+       platform_driver_unregister(&fimc_is_sensor_driver);
+}
+module_init(fimc_is_sensor_init);
+module_exit(fimc_is_sensor_exit);
+#endif
+
+MODULE_AUTHOR("Gilyeon lim<kilyeon.im@samsung.com>");
+MODULE_DESCRIPTION("Exynos FIMC_IS_SENSOR driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-device-sensor.h b/drivers/media/platform/exynos/fimc-is/fimc-is-device-sensor.h
new file mode 100644 (file)
index 0000000..a0ae8a1
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef fimc_is_device_sensor_H
+#define fimc_is_device_sensor_H
+
+#include <mach/exynos-fimc-is-sensor.h>
+#include "fimc-is-mem.h"
+#include "fimc-is-video.h"
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-device-flite.h"
+#include "fimc-is-device-csi.h"
+
+struct fimc_is_video_ctx;
+struct fimc_is_device_ischain;
+
+#define SENSOR_MAX_ENUM                        20
+#define SENSOR_DEFAULT_FRAMERATE       30
+
+#define SENSOR_SCENARIO_MASK           0xF0000000
+#define SENSOR_SCENARIO_SHIFT          28
+#define SENSOR_MODULE_MASK             0x0FFFFFFF
+#define SENSOR_MODULE_SHIFT            0
+
+#define SENSOR_SSTREAM_MASK            0x0000000F
+#define SENSOR_SSTREAM_SHIFT           0
+#define SENSOR_INSTANT_MASK            0x0FFF0000
+#define SENSOR_INSTANT_SHIFT           16
+#define SENSOR_NOBLOCK_MASK            0xF0000000
+#define SENSOR_NOBLOCK_SHIFT           28
+
+#define SENSOR_I2C_CH_MASK             0xFF
+#define SENSOR_I2C_CH_SHIFT            0
+#define ACTUATOR_I2C_CH_MASK           0xFF00
+#define ACTUATOR_I2C_CH_SHIFT          8
+#define OIS_I2C_CH_MASK                0xFF0000
+#define OIS_I2C_CH_SHIFT               16
+
+#define SENSOR_I2C_ADDR_MASK           0xFF
+#define SENSOR_I2C_ADDR_SHIFT          0
+#define ACTUATOR_I2C_ADDR_MASK         0xFF00
+#define ACTUATOR_I2C_ADDR_SHIFT                8
+#define OIS_I2C_ADDR_MASK              0xFF0000
+#define OIS_I2C_ADDR_SHIFT             16
+
+#define FIMC_IS_SENSOR_CFG(w, h, f, s, m) {    \
+       .width          = w,                    \
+       .height         = h,                    \
+       .framerate      = f,                    \
+       .settle         = s,                    \
+       .mode           = m,                    \
+}
+
+enum fimc_is_sensor_output_entity {
+       FIMC_IS_SENSOR_OUTPUT_NONE = 0,
+       FIMC_IS_SENSOR_OUTPUT_FRONT,
+};
+
+enum fimc_is_sensor_force_stop {
+       FIMC_IS_BAD_FRAME_STOP = 0,
+       FIMC_IS_MIF_THROTTLING_STOP = 1,
+       FIMC_IS_FLITE_OVERFLOW_STOP = 2
+};
+
+struct fimc_is_sensor_cfg {
+       u32 width;
+       u32 height;
+       u32 framerate;
+       u32 settle;
+       int mode;
+};
+
+struct fimc_is_sensor_ops {
+       int (*stream_on)(struct v4l2_subdev *subdev);
+       int (*stream_off)(struct v4l2_subdev *subdev);
+
+       int (*s_duration)(struct v4l2_subdev *subdev, u64 duration);
+       int (*g_min_duration)(struct v4l2_subdev *subdev);
+       int (*g_max_duration)(struct v4l2_subdev *subdev);
+
+       int (*s_exposure)(struct v4l2_subdev *subdev, u64 exposure);
+       int (*g_min_exposure)(struct v4l2_subdev *subdev);
+       int (*g_max_exposure)(struct v4l2_subdev *subdev);
+
+       int (*s_again)(struct v4l2_subdev *subdev, u64 sensivity);
+       int (*g_min_again)(struct v4l2_subdev *subdev);
+       int (*g_max_again)(struct v4l2_subdev *subdev);
+
+       int (*s_dgain)(struct v4l2_subdev *subdev);
+       int (*g_min_dgain)(struct v4l2_subdev *subdev);
+       int (*g_max_dgain)(struct v4l2_subdev *subdev);
+};
+
+struct fimc_is_module_enum {
+       u32                             id;
+       struct v4l2_subdev              *subdev; /* connected module subdevice */
+       u32                             device; /* connected sensor device */
+       u32                             pixel_width;
+       u32                             pixel_height;
+       u32                             active_width;
+       u32                             active_height;
+       u32                             max_framerate;
+       u32                             position;
+       u32                             mode;
+       u32                             lanes;
+       u32                             vcis; /* vci is valid only if mode is vc mode */
+       struct fimc_is_vci              *vci;
+       u32                             cfgs;
+       struct fimc_is_sensor_cfg       *cfg;
+       struct i2c_client               *client;
+       struct sensor_open_extended     ext;
+       struct fimc_is_sensor_ops       *ops;
+       char                            *sensor_maker;
+       char                            *sensor_name;
+       char                            *setfile_name;
+       void                            *private_data;
+       int                             (*power_setpin)(struct device *);
+};
+
+enum fimc_is_sensor_state {
+       FIMC_IS_SENSOR_OPEN,
+       FIMC_IS_SENSOR_MCLK_ON,
+       FIMC_IS_SENSOR_ICLK_ON,
+       FIMC_IS_SENSOR_GPIO_ON,
+       FIMC_IS_SENSOR_DRIVING,
+       FIMC_IS_SENSOR_FRONT_START,
+       FIMC_IS_SENSOR_FRONT_DTP_STOP,
+       FIMC_IS_SENSOR_BACK_START,
+       FIMC_IS_SENSOR_BACK_NOWAIT_STOP
+};
+
+struct fimc_is_device_sensor {
+       struct v4l2_device                              v4l2_dev;
+       struct platform_device                          *pdev;
+       struct fimc_is_mem                              mem;
+
+       u32                                             instance;
+       struct fimc_is_image                            image;
+
+       struct fimc_is_video_ctx                        *vctx;
+       struct fimc_is_video                            video;
+
+       struct fimc_is_device_ischain                   *ischain;
+       struct fimc_is_resourcemgr                      *resourcemgr;
+       struct fimc_is_module_enum                      module_enum[SENSOR_MAX_ENUM];
+
+       /* current control value */
+       struct camera2_sensor_ctl                       sensor_ctl;
+       struct camera2_lens_ctl                         lens_ctl;
+       struct camera2_flash_ctl                        flash_ctl;
+       struct work_struct                              control_work;
+       struct fimc_is_frame                            *control_frame;
+
+       u32                                             fcount;
+       u32                                             instant_cnt;
+       int                                             instant_ret;
+       wait_queue_head_t                               instant_wait;
+       struct work_struct                              instant_work;
+       unsigned long                                   state;
+       spinlock_t                                      slock_state;
+
+       /* hardware configuration */
+       struct v4l2_subdev                              *subdev_module;
+       struct v4l2_subdev                              *subdev_csi;
+       struct v4l2_subdev                              *subdev_flite;
+
+       int                                             mode;
+       /* gain boost */
+       int                                             min_target_fps;
+       int                                             max_target_fps;
+       int                                             scene_mode;
+
+       /* for vision control */
+       int                                             exposure_time;
+       u64                                             frame_duration;
+
+       /* ENABLE_DTP */
+       bool                                            dtp_check;
+       struct timer_list                               dtp_timer;
+       unsigned long                                   force_stop;
+
+       struct exynos_platform_fimc_is_sensor           *pdata;
+       void                                            *private_data;
+
+       /* DVFS state */
+       bool                                            request_cam_qos;
+       bool                                            request_int_qos;
+       bool                                            request_mif_qos;
+};
+
+int fimc_is_sensor_open(struct fimc_is_device_sensor *device,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_sensor_close(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_s_input(struct fimc_is_device_sensor *device,
+       u32 input,
+       u32 scenario);
+int fimc_is_sensor_s_format(struct fimc_is_device_sensor *device,
+       struct fimc_is_fmt *format,
+       u32 width,
+       u32 height);
+int fimc_is_sensor_s_ctrl(struct fimc_is_device_sensor *device,
+       struct v4l2_control *ctrl);
+int fimc_is_sensor_buffer_queue(struct fimc_is_device_sensor *device,
+       u32 index);
+int fimc_is_sensor_buffer_finish(struct fimc_is_device_sensor *device,
+       u32 index);
+
+int fimc_is_sensor_front_start(struct fimc_is_device_sensor *device,
+       u32 instant_cnt,
+       u32 nonblock);
+int fimc_is_sensor_front_stop(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_back_start(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_back_stop(struct fimc_is_device_sensor *device);
+
+int fimc_is_sensor_s_framerate(struct fimc_is_device_sensor *device,
+       struct v4l2_streamparm *param);
+int fimc_is_sensor_s_bns(struct fimc_is_device_sensor *device,
+       u32 reatio);
+
+int fimc_is_sensor_s_frame_duration(struct fimc_is_device_sensor *device,
+       u32 frame_duration);
+int fimc_is_sensor_s_exposure_time(struct fimc_is_device_sensor *device,
+       u32 exposure_time);
+
+int fimc_is_sensor_g_ctrl(struct fimc_is_device_sensor *device,
+       struct v4l2_control *ctrl);
+int fimc_is_sensor_g_instance(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_framerate(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_fcount(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_width(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_height(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_bns_width(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_bns_height(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_bns_ratio(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_bratio(struct fimc_is_device_sensor *device);
+int fimc_is_sensor_g_module(struct fimc_is_device_sensor *device,
+       struct fimc_is_module_enum **module);
+int fimc_is_sensor_gpio_off_softlanding(struct fimc_is_device_sensor *device);
+
+/* sensor driver */
+int fimc_is_sensor_read8(struct i2c_client *client,
+       u16 addr, u8 *val);
+int fimc_is_sensor_read16(struct i2c_client *client,
+       u16 addr, u16 *val);
+int fimc_is_sensor_write(struct i2c_client *client,
+       u8 *buf, u32 size);
+int fimc_is_sensor_write8(struct i2c_client *client,
+       u16 addr, u8 val);
+int fimc_is_sensor_write16(struct i2c_client *client,
+       u16 addr, u16 val);
+
+#define CALL_MOPS(s, op, args...) (((s)->ops->op) ? ((s)->ops->op(args)) : 0)
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-dt.c b/drivers/media/platform/exynos/fimc-is/fimc-is-dt.c
new file mode 100644 (file)
index 0000000..d14e8d2
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <mach/exynos-fimc-is-sensor.h>
+#include <mach/exynos-fimc-is.h>
+#include <media/exynos_mc.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#endif
+
+#include "fimc-is-core.h"
+#include "fimc-is-dt.h"
+
+#ifdef CONFIG_OF
+int get_pin_lookup_state(struct device *dev,
+       struct exynos_platform_fimc_is_sensor *pdata)
+{
+       int ret = 0;
+       u32 i, j, k;
+       char ch_name[30];
+       struct exynos_sensor_pin (*pin_ctrls)[2][GPIO_CTRL_MAX];
+       struct pinctrl_state *s;
+
+       pin_ctrls = pdata->pin_ctrls;
+
+       for (i = 0; i < SENSOR_SCENARIO_MAX; ++i) {
+               for (j = 0; j < GPIO_SCENARIO_MAX; ++j) {
+                       for (k = 0; k < GPIO_CTRL_MAX; ++k) {
+                               if (pin_ctrls[i][j][k].act == PIN_FUNCTION) {
+                                       snprintf(ch_name, sizeof(ch_name), "%s%d",
+                                                       pin_ctrls[i][j][k].name,
+                                                       pdata->csi_ch);
+                                       s = pinctrl_lookup_state(pdata->pinctrl, ch_name);
+                                       if (IS_ERR(s)) {
+                                               err("cam %s, ch %d pinctrl_lookup_state is failed", ch_name, pdata->csi_ch);
+                                               ret = -EINVAL;
+                                               goto p_err;
+                                       } else {
+                                               pin_ctrls[i][j][k].pin = (unsigned long)s;
+                                               pr_info("[%d][%d][%d][%s] gpio function cfg is seted", i, j, k, ch_name);
+                                       }
+                               }
+                       }
+               }
+       }
+
+p_err:
+       return ret;
+}
+
+static int parse_gate_info(struct exynos_platform_fimc_is *pdata, struct device_node *np)
+{
+       int ret = 0;
+       struct device_node *group_np = NULL;
+       struct device_node *gate_info_np;
+       struct property *prop;
+       struct property *prop2;
+       const __be32 *p;
+       const char *s;
+       u32 i = 0, u = 0;
+       struct exynos_fimc_is_clk_gate_info *gate_info;
+
+       /* get subip of fimc-is info */
+       gate_info = kzalloc(sizeof(struct exynos_fimc_is_clk_gate_info), GFP_KERNEL);
+       if (!gate_info) {
+               printk(KERN_ERR "%s: no memory for fimc_is gate_info\n", __func__);
+               return -EINVAL;
+       }
+
+       s = NULL;
+       /* get gate register info */
+       prop2 = of_find_property(np, "clk_gate_strs", NULL);
+       of_property_for_each_u32(np, "clk_gate_enums", prop, p, u) {
+               printk(KERN_INFO "int value: %d\n", u);
+               s = of_prop_next_string(prop2, s);
+               if (s != NULL) {
+                       printk(KERN_INFO "String value: %d-%s\n", u, s);
+                       gate_info->gate_str[u] = s;
+               }
+       }
+
+       /* gate info */
+       gate_info_np = of_find_node_by_name(np, "clk_gate_ctrl");
+       if (!gate_info_np) {
+               printk(KERN_ERR "%s: can't find fimc_is clk_gate_ctrl node\n", __func__);
+               ret = -ENOENT;
+               goto p_err;
+       }
+       i = 0;
+       while ((group_np = of_get_next_child(gate_info_np, group_np))) {
+               struct exynos_fimc_is_clk_gate_group *group =
+                               &gate_info->groups[i];
+               of_property_for_each_u32(group_np, "mask_clk_on_org", prop, p, u) {
+                       printk(KERN_INFO "(%d) int1 value: %d\n", i, u);
+                       group->mask_clk_on_org |= (1 << u);
+               }
+               of_property_for_each_u32(group_np, "mask_clk_off_self_org", prop, p, u) {
+                       printk(KERN_INFO "(%d) int2 value: %d\n", i, u);
+                       group->mask_clk_off_self_org |= (1 << u);
+               }
+               of_property_for_each_u32(group_np, "mask_clk_off_depend", prop, p, u) {
+                       printk(KERN_INFO "(%d) int3 value: %d\n", i, u);
+                       group->mask_clk_off_depend |= (1 << u);
+               }
+               of_property_for_each_u32(group_np, "mask_cond_for_depend", prop, p, u) {
+                       printk(KERN_INFO "(%d) int4 value: %d\n", i, u);
+                       group->mask_cond_for_depend |= (1 << u);
+               }
+               i++;
+               printk(KERN_INFO "(%d) [0x%x , 0x%x, 0x%x, 0x%x\n", i,
+                       group->mask_clk_on_org,
+                       group->mask_clk_off_self_org,
+                       group->mask_clk_off_depend,
+                       group->mask_cond_for_depend
+               );
+       }
+
+       pdata->gate_info = gate_info;
+       pdata->gate_info->user_clk_gate = exynos_fimc_is_set_user_clk_gate;
+       pdata->gate_info->clk_on_off = exynos_fimc_is_clk_gate;
+
+       return 0;
+p_err:
+       kfree(gate_info);
+       return ret;
+}
+
+static int parse_dvfs_data(struct exynos_platform_fimc_is *pdata, struct device_node *np)
+{
+       u32 temp;
+       char *pprop;
+
+       memset(pdata->dvfs_data, 0, sizeof(pdata->dvfs_data));
+       DT_READ_U32(np, "default_int", pdata->dvfs_data[FIMC_IS_SN_DEFAULT][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "default_cam", pdata->dvfs_data[FIMC_IS_SN_DEFAULT][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "default_mif", pdata->dvfs_data[FIMC_IS_SN_DEFAULT][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "default_i2c", pdata->dvfs_data[FIMC_IS_SN_DEFAULT][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "front_preview_int", pdata->dvfs_data[FIMC_IS_SN_FRONT_PREVIEW][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "front_preview_cam", pdata->dvfs_data[FIMC_IS_SN_FRONT_PREVIEW][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "front_preview_mif", pdata->dvfs_data[FIMC_IS_SN_FRONT_PREVIEW][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "front_preview_i2c", pdata->dvfs_data[FIMC_IS_SN_FRONT_PREVIEW][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "front_capture_int", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAPTURE][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "front_capture_cam", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAPTURE][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "front_capture_mif", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAPTURE][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "front_capture_i2c", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAPTURE][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "front_camcording_int", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAMCORDING][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "front_camcording_cam", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAMCORDING][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "front_camcording_mif", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAMCORDING][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "front_camcording_i2c", pdata->dvfs_data[FIMC_IS_SN_FRONT_CAMCORDING][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "front_vt1_int", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT1][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "front_vt1_cam", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT1][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "front_vt1_mif", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT1][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "front_vt1_i2c", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT1][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "front_vt2_int", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT2][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "front_vt2_cam", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT2][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "front_vt2_mif", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT2][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "front_vt2_i2c", pdata->dvfs_data[FIMC_IS_SN_FRONT_VT2][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_preview_fhd_bns_off_int", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_preview_fhd_bns_off_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_preview_fhd_bns_off_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_preview_fhd_bns_off_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_preview_fhd_int", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_preview_fhd_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_preview_fhd_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_preview_fhd_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_I2C]);
+       /* if there's no FHD preview(with BNS off) dvfa data, set value of FHD recording data */
+       if (!(pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_MIF])) {
+               pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_INT] = pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_INT];
+               pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_CAM] = pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_CAM];
+               pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_MIF] = pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_MIF];
+               pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF][FIMC_IS_DVFS_I2C] = pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_FHD][FIMC_IS_DVFS_I2C];
+       }
+       DT_READ_U32(np, "rear_preview_whd_int", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_WHD][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_preview_whd_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_WHD][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_preview_whd_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_WHD][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_preview_whd_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_WHD][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_preview_uhd_int", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_UHD][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_preview_uhd_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_UHD][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_preview_uhd_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_UHD][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_preview_uhd_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_PREVIEW_UHD][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_capture_int", pdata->dvfs_data[FIMC_IS_SN_REAR_CAPTURE][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_capture_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_CAPTURE][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_capture_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_CAPTURE][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_capture_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_CAPTURE][FIMC_IS_DVFS_I2C]);
+
+       DT_READ_U32(np, "rear_camcording_fhd_bns_off_int", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_camcording_fhd_bns_off_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_camcording_fhd_bns_off_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_camcording_fhd_bns_off_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_camcording_fhd_int", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_camcording_fhd_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_camcording_fhd_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_camcording_fhd_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_camcording_whd_int", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_WHD][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_camcording_whd_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_WHD][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_camcording_whd_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_WHD][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_camcording_whd_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_WHD][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "rear_camcording_uhd_int", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_UHD][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "rear_camcording_uhd_cam", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_UHD][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "rear_camcording_uhd_mif", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_UHD][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "rear_camcording_uhd_i2c", pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_UHD][FIMC_IS_DVFS_I2C]);
+       /* if there's no FHD recording(with BNS off) dvfa data, set value of FHD recording data */
+       if (!(pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_MIF])) {
+               pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_INT] = pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_INT];
+               pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_CAM] = pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_CAM];
+               pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_MIF] = pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_MIF];
+               pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF][FIMC_IS_DVFS_I2C] = pdata->dvfs_data[FIMC_IS_SN_REAR_CAMCORDING_FHD][FIMC_IS_DVFS_I2C];
+       }
+       DT_READ_U32(np, "dual_preview_int", pdata->dvfs_data[FIMC_IS_SN_DUAL_PREVIEW][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "dual_preview_cam", pdata->dvfs_data[FIMC_IS_SN_DUAL_PREVIEW][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "dual_preview_mif", pdata->dvfs_data[FIMC_IS_SN_DUAL_PREVIEW][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "dual_preview_i2c", pdata->dvfs_data[FIMC_IS_SN_DUAL_PREVIEW][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "dual_capture_int", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAPTURE][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "dual_capture_cam", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAPTURE][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "dual_capture_mif", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAPTURE][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "dual_capture_i2c", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAPTURE][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "dual_camcording_int", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAMCORDING][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "dual_camcording_cam", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAMCORDING][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "dual_camcording_mif", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAMCORDING][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "dual_camcording_i2c", pdata->dvfs_data[FIMC_IS_SN_DUAL_CAMCORDING][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "high_speed_fps_int", pdata->dvfs_data[FIMC_IS_SN_HIGH_SPEED_FPS][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "high_speed_fps_cam", pdata->dvfs_data[FIMC_IS_SN_HIGH_SPEED_FPS][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "high_speed_fps_mif", pdata->dvfs_data[FIMC_IS_SN_HIGH_SPEED_FPS][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "high_speed_fps_i2c", pdata->dvfs_data[FIMC_IS_SN_HIGH_SPEED_FPS][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "dis_enable_int", pdata->dvfs_data[FIMC_IS_SN_DIS_ENABLE][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "dis_enable_cam", pdata->dvfs_data[FIMC_IS_SN_DIS_ENABLE][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "dis_enable_mif", pdata->dvfs_data[FIMC_IS_SN_DIS_ENABLE][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "dis_enable_i2c", pdata->dvfs_data[FIMC_IS_SN_DIS_ENABLE][FIMC_IS_DVFS_I2C]);
+       DT_READ_U32(np, "max_int", pdata->dvfs_data[FIMC_IS_SN_MAX][FIMC_IS_DVFS_INT]);
+       DT_READ_U32(np, "max_cam", pdata->dvfs_data[FIMC_IS_SN_MAX][FIMC_IS_DVFS_CAM]);
+       DT_READ_U32(np, "max_mif", pdata->dvfs_data[FIMC_IS_SN_MAX][FIMC_IS_DVFS_MIF]);
+       DT_READ_U32(np, "max_i2c", pdata->dvfs_data[FIMC_IS_SN_MAX][FIMC_IS_DVFS_I2C]);
+
+       return 0;
+}
+
+static int parse_subip_info(struct exynos_platform_fimc_is *pdata, struct device_node *np)
+{
+       u32 temp;
+       char *pprop;
+       struct exynos_fimc_is_subip_info *subip_info;
+
+       /* get subip of fimc-is info */
+       subip_info = kzalloc(sizeof(struct exynos_fimc_is_subip_info), GFP_KERNEL);
+       if (!subip_info) {
+               printk(KERN_ERR "%s: no memory for fimc_is subip_info\n", __func__);
+               return -EINVAL;
+       }
+
+       DT_READ_U32(np, "num_of_mcuctl", subip_info->_mcuctl.valid);
+       DT_READ_U32(np, "num_of_3a0", subip_info->_3a0.valid);
+       DT_READ_U32(np, "num_of_3a1", subip_info->_3a1.valid);
+       DT_READ_U32(np, "num_of_isp", subip_info->_isp.valid);
+       DT_READ_U32(np, "num_of_drc", subip_info->_drc.valid);
+       DT_READ_U32(np, "num_of_scc", subip_info->_scc.valid);
+       DT_READ_U32(np, "num_of_odc", subip_info->_odc.valid);
+       DT_READ_U32(np, "num_of_dis", subip_info->_dis.valid);
+       DT_READ_U32(np, "num_of_dnr", subip_info->_dnr.valid);
+       DT_READ_U32(np, "num_of_scp", subip_info->_scp.valid);
+       DT_READ_U32(np, "num_of_fd",  subip_info->_fd.valid);
+
+       DT_READ_U32(np, "full_bypass_mcuctl", subip_info->_mcuctl.full_bypass);
+       DT_READ_U32(np, "full_bypass_3a0", subip_info->_3a0.full_bypass);
+       DT_READ_U32(np, "full_bypass_3a1", subip_info->_3a1.full_bypass);
+       DT_READ_U32(np, "full_bypass_isp", subip_info->_isp.full_bypass);
+       DT_READ_U32(np, "full_bypass_drc", subip_info->_drc.full_bypass);
+       DT_READ_U32(np, "full_bypass_scc", subip_info->_scc.full_bypass);
+       DT_READ_U32(np, "full_bypass_odc", subip_info->_odc.full_bypass);
+       DT_READ_U32(np, "full_bypass_dis", subip_info->_dis.full_bypass);
+       DT_READ_U32(np, "full_bypass_dnr", subip_info->_dnr.full_bypass);
+       DT_READ_U32(np, "full_bypass_scp", subip_info->_scp.full_bypass);
+       DT_READ_U32(np, "full_bypass_fd",  subip_info->_fd.full_bypass);
+
+       DT_READ_U32(np, "version_mcuctl", subip_info->_mcuctl.version);
+       DT_READ_U32(np, "version_3a0", subip_info->_3a0.version);
+       DT_READ_U32(np, "version_3a1", subip_info->_3a1.version);
+       DT_READ_U32(np, "version_isp", subip_info->_isp.version);
+       DT_READ_U32(np, "version_drc", subip_info->_drc.version);
+       DT_READ_U32(np, "version_scc", subip_info->_scc.version);
+       DT_READ_U32(np, "version_odc", subip_info->_odc.version);
+       DT_READ_U32(np, "version_dis", subip_info->_dis.version);
+       DT_READ_U32(np, "version_dnr", subip_info->_dnr.version);
+       DT_READ_U32(np, "version_scp", subip_info->_scp.version);
+       DT_READ_U32(np, "version_fd",  subip_info->_fd.version);
+
+       pdata->subip_info = subip_info;
+
+       return 0;
+}
+
+int fimc_is_power_initpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       int gpio_none = 0;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       pdata = dev->platform_data;
+
+       if (!pdata->sensor_id || (pdata->sensor_id >= SENSOR_NAME_END)) {
+               err("check the sensor id. sensor_id %d", pdata->sensor_id);
+               return -ENODEV;
+       }
+
+       /* POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+
+int fimc_is_power_setpin(struct device *dev, int position, int sensor_id)
+{
+       struct fimc_is_core *core;
+       struct fimc_is_device_sensor *sensor;
+       int ret = 0;
+       int i, pos, found;
+
+       if (!fimc_is_dev) {
+               err("fimc_is_dev is not yet probed");
+               return -ENODEV;
+       }
+
+       if (!sensor_id || (sensor_id >= SENSOR_NAME_END)) {
+               err("check the sensor id. sensor_id %d", sensor_id);
+               return -ENODEV;
+       }
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core is NULL");
+               return -EINVAL;
+       }
+
+       if (!atomic_read(&core->resourcemgr.rsccount_module))
+               err("sensor driver not probed");
+
+       sensor = &core->sensor[position];
+
+       /* Call power_setpin and return  */
+       for (i = 0; i < atomic_read(&core->resourcemgr.rsccount_module); i++) {
+               if (sensor_id == sensor->module_enum[i].id) {
+                       info("%s: sensor found(id %d). %s\n", __func__, sensor_id,
+                               (position == sensor->module_enum[i].position) ? "" : "position not matched");
+
+                       if (sensor->module_enum[i].power_setpin)
+                               ret = sensor->module_enum[i].power_setpin(dev);
+
+                       return ret;
+               }
+       }
+
+       /* Enumerate probed sensor lists if not found */
+       for (pos = 0, found = 0; pos < FIMC_IS_MAX_NODES; pos++, found = 0) {
+               sensor = &core->sensor[pos];
+               for (i = 0; i < atomic_read(&core->resourcemgr.rsccount_module); i++) {
+                       if (sensor->module_enum[i].id) {
+                               info("Camera sensor %d: id %3d. %s\n", pos, sensor->module_enum[i].id,
+                                       sensor->module_enum[i].setfile_name ?
+                                       sensor->module_enum[i].setfile_name : "");
+                               found++;
+                       }
+               }
+
+               if (!found)
+                       info("Camera sensor %d: none\n", pos);
+       }
+
+       err("sensor not found (pos %d, id %d)", position, sensor_id);
+
+       return 0;
+}
+
+struct exynos_platform_fimc_is *fimc_is_parse_dt(struct device *dev)
+{
+       void *ret = NULL;
+       struct exynos_platform_fimc_is *pdata;
+       struct device_node *subip_info_np;
+       struct device_node *dvfs_np;
+       struct device_node *np = dev->of_node;
+#if defined CONFIG_COMPANION_USE || defined CONFIG_USE_VENDER_FEATURE
+       int retVal = 0;
+#endif
+
+       if (!np)
+               return ERR_PTR(-ENOENT);
+
+       pdata = kzalloc(sizeof(struct exynos_platform_fimc_is), GFP_KERNEL);
+       if (!pdata) {
+               printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       pdata->clk_cfg = exynos_fimc_is_cfg_clk;
+       pdata->clk_on = exynos_fimc_is_clk_on;
+       pdata->clk_off = exynos_fimc_is_clk_off;
+       pdata->print_clk = exynos_fimc_is_print_clk;
+       pdata->print_cfg = exynos_fimc_is_print_cfg;
+       pdata->print_pwr = exynos_fimc_is_print_pwr;
+
+       dev->platform_data = pdata;
+
+#ifdef CONFIG_COMPANION_USE
+       retVal = of_property_read_u32(np, "companion_spi_channel", &pdata->companion_spi_channel);
+       if (retVal) {
+               err("spi_channel read is fail(%d)", retVal);
+       }
+
+       pdata->use_two_spi_line = of_property_read_bool(np, "use_two_spi_line");
+#endif
+#ifdef CONFIG_USE_VENDER_FEATURE
+       retVal = of_property_read_u32(np, "use_sensor_dynamic_voltage_mode", &pdata->use_sensor_dynamic_voltage_mode);
+       if (retVal) {
+               err("use_sensor_dynamic_voltage_mode read is fail(%d)", retVal);
+               pdata->use_sensor_dynamic_voltage_mode = 0;
+       }
+#ifdef CONFIG_OIS_USE
+       pdata->use_ois = of_property_read_bool(np, "use_ois");
+       if (!pdata->use_ois) {
+               err("use_ois not use(%d)", pdata->use_ois);
+       }
+#endif /* CONFIG_OIS_USE */
+       pdata->use_ois_hsi2c = of_property_read_bool(np, "use_ois_hsi2c");
+       if (!pdata->use_ois_hsi2c) {
+               err("use_ois_hsi2c not use(%d)", pdata->use_ois_hsi2c);
+       }
+
+       pdata->use_module_check = of_property_read_bool(np, "use_module_check");
+       if (!pdata->use_module_check) {
+               err("use_module_check not use(%d)", pdata->use_module_check);
+       }
+#endif
+       subip_info_np = of_find_node_by_name(np, "subip_info");
+       if (!subip_info_np) {
+               printk(KERN_ERR "%s: can't find fimc_is subip_info node\n", __func__);
+               ret = ERR_PTR(-ENOENT);
+               goto p_err;
+       }
+       parse_subip_info(pdata, subip_info_np);
+
+       if (parse_gate_info(pdata, np) < 0)
+               printk(KERN_ERR "%s: can't parse clock gate info node\n", __func__);
+
+       dvfs_np = of_find_node_by_name(np, "fimc_is_dvfs");
+       if (!dvfs_np) {
+               printk(KERN_ERR "%s: can't find fimc_is_dvfs node\n", __func__);
+               ret = ERR_PTR(-ENOENT);
+               goto p_err;
+       }
+       parse_dvfs_data(pdata, dvfs_np);
+
+       return pdata;
+p_err:
+       kfree(pdata);
+       return ret;
+}
+
+int fimc_is_sensor_parse_dt(struct platform_device *pdev)
+{
+       int ret = 0;
+       u32 temp;
+       char *pprop;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       struct device *dev;
+       const char *name;
+       u32 id;
+
+       BUG_ON(!pdev);
+       BUG_ON(!pdev->dev.of_node);
+
+       dev = &pdev->dev;
+       dnode = dev->of_node;
+
+       pdata = kzalloc(sizeof(struct exynos_platform_fimc_is_sensor), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: no memory for platform data\n", __func__);
+               return -ENOMEM;
+       }
+
+       pdata->gpio_cfg = exynos_fimc_is_sensor_pins_cfg;
+       pdata->iclk_cfg = exynos_fimc_is_sensor_iclk_cfg;
+       pdata->iclk_on = exynos_fimc_is_sensor_iclk_on;
+       pdata->iclk_off = exynos_fimc_is_sensor_iclk_off;
+       pdata->mclk_on = exynos_fimc_is_sensor_mclk_on;
+       pdata->mclk_off = exynos_fimc_is_sensor_mclk_off;
+
+       ret = of_property_read_u32(dnode, "scenario", &pdata->scenario);
+       if (ret) {
+               err("scenario read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "mclk_ch", &pdata->mclk_ch);
+       if (ret) {
+               err("mclk_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "csi_ch", &pdata->csi_ch);
+       if (ret) {
+               err("csi_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "flite_ch", &pdata->flite_ch);
+       if (ret) {
+               err("flite_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "i2c_ch", &pdata->i2c_ch);
+       if (ret) {
+               err("i2c_ch read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "i2c_addr", &pdata->i2c_addr);
+       if (ret) {
+               err("i2c_addr read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "is_bns", &pdata->is_bns);
+       if (ret) {
+               err("is_bns read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       ret = of_property_read_u32(dnode, "id", &id);
+       if (ret) {
+               err("id read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       DT_READ_U32(dnode, "flash_first_gpio", pdata->flash_first_gpio);
+       DT_READ_U32(dnode, "flash_second_gpio", pdata->flash_second_gpio);
+
+       ret = of_property_read_string(dnode, "sensor_name", &name);
+       if (ret) {
+               err("sensor_name read is fail(%d)", ret);
+               goto p_err;
+       }
+       strcpy(pdata->sensor_name, name);
+
+       ret = of_property_read_u32(dnode, "sensor_id", &pdata->sensor_id);
+       if (ret) {
+               err("sensor_id read is fail(%d)", ret);
+               goto p_err;
+       }
+
+       dev->platform_data = pdata;
+
+       ret = fimc_is_power_setpin(dev, id, pdata->sensor_id);
+       if (ret)
+               err("power_setpin failed(%d). id %d", ret, id);
+
+       pdev->id = id;
+
+       pdata->pinctrl = devm_pinctrl_get(dev);
+       if (IS_ERR(pdata->pinctrl)) {
+               err("devm_pinctrl_get is fail");
+               goto p_err;
+       } else {
+               ret = get_pin_lookup_state(dev, pdata);
+               if (ret < 0) {
+                       err("fimc_is_get_pin_lookup_state is fail");
+                       goto p_err;
+               }
+       }
+
+       return ret;
+
+p_err:
+       kfree(pdata);
+       return ret;
+}
+#else
+struct exynos_platform_fimc_is *fimc_is_parse_dt(struct device *dev)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-dt.h b/drivers/media/platform/exynos/fimc-is/fimc-is-dt.h
new file mode 100644 (file)
index 0000000..81b4591
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <mach/exynos-fimc-is-sensor.h>
+
+#ifndef FIMC_IS_DT_H
+#define FIMC_IS_DT_H
+
+#define DT_READ_U32(node, key, value) do {\
+               pprop = key; \
+               temp = 0; \
+               if (of_property_read_u32((node), key, &temp)) \
+                       pr_warn("%s: no property in the node.\n", pprop);\
+               (value) = temp; \
+       } while (0)
+
+#define DT_READ_STR(node, key, value) do {\
+               pprop = key; \
+               if (of_property_read_string((node), key, &name)) \
+                       pr_warn("%s: no property in the node.\n", pprop);\
+               (value) = name; \
+       } while (0)
+
+int get_pin_lookup_state(struct device *dev, struct exynos_platform_fimc_is_sensor *pdata);
+int fimc_is_power_initpin(struct device *dev);
+int fimc_is_power_setpin(struct device *dev, int position, int sensor_id);
+struct exynos_platform_fimc_is *fimc_is_parse_dt(struct device *dev);
+int fimc_is_sensor_parse_dt(struct platform_device *pdev);
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-dvfs.c b/drivers/media/platform/exynos/fimc-is/fimc-is-dvfs.c
new file mode 100644 (file)
index 0000000..48ef921
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/slab.h>
+#include "fimc-is-core.h"
+#include "fimc-is-dvfs.h"
+
+extern struct pm_qos_request exynos_isp_qos_cpu_min;
+extern struct pm_qos_request exynos_isp_qos_cpu_max;
+extern struct pm_qos_request exynos_isp_qos_int;
+extern struct pm_qos_request exynos_isp_qos_mem;
+extern struct pm_qos_request exynos_isp_qos_cam;
+extern struct pm_qos_request exynos_isp_qos_disp;
+
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_CAPTURE);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_CAMCORDING);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_PREVIEW);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_HIGH_SPEED_FPS);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_FHD);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_WHD);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_UHD);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_FHD);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_WHD);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_UHD);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_VT1);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_VT2);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_PREVIEW);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAPTURE);
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DIS_ENABLE);
+
+#if defined(ENABLE_DVFS)
+/*
+ * Static Scenario Set
+ * You should describe static scenario by priorities of scenario.
+ * And you should name array 'static_scenarios'
+ */
+static struct fimc_is_dvfs_scenario static_scenarios[] = {
+       {
+               .scenario_id            = FIMC_IS_SN_DUAL_CAMCORDING,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_DUAL_CAMCORDING),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_CAMCORDING),
+       }, {
+               .scenario_id            = FIMC_IS_SN_DUAL_PREVIEW,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_DUAL_PREVIEW),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_PREVIEW),
+       }, {
+               .scenario_id            = FIMC_IS_SN_HIGH_SPEED_FPS,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_HIGH_SPEED_FPS),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_HIGH_SPEED_FPS),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_CAMCORDING_FHD,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_CAMCORDING_FHD),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_FHD),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_CAMCORDING_WHD,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_CAMCORDING_WHD),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_WHD),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_CAMCORDING_UHD,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_CAMCORDING_UHD),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_UHD),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_PREVIEW_FHD,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_PREVIEW_FHD),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_FHD),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_PREVIEW_WHD,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_PREVIEW_WHD),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_WHD),
+       }, {
+               .scenario_id            = FIMC_IS_SN_REAR_PREVIEW_UHD,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_PREVIEW_UHD),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_UHD),
+       }, {
+               .scenario_id            = FIMC_IS_SN_FRONT_VT1,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_FRONT_VT1),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_VT1),
+       }, {
+               .scenario_id            = FIMC_IS_SN_FRONT_VT2,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_FRONT_VT2),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_VT2),
+       }, {
+               .scenario_id            = FIMC_IS_SN_FRONT_PREVIEW,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_FRONT_PREVIEW),
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_PREVIEW),
+       },
+};
+
+/*
+ * Dynamic Scenario Set
+ * You should describe static scenario by priorities of scenario.
+ * And you should name array 'dynamic_scenarios'
+ */
+static struct fimc_is_dvfs_scenario dynamic_scenarios[] = {
+       {
+               .scenario_id            = FIMC_IS_SN_DUAL_CAPTURE,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_DUAL_CAPTURE),
+               .keep_frame_tick        = KEEP_FRAME_TICK_DEFAULT,
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_CAPTURE),
+       },
+       {
+               .scenario_id            = FIMC_IS_SN_REAR_CAPTURE,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_REAR_CAPTURE),
+               .keep_frame_tick        = KEEP_FRAME_TICK_DEFAULT,
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAPTURE),
+       },
+       {
+               .scenario_id            = FIMC_IS_SN_DIS_ENABLE,
+               .scenario_nm            = DVFS_SN_STR(FIMC_IS_SN_DIS_ENABLE),
+               .keep_frame_tick        = KEEP_FRAME_TICK_DEFAULT,
+               .check_func             = GET_DVFS_CHK_FUNC(FIMC_IS_SN_DIS_ENABLE),
+       },
+};
+#else
+/*
+ * Default Scenario can not be seleted, this declaration is for static variable.
+ */
+static struct fimc_is_dvfs_scenario static_scenarios[] = {
+       {
+               .scenario_id            = FIMC_IS_SN_DEFAULT,
+               .scenario_nm            = NULL,
+               .keep_frame_tick        = 0,
+               .check_func             = NULL,
+       },
+};
+static struct fimc_is_dvfs_scenario dynamic_scenarios[] = {
+       {
+               .scenario_id            = FIMC_IS_SN_DEFAULT,
+               .scenario_nm            = NULL,
+               .keep_frame_tick        = 0,
+               .check_func             = NULL,
+       },
+};
+#endif
+
+static inline int fimc_is_get_open_sensor_cnt(struct fimc_is_core *core)
+{
+       int i, sensor_cnt = 0;
+
+       for (i = 0; i < FIMC_IS_MAX_NODES; i++)
+               if (test_bit(FIMC_IS_SENSOR_OPEN, &(core->sensor[i].state)))
+                       sensor_cnt++;
+
+       return sensor_cnt;
+}
+
+static inline u32 fimc_is_chk_req(struct fimc_is_frame *frame, enum fimc_is_video_dev_num vid)
+{
+       int i;
+       struct camera2_node *node;
+       u32 ret = 0;
+
+       if (frame == NULL)
+               return ret;
+
+       for (i = 0; i < CAPTURE_NODE_MAX; i++) {
+               node = &frame->shot_ext->node_group.capture[i];
+               if (node->vid == vid) {
+                       ret = node->request;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+/* dual capture */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_CAPTURE)
+{
+       struct fimc_is_core *core;
+       int sensor_cnt = 0;
+       core = (struct fimc_is_core *)device->interface->core;
+       sensor_cnt = fimc_is_get_open_sensor_cnt(core);
+
+       if ((sensor_cnt >= 2) &&
+                       (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)))
+               return 1;
+       else
+               return 0;
+}
+
+/* dual camcording */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_CAMCORDING)
+{
+       struct fimc_is_core *core;
+       int sensor_cnt = 0;
+       core = (struct fimc_is_core *)device->interface->core;
+       sensor_cnt = fimc_is_get_open_sensor_cnt(core);
+
+       if ((sensor_cnt >= 2) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        == ISS_SUB_SCENARIO_DUAL_VIDEO))
+               return 1;
+       else
+               return 0;
+}
+
+/* dual preview */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DUAL_PREVIEW)
+{
+       struct fimc_is_core *core;
+       int sensor_cnt = 0;
+       core = (struct fimc_is_core *)device->interface->core;
+       sensor_cnt = fimc_is_get_open_sensor_cnt(core);
+
+       if ((sensor_cnt >= 2) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        != ISS_SUB_SCENARIO_DUAL_VIDEO))
+               return 1;
+       else
+               return 0;
+}
+
+/* high speed fps */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_HIGH_SPEED_FPS)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) > 30))
+               return 1;
+       else
+               return 0;
+}
+
+/* rear camcording FHD with BNS off */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_FHD_BNS_OFF)
+{
+       u32 mask = (device->setfile & FIMC_IS_SETFILE_MASK);
+       bool setfile_flag = (mask == ISS_SUB_SCENARIO_VIDEO) ||
+                       (mask == ISS_SUB_SCENARIO_VIDEO_WDR);
+
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_FHD) &&
+                       (fimc_is_sensor_g_bns_ratio(device->sensor) <= 1000) &&
+                       setfile_flag)
+               return 1;
+       else
+               return 0;
+}
+
+/* rear camcording FHD*/
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_FHD)
+{
+       u32 mask = (device->setfile & FIMC_IS_SETFILE_MASK);
+       bool setfile_flag = (mask == ISS_SUB_SCENARIO_VIDEO) ||
+                       (mask == ISS_SUB_SCENARIO_VIDEO_WDR);
+
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_FHD) &&
+                       (fimc_is_sensor_g_bns_ratio(device->sensor) > 1000) &&
+                       setfile_flag)
+               return 1;
+       else
+               return 0;
+}
+
+/* rear camcording WHD*/
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_WHD)
+{
+       u32 mask = (device->setfile & FIMC_IS_SETFILE_MASK);
+       bool setfile_flag = (mask == ISS_SUB_SCENARIO_VIDEO) ||
+                       (mask == ISS_SUB_SCENARIO_VIDEO_WDR);
+
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height > SIZE_FHD) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_WHD) &&
+                       setfile_flag)
+               return 1;
+       else
+               return 0;
+}
+
+/* rear camcording UHD*/
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAMCORDING_UHD)
+{
+       u32 mask = (device->setfile & FIMC_IS_SETFILE_MASK);
+       bool setfile_flag = (mask == ISS_SUB_SCENARIO_UHD_30FPS) ||
+                       (mask == ISS_SUB_SCENARIO_UHD_30FPS_WDR);
+
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height > SIZE_WHD) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_UHD) &&
+                       setfile_flag)
+               return 1;
+       else
+               return 0;
+}
+
+/* rear preview FHD with BNS off */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_FHD_BNS_OFF)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_FHD) &&
+                       (fimc_is_sensor_g_bns_ratio(device->sensor) <= 1000) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        != ISS_SUB_SCENARIO_VIDEO))
+
+               return 1;
+       else
+               return 0;
+}
+
+/* rear preview FHD */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_FHD)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_FHD) &&
+                       (fimc_is_sensor_g_bns_ratio(device->sensor) > 1000) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        != ISS_SUB_SCENARIO_VIDEO))
+
+               return 1;
+       else
+               return 0;
+}
+
+/* rear preview WHD */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_WHD)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height > SIZE_FHD) &&
+                       (device->chain3_width * device->chain3_height <= SIZE_WHD) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        != ISS_SUB_SCENARIO_VIDEO))
+               return 1;
+       else
+               return 0;
+}
+
+/* rear preview UHD */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_PREVIEW_UHD)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       (fimc_is_sensor_g_framerate(device->sensor) <= 30) &&
+                       (device->chain3_width * device->chain3_height > SIZE_WHD) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        != ISS_SUB_SCENARIO_VIDEO))
+               return 1;
+       else
+               return 0;
+}
+
+/* front vt1 */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_VT1)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_FRONT) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        == ISS_SUB_SCENARIO_FRONT_VT1))
+               return 1;
+       else
+               return 0;
+}
+
+/* front vt2 */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_VT2)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_FRONT) &&
+                       ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                        == ISS_SUB_SCENARIO_FRONT_VT2))
+               return 1;
+       else
+               return 0;
+}
+
+/* front preview */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_FRONT_PREVIEW)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_FRONT) &&
+                       !(((device->setfile & FIMC_IS_SETFILE_MASK) \
+                                       == ISS_SUB_SCENARIO_FRONT_VT1) ||
+                               ((device->setfile & FIMC_IS_SETFILE_MASK) \
+                                == ISS_SUB_SCENARIO_FRONT_VT2)))
+               return 1;
+       else
+               return 0;
+}
+
+/* rear capture */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_REAR_CAPTURE)
+{
+       if ((device->sensor->pdev->id == SENSOR_POSITION_REAR) &&
+                       ((test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) ||
+                       fimc_is_chk_req(frame, FIMC_IS_VIDEO_SCC_NUM)))
+               return 1;
+       else
+               return 0;
+}
+
+/* dis */
+DECLARE_DVFS_CHK_FUNC(FIMC_IS_SN_DIS_ENABLE)
+{
+       if (test_bit(FIMC_IS_SUBDEV_START, &device->dis.state))
+               return 1;
+       else
+               return 0;
+}
+
+static int fimc_is_set_pwm(struct fimc_is_device_ischain *device, u32 pwm_qos)
+{
+       int ret = 0;
+       u32 base_addr;
+       void __iomem *addr;
+
+       base_addr = GET_FIMC_IS_ADDR_OF_SUBIP2(device, pwm);
+
+       if (base_addr) {
+               addr = ioremap(base_addr + FIMC_IS_PWM_TCNTB0, SZ_4);
+               writel(pwm_qos, addr);
+               dbg("PWM SFR Read(%08X), pwm_qos(%08X)\n", readl(addr), pwm_qos);
+               iounmap(addr);
+       }
+
+       return ret;
+}
+
+int fimc_is_dvfs_init(struct fimc_is_resourcemgr *resourcemgr)
+{
+       int i;
+       pr_info("%s\n", __func__);
+
+       BUG_ON(!resourcemgr);
+
+       resourcemgr->dvfs_ctrl.cur_cpu_min_qos = 0;
+       resourcemgr->dvfs_ctrl.cur_cpu_max_qos = 0;
+       resourcemgr->dvfs_ctrl.cur_int_qos = 0;
+       resourcemgr->dvfs_ctrl.cur_mif_qos = 0;
+       resourcemgr->dvfs_ctrl.cur_cam_qos = 0;
+       resourcemgr->dvfs_ctrl.cur_i2c_qos = 0;
+       resourcemgr->dvfs_ctrl.cur_disp_qos = 0;
+
+       /* init spin_lock for clock gating */
+       mutex_init(&resourcemgr->dvfs_ctrl.lock);
+
+       if (!(resourcemgr->dvfs_ctrl.static_ctrl))
+               resourcemgr->dvfs_ctrl.static_ctrl =
+                       kzalloc(sizeof(struct fimc_is_dvfs_scenario_ctrl), GFP_KERNEL);
+       if (!(resourcemgr->dvfs_ctrl.dynamic_ctrl))
+               resourcemgr->dvfs_ctrl.dynamic_ctrl =
+                       kzalloc(sizeof(struct fimc_is_dvfs_scenario_ctrl), GFP_KERNEL);
+
+       if (!resourcemgr->dvfs_ctrl.static_ctrl || !resourcemgr->dvfs_ctrl.dynamic_ctrl) {
+               err("dvfs_ctrl alloc is failed!!\n");
+               return -ENOMEM;
+       }
+
+       /* set priority by order */
+       for (i = 0; i < ARRAY_SIZE(static_scenarios); i++)
+               static_scenarios[i].priority = i;
+       for (i = 0; i < ARRAY_SIZE(dynamic_scenarios); i++)
+               dynamic_scenarios[i].priority = i;
+
+       resourcemgr->dvfs_ctrl.static_ctrl->cur_scenario_id     = -1;
+       resourcemgr->dvfs_ctrl.static_ctrl->cur_scenario_idx    = -1;
+       resourcemgr->dvfs_ctrl.static_ctrl->scenarios           = static_scenarios;
+       if (static_scenarios[0].scenario_id == FIMC_IS_SN_DEFAULT)
+               resourcemgr->dvfs_ctrl.static_ctrl->scenario_cnt        = 0;
+       else
+               resourcemgr->dvfs_ctrl.static_ctrl->scenario_cnt        = ARRAY_SIZE(static_scenarios);
+
+       resourcemgr->dvfs_ctrl.dynamic_ctrl->cur_scenario_id    = -1;
+       resourcemgr->dvfs_ctrl.dynamic_ctrl->cur_scenario_idx   = -1;
+       resourcemgr->dvfs_ctrl.dynamic_ctrl->cur_frame_tick     = -1;
+       resourcemgr->dvfs_ctrl.dynamic_ctrl->scenarios          = dynamic_scenarios;
+       if (static_scenarios[0].scenario_id == FIMC_IS_SN_DEFAULT)
+               resourcemgr->dvfs_ctrl.dynamic_ctrl->scenario_cnt       = 0;
+       else
+               resourcemgr->dvfs_ctrl.dynamic_ctrl->scenario_cnt       = ARRAY_SIZE(dynamic_scenarios);
+
+       return 0;
+}
+
+int fimc_is_dvfs_sel_scenario(u32 type, struct fimc_is_device_ischain *device, struct fimc_is_frame *frame)
+{
+       struct fimc_is_dvfs_ctrl *dvfs_ctrl;
+       struct fimc_is_dvfs_scenario_ctrl *static_ctrl, *dynamic_ctrl;
+       struct fimc_is_dvfs_scenario *scenarios;
+       struct fimc_is_dvfs_scenario *cur_scenario;
+       struct fimc_is_resourcemgr *resourcemgr;
+       int i, scenario_id, scenario_cnt;
+
+       if (device == NULL) {
+               err("device is NULL\n");
+               return -EINVAL;
+       }
+
+       resourcemgr = device->resourcemgr;
+       dvfs_ctrl = &(resourcemgr->dvfs_ctrl);
+       static_ctrl = dvfs_ctrl->static_ctrl;
+       dynamic_ctrl = dvfs_ctrl->dynamic_ctrl;
+
+       if (type == FIMC_IS_DYNAMIC_SN) {
+               /* dynamic scenario */
+               if (!dynamic_ctrl) {
+                       err("dynamic_dvfs_ctrl is NULL\n");
+                       return -EINVAL;
+               }
+
+               if (dynamic_ctrl->scenario_cnt == 0) {
+                       pr_debug("dynamic_scenario's count is jero\n");
+                       return -EINVAL;
+               }
+
+               scenarios = dynamic_ctrl->scenarios;
+               scenario_cnt = dynamic_ctrl->scenario_cnt;
+
+               if (dynamic_ctrl->cur_frame_tick >= 0) {
+                       (dynamic_ctrl->cur_frame_tick)--;
+                       /*
+                        * when cur_frame_tick is lower than 0, clear current scenario.
+                        * This means that current frame tick to keep dynamic scenario
+                        * was expired.
+                        */
+                       if (dynamic_ctrl->cur_frame_tick < 0) {
+                               dynamic_ctrl->cur_scenario_id = -1;
+                               dynamic_ctrl->cur_scenario_idx = -1;
+                       }
+               }
+       } else {
+               /* static scenario */
+               if (!static_ctrl) {
+                       err("static_dvfs_ctrl is NULL\n");
+                       return -EINVAL;
+               }
+
+               if (static_ctrl->scenario_cnt == 0) {
+                       pr_debug("static_scenario's count is jero\n");
+                       return -EINVAL;
+               }
+
+               scenarios = static_ctrl->scenarios;
+               scenario_cnt = static_ctrl->scenario_cnt;
+       }
+
+       for (i = 0; i < scenario_cnt; i++) {
+               if (!scenarios[i].check_func) {
+                       warn("check_func[%d] is NULL\n", i);
+                       continue;
+               }
+
+               if ((scenarios[i].check_func(device, frame)) > 0) {
+                       scenario_id = scenarios[i].scenario_id;
+
+                       if (type == FIMC_IS_DYNAMIC_SN) {
+                               cur_scenario = &scenarios[dynamic_ctrl->cur_scenario_idx];
+
+                               /*
+                                * if condition 1 or 2 is true
+                                * condition 1 : There's no dynamic scenario applied.
+                                * condition 2 : Finded scenario's prority was higher than current
+                                */
+                               if ((dynamic_ctrl->cur_scenario_id <= 0) ||
+                                               (scenarios[i].priority < (cur_scenario->priority))) {
+                                       dynamic_ctrl->cur_scenario_id = scenarios[i].scenario_id;
+                                       dynamic_ctrl->cur_scenario_idx = i;
+                                       dynamic_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick;
+                               } else {
+                                       /* if finded scenario is same */
+                                       if (scenarios[i].priority == (cur_scenario->priority))
+                                               dynamic_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick;
+                                       return -EAGAIN;
+                               }
+                       } else {
+                               static_ctrl->cur_scenario_id = scenario_id;
+                               static_ctrl->cur_scenario_idx = i;
+                               static_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick;
+                       }
+
+                       return scenario_id;
+               }
+       }
+
+       if (type == FIMC_IS_DYNAMIC_SN)
+               return -EAGAIN;
+
+       {
+               struct fimc_is_core *core;
+               int sensor_cnt = 0;
+               core = (struct fimc_is_core *)device->interface->core;
+               sensor_cnt = fimc_is_get_open_sensor_cnt(core);
+
+               warn("couldn't find static dvfs scenario [sensor:(%d/%d)/fps:%d/setfile:%d/scp size:(%d/%d)]\n",
+                       sensor_cnt,
+                       device->sensor->pdev->id,
+                       fimc_is_sensor_g_framerate(device->sensor),
+                       (device->setfile & FIMC_IS_SETFILE_MASK),
+                       device->chain3_width,
+                       device->chain3_height);
+       }
+
+       static_ctrl->cur_scenario_id = FIMC_IS_SN_DEFAULT;
+       static_ctrl->cur_scenario_idx = -1;
+       static_ctrl->cur_frame_tick = -1;
+
+       return FIMC_IS_SN_DEFAULT;
+}
+
+int fimc_is_get_qos(struct fimc_is_core *core, u32 type, u32 scenario_id)
+{
+       struct exynos_platform_fimc_is  *pdata = NULL;
+       int qos = 0;
+
+       pdata = core->pdata;
+       if (pdata == NULL) {
+               err("pdata is NULL\n");
+               return -EINVAL;
+       }
+
+       if (!pdata->get_int_qos || !pdata->get_mif_qos)
+               goto struct_qos;
+
+       switch (type) {
+               case FIMC_IS_DVFS_INT:
+                       qos = pdata->get_int_qos(scenario_id);
+                       break;
+               case FIMC_IS_DVFS_MIF:
+                       qos = pdata->get_mif_qos(scenario_id);
+                       break;
+               case FIMC_IS_DVFS_I2C:
+                       if (pdata->get_i2c_qos)
+                               qos = pdata->get_i2c_qos(scenario_id);
+                       break;
+       }
+       goto exit;
+
+struct_qos:
+       if (max(0, (int)type) >= FIMC_IS_DVFS_END) {
+               err("Cannot find DVFS value");
+               return -EINVAL;
+       }
+
+       qos = pdata->dvfs_data[scenario_id][type];
+
+exit:
+       return qos;
+}
+
+int fimc_is_set_dvfs(struct fimc_is_device_ischain *device, u32 scenario_id)
+{
+       int ret = 0;
+       int cpu_min_qos, cpu_max_qos, int_qos, mif_qos, i2c_qos, cam_qos, disp_qos, pwm_qos = 0;
+       int refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_resourcemgr *resourcemgr;
+       struct fimc_is_dvfs_ctrl *dvfs_ctrl;
+
+       if (device == NULL) {
+               err("device is NULL\n");
+               return -EINVAL;
+       }
+
+       core = (struct fimc_is_core *)device->interface->core;
+       resourcemgr = device->resourcemgr;
+       dvfs_ctrl = &(resourcemgr->dvfs_ctrl);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount < 0) {
+               err("invalid ischain refcount");
+               goto exit;
+       }
+
+       cpu_min_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CPU_MIN, scenario_id);
+       cpu_max_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CPU_MAX, scenario_id);
+       int_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_INT, scenario_id);
+       mif_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_MIF, scenario_id);
+       i2c_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_I2C, scenario_id);
+       cam_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CAM, scenario_id);
+       disp_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_DISP, scenario_id);
+       pwm_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_PWM, scenario_id);
+
+       if ((int_qos < 0) || (mif_qos < 0) || (i2c_qos < 0)
+       || (cam_qos < 0) || (disp_qos < 0) || (pwm_qos < 0)) {
+               err("getting qos value is failed!!\n");
+               return -EINVAL;
+       }
+
+       if (dvfs_ctrl->cur_cpu_min_qos != cpu_min_qos) {
+               pm_qos_update_request(&exynos_isp_qos_cpu_min, cpu_min_qos);
+               dvfs_ctrl->cur_cpu_min_qos = cpu_min_qos;
+       }
+
+       if (dvfs_ctrl->cur_cpu_max_qos != cpu_max_qos) {
+               pm_qos_update_request(&exynos_isp_qos_cpu_max, cpu_max_qos);
+               dvfs_ctrl->cur_cpu_max_qos = cpu_max_qos;
+       }
+
+       /* check current qos */
+       if (int_qos && dvfs_ctrl->cur_int_qos != int_qos) {
+               if (i2c_qos) {
+                       ret = fimc_is_itf_i2c_lock(device, i2c_qos, true);
+                       if (ret) {
+                               err("fimc_is_itf_i2_clock fail\n");
+                               goto exit;
+                       }
+               }
+
+               if (pwm_qos) {
+                       fimc_is_set_pwm(device, pwm_qos);
+                       if (ret) {
+                               err("fimc_is_set_pwm fail\n");
+                               goto exit;
+                       }
+               }
+
+               pm_qos_update_request(&exynos_isp_qos_int, int_qos);
+               dvfs_ctrl->cur_int_qos = int_qos;
+
+               if (i2c_qos) {
+                       /* i2c unlock */
+                       ret = fimc_is_itf_i2c_lock(device, i2c_qos, false);
+                       if (ret) {
+                               err("fimc_is_itf_i2c_unlock fail\n");
+                               goto exit;
+                       }
+               }
+       }
+
+       if (mif_qos && dvfs_ctrl->cur_mif_qos != mif_qos) {
+               pm_qos_update_request(&exynos_isp_qos_mem, mif_qos);
+               dvfs_ctrl->cur_mif_qos = mif_qos;
+       }
+
+       if (cam_qos && dvfs_ctrl->cur_cam_qos != cam_qos) {
+               pm_qos_update_request(&exynos_isp_qos_cam, cam_qos);
+               dvfs_ctrl->cur_cam_qos = cam_qos;
+       }
+
+       if (disp_qos && dvfs_ctrl->cur_disp_qos != disp_qos) {
+               pm_qos_update_request(&exynos_isp_qos_disp, disp_qos);
+               dvfs_ctrl->cur_disp_qos = disp_qos;
+       }
+
+       dbg("[RSC:%d]: New QoS [INT(%d), MIF(%d), CAM(%d), DISP(%d), I2C(%d), PWM(%d) CPU(%d/%d)]\n",
+                       device->instance, int_qos, mif_qos,
+                       cam_qos, disp_qos, i2c_qos, pwm_qos, cpu_min_qos, cpu_max_qos);
+exit:
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-dvfs.h b/drivers/media/platform/exynos/fimc-is/fimc-is-dvfs.h
new file mode 100644 (file)
index 0000000..6ffd9e4
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DVFS_H
+#define FIMC_IS_DVFS_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include "fimc-is-time.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-groupmgr.h"
+#include "fimc-is-device-ischain.h"
+
+#define KEEP_FRAME_TICK_DEFAULT (5)
+#define DVFS_SN_STR(__SCENARIO) #__SCENARIO
+#define GET_DVFS_CHK_FUNC(__SCENARIO) check_ ## __SCENARIO
+#define DECLARE_DVFS_CHK_FUNC(__SCENARIO) \
+       int check_ ## __SCENARIO \
+               (struct fimc_is_device_ischain *device, struct fimc_is_frame *frame, ...)
+
+#define SIZE_FHD (1920 * 1080)
+#define SIZE_WHD (2560 * 1440)
+#define SIZE_UHD (3840 * 2160)
+
+enum FIMC_IS_DVFS_SCENARIO_TYPE {
+       FIMC_IS_STATIC_SN,
+       FIMC_IS_DYNAMIC_SN,
+};
+
+struct fimc_is_dvfs_scenario {
+       u32 scenario_id;        /* scenario_id */
+       char *scenario_nm;      /* string of scenario_id */
+       int priority;           /* priority for dynamic scenario */
+       int keep_frame_tick;    /* keep qos lock during specific frames when dynamic scenario */
+
+       /* function pointer to check a scenario */
+       int (*check_func)(struct fimc_is_device_ischain *device,
+                       struct fimc_is_frame *frame, ...);
+};
+
+struct fimc_is_dvfs_scenario_ctrl {
+       int cur_scenario_id;    /* selected scenario idx */
+       int cur_frame_tick;     /* remained frame tick to keep qos lock in dynamic scenario */
+       int scenario_cnt;       /* total scenario count */
+       int cur_scenario_idx;   /* selected scenario idx for scenarios */
+       struct fimc_is_dvfs_scenario *scenarios;
+};
+
+int fimc_is_dvfs_init(struct fimc_is_resourcemgr *resourcemgr);
+int fimc_is_dvfs_sel_scenario(u32 type,        struct fimc_is_device_ischain *device, struct fimc_is_frame *frame);
+int fimc_is_get_qos(struct fimc_is_core *core, u32 type, u32 scenario_id);
+int fimc_is_set_dvfs(struct fimc_is_device_ischain *device, u32 scenario_id);
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-err.h b/drivers/media/platform/exynos/fimc-is/fimc-is-err.h
new file mode 100644 (file)
index 0000000..c83edfe
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_ERR_H
+#define FIMC_IS_ERR_H
+
+#define IS_ERROR_VER 014 /* IS ERROR VERSION 0.14 */
+
+#define IS_ERROR_SUCCESS               0
+/* General 1 ~ 100 */
+#define IS_ERROR_INVALID_COMMAND        (IS_ERROR_SUCCESS+1)
+#define IS_ERROR_REQUEST_FAIL           (IS_ERROR_INVALID_COMMAND+1)
+#define IS_ERROR_INVALID_SCENARIO       (IS_ERROR_REQUEST_FAIL+1)
+#define IS_ERROR_INVALID_SENSORID       (IS_ERROR_INVALID_SCENARIO+1)
+#define IS_ERROR_INVALID_MODE_CHANGE    (IS_ERROR_INVALID_SENSORID+1)
+#define IS_ERROR_INVALID_MAGIC_NUMBER  (IS_ERROR_INVALID_MODE_CHANGE+1)
+#define IS_ERROR_INVALID_SETFILE_HDR   (IS_ERROR_INVALID_MAGIC_NUMBER+1)
+#define IS_ERROR_ISP_SETFILE_VERSION_MISMATCH  (IS_ERROR_INVALID_SETFILE_HDR+1)
+#define IS_ERROR_ISP_SETFILE_REVISION_MISMATCH\
+                               (IS_ERROR_ISP_SETFILE_VERSION_MISMATCH+1)
+#define IS_ERROR_BUSY (IS_ERROR_ISP_SETFILE_REVISION_MISMATCH+1)
+#define IS_ERROR_SET_PARAMETER          (IS_ERROR_BUSY+1)
+#define IS_ERROR_INVALID_PATH           (IS_ERROR_SET_PARAMETER+1)
+#define IS_ERROR_OPEN_SENSOR_FAIL       (IS_ERROR_INVALID_PATH+1)
+#define IS_ERROR_ENTRY_MSG_THREAD_DOWN (IS_ERROR_OPEN_SENSOR_FAIL+1)
+#define IS_ERROR_ISP_FRAME_END_NOT_DONE        (IS_ERROR_ENTRY_MSG_THREAD_DOWN+1)
+#define IS_ERROR_DRC_FRAME_END_NOT_DONE        (IS_ERROR_ISP_FRAME_END_NOT_DONE+1)
+#define IS_ERROR_SCALERC_FRAME_END_NOT_DONE (IS_ERROR_DRC_FRAME_END_NOT_DONE+1)
+#define IS_ERROR_DIS_FRAME_END_NOT_DONE (IS_ERROR_SCALERC_FRAME_END_NOT_DONE+1)
+#define IS_ERROR_TDNR_FRAME_END_NOT_DONE (IS_ERROR_DIS_FRAME_END_NOT_DONE+1)
+#define IS_ERROR_SCALERP_FRAME_END_NOT_DONE (IS_ERROR_TDNR_FRAME_END_NOT_DONE+1)
+#define IS_ERROR_WAIT_STREAM_OFF_NOT_DONE\
+                               (IS_ERROR_SCALERP_FRAME_END_NOT_DONE+1)
+#define IS_ERROR_NO_MSG_IS_RECEIVED     (IS_ERROR_WAIT_STREAM_OFF_NOT_DONE+1)
+#define IS_ERROR_SENSOR_MSG_FAIL           (IS_ERROR_NO_MSG_IS_RECEIVED+1)
+#define IS_ERROR_ISP_MSG_FAIL          (IS_ERROR_SENSOR_MSG_FAIL+1)
+#define IS_ERROR_DRC_MSG_FAIL          (IS_ERROR_ISP_MSG_FAIL+1)
+#define IS_ERROR_SCALERC_MSG_FAIL              (IS_ERROR_DRC_MSG_FAIL+1)
+#define IS_ERROR_DIS_MSG_FAIL          (IS_ERROR_ODC_MSG_FAIL+1)
+#define IS_ERROR_TDNR_MSG_FAIL         (IS_ERROR_DIS_MSG_FAIL+1)
+#define IS_ERROR_SCALERP_MSG_FAIL              (IS_ERROR_TDNR_MSG_FAIL+1)
+#define IS_ERROR_LHFD_MSG_FAIL         (IS_ERROR_SCALERP_MSG_FAIL+1)
+#define IS_ERROR_INTERNAL_STOP          (IS_ERROR_LHFD_MSG_FAIL+1)
+#define IS_ERROR_UNKNOWN                1000
+#define IS_ERROR_TIME_OUT_FLAG          0x80000000
+
+/* Sensor 100 ~ 200 */
+#define IS_ERROR_SENSOR_PWRDN_FAIL     100
+#define IS_ERROR_SENSOR_STREAM_ON_FAIL (IS_ERROR_SENSOR_PWRDN_FAIL+1)
+#define IS_ERROR_SENSOR_STREAM_OFF_FAIL        (IS_ERROR_SENSOR_STREAM_ON_FAIL+1)
+
+/* ISP 200 ~ 300 */
+#define IS_ERROR_ISP_PWRDN_FAIL                200
+#define IS_ERROR_ISP_MULTIPLE_INPUT    (IS_ERROR_ISP_PWRDN_FAIL+1)
+#define IS_ERROR_ISP_ABSENT_INPUT      (IS_ERROR_ISP_MULTIPLE_INPUT+1)
+#define IS_ERROR_ISP_ABSENT_OUTPUT     (IS_ERROR_ISP_ABSENT_INPUT+1)
+#define IS_ERROR_ISP_NONADJACENT_OUTPUT        (IS_ERROR_ISP_ABSENT_OUTPUT+1)
+#define IS_ERROR_ISP_FORMAT_MISMATCH   (IS_ERROR_ISP_NONADJACENT_OUTPUT+1)
+#define IS_ERROR_ISP_WIDTH_MISMATCH    (IS_ERROR_ISP_FORMAT_MISMATCH+1)
+#define IS_ERROR_ISP_HEIGHT_MISMATCH   (IS_ERROR_ISP_WIDTH_MISMATCH+1)
+#define IS_ERROR_ISP_BITWIDTH_MISMATCH (IS_ERROR_ISP_HEIGHT_MISMATCH+1)
+#define IS_ERROR_ISP_FRAME_END_TIME_OUT        (IS_ERROR_ISP_BITWIDTH_MISMATCH+1)
+
+/* DRC 300 ~ 400 */
+#define IS_ERROR_DRC_PWRDN_FAIL                300
+#define IS_ERROR_DRC_MULTIPLE_INPUT    (IS_ERROR_DRC_PWRDN_FAIL+1)
+#define IS_ERROR_DRC_ABSENT_INPUT      (IS_ERROR_DRC_MULTIPLE_INPUT+1)
+#define IS_ERROR_DRC_NONADJACENT_INTPUT        (IS_ERROR_DRC_ABSENT_INPUT+1)
+#define IS_ERROR_DRC_ABSENT_OUTPUT     (IS_ERROR_DRC_NONADJACENT_INTPUT+1)
+#define IS_ERROR_DRC_NONADJACENT_OUTPUT        (IS_ERROR_DRC_ABSENT_OUTPUT+1)
+#define IS_ERROR_DRC_FORMAT_MISMATCH   (IS_ERROR_DRC_NONADJACENT_OUTPUT+1)
+#define IS_ERROR_DRC_WIDTH_MISMATCH    (IS_ERROR_DRC_FORMAT_MISMATCH+1)
+#define IS_ERROR_DRC_HEIGHT_MISMATCH   (IS_ERROR_DRC_WIDTH_MISMATCH+1)
+#define IS_ERROR_DRC_BITWIDTH_MISMATCH (IS_ERROR_DRC_HEIGHT_MISMATCH+1)
+#define IS_ERROR_DRC_FRAME_END_TIME_OUT        (IS_ERROR_DRC_BITWIDTH_MISMATCH+1)
+
+/*SCALERC(400~500)*/
+#define IS_ERROR_SCALERC_PWRDN_FAIL     400
+
+/*DIS(600~700)*/
+#define IS_ERROR_DIS_PWRDN_FAIL         600
+
+/*TDNR(700~800)\r*/
+#define IS_ERROR_TDNR_PWRDN_FAIL        700
+
+/*SCALERP(800~900)*/
+#define IS_ERROR_SCALERP_PWRDN_FAIL     800
+
+/*FD(900~1000)*/
+#define IS_ERROR_FD_PWRDN_FAIL          900
+#define IS_ERROR_FD_MULTIPLE_INPUT     (IS_ERROR_FD_PWRDN_FAIL+1)
+#define IS_ERROR_FD_ABSENT_INPUT       (IS_ERROR_FD_MULTIPLE_INPUT+1)
+#define IS_ERROR_FD_NONADJACENT_INPUT  (IS_ERROR_FD_ABSENT_INPUT+1)
+#define IS_ERROR_LHFD_FRAME_END_TIME_OUT \
+                                       (IS_ERROR_FD_NONADJACENT_INPUT+1)
+
+/* Set parameter error enum */
+enum error {
+       /* Common error (0~99) */
+       ERROR_COMMON_NO                 = 0,
+       ERROR_COMMON_CMD                = 1,    /* Invalid command*/
+       ERROR_COMMON_PARAMETER          = 2,    /* Invalid parameter*/
+       /* setfile is not loaded before adjusting */
+       ERROR_COMMON_SETFILE_LOAD       = 3,
+       /* setfile is not Adjusted before runnng. */
+       ERROR_COMMON_SETFILE_ADJUST     = 4,
+       /* index of setfile is not valid. */
+       ERROR_COMMON_SETFILE_INDEX = 5,
+       /* Input path can be changed in ready state(stop) */
+       ERROR_COMMON_INPUT_PATH         = 6,
+       /* IP can not start if input path is not set */
+       ERROR_COMMON_INPUT_INIT         = 7,
+       /* Output path can be changed in ready state(stop) */
+       ERROR_COMMON_OUTPUT_PATH        = 8,
+       /* IP can not start if output path is not set */
+       ERROR_COMMON_OUTPUT_INIT        = 9,
+
+       ERROR_CONTROL_NO                = ERROR_COMMON_NO,
+       ERROR_CONTROL_BYPASS            = 11,   /* Enable or Disable */
+       ERROR_CONTROL_BUF               = 12,   /* invalid buffer info */
+
+       ERROR_OTF_INPUT_NO              = ERROR_COMMON_NO,
+       /* invalid command */
+       ERROR_OTF_INPUT_CMD             = 21,
+       /* invalid format  (DRC: YUV444, FD: YUV444, 422, 420) */
+       ERROR_OTF_INPUT_FORMAT          = 22,
+       /* invalid width (DRC: 128~8192, FD: 32~8190) */
+       ERROR_OTF_INPUT_WIDTH           = 23,
+       /* invalid height (DRC: 64~8192, FD: 16~8190) */
+       ERROR_OTF_INPUT_HEIGHT          = 24,
+       /* invalid bit-width (DRC: 8~12bits, FD: 8bit) */
+       ERROR_OTF_INPUT_BIT_WIDTH       = 25,
+       /* invalid frame time for ISP */
+       ERROR_OTF_INPUT_USER_FRAMETILE = 26,
+
+       ERROR_DMA_INPUT_NO              = ERROR_COMMON_NO,
+       /* invalid width (DRC: 128~8192, FD: 32~8190) */
+       ERROR_DMA_INPUT_WIDTH           = 31,
+       /* invalid height (DRC: 64~8192, FD: 16~8190) */
+       ERROR_DMA_INPUT_HEIGHT          = 32,
+       /* invalid format (DRC: YUV444 or YUV422, FD: YUV444, 422, 420) */
+       ERROR_DMA_INPUT_FORMAT          = 33,
+       /* invalid bit-width (DRC: 8~12bit, FD: 8bit) */
+       ERROR_DMA_INPUT_BIT_WIDTH       = 34,
+       /* invalid order(DRC: YYCbCrorYCbYCr, FD:NO,YYCbCr,YCbYCr,CbCr,CrCb) */
+       ERROR_DMA_INPUT_ORDER           = 35,
+       /* invalid palne (DRC: 3, FD: 1, 2, 3) */
+       ERROR_DMA_INPUT_PLANE           = 36,
+
+       ERROR_OTF_OUTPUT_NO             = ERROR_COMMON_NO,
+       /* invalid width (DRC: 128~8192) */
+       ERROR_OTF_OUTPUT_WIDTH          = 41,
+       /* invalid height (DRC: 64~8192) */
+       ERROR_OTF_OUTPUT_HEIGHT         = 42,
+       /* invalid format (DRC: YUV444) */
+       ERROR_OTF_OUTPUT_FORMAT         = 43,
+       /* invalid bit-width (DRC: 8~12bits) */
+       ERROR_OTF_OUTPUT_BIT_WIDTH      = 44,
+       /* invalid crop size (ODC: left>2, right>10) */
+       ERROR_OTF_OUTPUT_CROP           = 45,
+
+       ERROR_DMA_OUTPUT_NO             = ERROR_COMMON_NO,
+       ERROR_DMA_OUTPUT_WIDTH          = 51,   /* invalid width */
+       ERROR_DMA_OUTPUT_HEIGHT         = 52,   /* invalid height */
+       ERROR_DMA_OUTPUT_FORMAT         = 53,   /* invalid format */
+       ERROR_DMA_OUTPUT_BIT_WIDTH      = 54,   /* invalid bit-width */
+       ERROR_DMA_OUTPUT_PLANE          = 55,   /* invalid plane */
+       ERROR_DMA_OUTPUT_ORDER          = 56,   /* invalid order */
+       ERROR_DMA_OUTPUT_BUF            = 57,   /* invalid buffer info */
+
+       ERROR_GLOBAL_SHOTMODE_NO        = ERROR_COMMON_NO,
+
+       /* SENSOR Error(100~199) */
+       ERROR_SENSOR_NO                 = ERROR_COMMON_NO,
+       ERROR_SENSOR_I2C_FAIL           = 101,
+       ERROR_SENSOR_INVALID_FRAMERATE,
+       ERROR_SENSOR_INVALID_EXPOSURETIME,
+       ERROR_SENSOR_INVALID_SIZE,
+       ERROR_SENSOR_ACTURATOR_INIT_FAIL,
+       ERROR_SENSOR_INVALID_AF_POS,
+       ERROR_SENSOR_UNSUPPORT_FUNC,
+       ERROR_SENSOR_UNSUPPORT_PERI,
+       ERROR_SENSOR_UNSUPPORT_AF,
+       ERROR_SENSOR_FLASH_FAIL,
+       ERROR_SENSOR_START_FAIL,
+       ERROR_SENSOR_STOP_FAIL,
+
+       /* ISP Error (200~299) */
+       ERROR_ISP_AF_NO                 = ERROR_COMMON_NO,
+       ERROR_ISP_AF_BUSY               = 201,
+       ERROR_ISP_AF_INVALID_COMMAND    = 202,
+       ERROR_ISP_AF_INVALID_MODE       = 203,
+       ERROR_ISP_FLASH_NO              = ERROR_COMMON_NO,
+       ERROR_ISP_AWB_NO                = ERROR_COMMON_NO,
+       ERROR_ISP_IMAGE_EFFECT_NO       = ERROR_COMMON_NO,
+       ERROR_ISP_IMAGE_EFFECT_INVALID  = 231,
+       ERROR_ISP_ISO_NO                = ERROR_COMMON_NO,
+       ERROR_ISP_ADJUST_NO             = ERROR_COMMON_NO,
+       ERROR_ISP_METERING_NO           = ERROR_COMMON_NO,
+       ERROR_ISP_AFC_NO                = ERROR_COMMON_NO,
+
+       /* DRC Error (300~399) */
+
+       /* FD Error  (400~499) */
+       ERROR_FD_NO                                     = ERROR_COMMON_NO,
+       /* Invalid max number (1~16) */
+       ERROR_FD_CONFIG_MAX_NUMBER_STATE                = 401,
+       ERROR_FD_CONFIG_MAX_NUMBER_INVALID              = 402,
+       ERROR_FD_CONFIG_YAW_ANGLE_STATE                 = 403,
+       ERROR_FD_CONFIG_YAW_ANGLE_INVALID               = 404,
+       ERROR_FD_CONFIG_ROLL_ANGLE_STATE                = 405,
+       ERROR_FD_CONFIG_ROLL_ANGLE_INVALID              = 406,
+       ERROR_FD_CONFIG_SMILE_MODE_INVALID              = 407,
+       ERROR_FD_CONFIG_BLINK_MODE_INVALID              = 408,
+       ERROR_FD_CONFIG_EYES_DETECT_INVALID             = 409,
+       ERROR_FD_CONFIG_MOUTH_DETECT_INVALID            = 410,
+       ERROR_FD_CONFIG_ORIENTATION_STATE               = 411,
+       ERROR_FD_CONFIG_ORIENTATION_INVALID             = 412,
+       ERROR_FD_CONFIG_ORIENTATION_VALUE_INVALID       = 413,
+       /* PARAM_FdResultStr can be only applied
+        * in ready-state or stream off */
+       ERROR_FD_RESULT                         = 414,
+       /* PARAM_FdModeStr can be only applied
+        * in ready-state or stream off */
+       ERROR_FD_MODE                                   = 415,
+
+       /*SCALER ERR(500~599)*/
+       ERROR_SCALER_NO                 = ERROR_COMMON_NO,
+       ERROR_SCALER_DMA_OUTSEL         = 501,
+       ERROR_SCALER_H_RATIO                    = 502,
+       ERROR_SCALER_V_RATIO                    = 503,
+       ERROR_SCALER_FRAME_BUFFER_SEQ           = 504,
+
+       ERROR_SCALER_IMAGE_EFFECT               = 510,
+
+       ERROR_SCALER_ROTATE                     = 520,
+       ERROR_SCALER_FLIP                       = 521,
+
+};
+
+enum ShotErrorType {
+       IS_SHOT_SUCCESS = 0,
+       /* Un-known state.(Normally under processing.) */
+       IS_SHOT_UNKNOWN,
+       /* Bad frame. Ndone is occured at provious group. */
+       IS_SHOT_BAD_FRAME,
+       /* Metadata is not valid. For example, sirc sdk's fd is not valid. */
+       IS_SHOT_CORRUPTED_FRAME,
+       /* Processing of previous group is not complete. */
+       IS_SHOT_EARLY_FRAME,
+       /* Shot is too late at OTF mode. */
+       IS_SHOT_LATE_FRAME,
+       /* Shot is coming when group is process-stop. */
+       IS_SHOT_GROUP_PROCESSSTOP,
+       /* Frame number is not allocated. */
+       IS_SHOT_INVALID_FRAMENUMBER,
+       /* Overflow is occred during processing. */
+       IS_SHOT_OVERFLOW,
+       /* Shot is time-out during processing.(Unknown reason.) */
+       IS_SHOT_SAME_FRAME_COUNT,
+       /* Shot is time-out during processing.(Unknown reason.) */
+       IS_SHOT_TIMEOUT,
+       /* Shot is droped at BufferEntry. */
+       IS_SHOT_DROP,
+       IS_SHOT_3AA_FRAME_END,
+       IS_SHOT_IP_CLOCK_OFF,
+       IS_SHOT_ENDPROC_DELAY
+};
+
+enum REPORT_ERR_TYPE {
+       REPORT_ERR_CIS_ID = 0,
+       REPORT_ERR_CIS_CRC = 1,
+       REPORT_ERR_CIS_ECC = 2,
+       REPORT_ERR_CIS_OVERFLOW_VC0 = 3,
+       REPORT_ERR_CIS_LOST_FE_VC0 = 4,
+       REPORT_ERR_CIS_LOST_FS_VC0 = 5,
+       REPORT_ERR_CIS_SOT_VC0 = 6,
+       REPORT_ERR_CIS_SOT_VC1 = 7,
+       REPORT_ERR_CIS_SOT_VC2 = 8,
+       REPORT_ERR_CIS_SOT_VC3 = 9,
+       REPORT_ERR_3AA_OVERFLOW = 10,
+       REPORT_ERR_FLITE_D_OVERFLOW = 11,
+       REPORT_ERR_COMPANION_LOST_FRAME = 12,
+       REPORT_ERR_3A_ALGORITHM_DELAYED = 13,
+       REPORT_ERR_END
+};
+
+#define ENOBASE_IS             0x10000
+#define        ENOSHOT                 (ENOBASE_IS + 1) /* shot error */
+#define ENOMDONE               (ENOBASE_IS + 2) /* meta done error */
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-fan53555.c b/drivers/media/platform/exynos/fimc-is/fimc-is-fan53555.c
new file mode 100644 (file)
index 0000000..7f76409
--- /dev/null
@@ -0,0 +1,117 @@
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include "fimc-is-fan53555.h"
+
+/**
+ * FAN53555 Vout Tables
+ */
+static const struct fan53555_vout vout_tables[] = {
+       {0, FAN53555_VOUT_1P00, "1.00"}, /* defualt voltage */
+       {1, FAN53555_VOUT_0P88, "0.88"},
+       {2, FAN53555_VOUT_0P90, "0.90"},
+       {3, FAN53555_VOUT_0P93, "0.93"},
+       {4, FAN53555_VOUT_0P95, "0.95"},
+       {5, FAN53555_VOUT_0P98, "0.98"},
+       {6, FAN53555_VOUT_1P00, "1.00"},
+};
+
+/**
+ * fan53555_get_vout_val: get i2c register value to set vout of dcdc regulator.
+ */
+int fan53555_get_vout_val(int sel)
+{
+       int i, vout = vout_tables[0].val;
+
+       if (sel < 0)
+               pr_err("%s: error, invalid sel %d\n", __func__, sel);
+
+       for (i = 0; ARRAY_SIZE(vout_tables); i++) {
+               if (vout_tables[i].sel == sel) {
+                       return vout_tables[i].val;
+               }
+       }
+
+       pr_err("%s: warning, default voltage selected. sel %d\n", __func__, sel);
+
+       return vout;
+}
+
+/**
+ * fan53555_get_vout_name: get voltage name of vout as string.
+ */
+ const char *fan53555_get_vout_str(int sel)
+{
+       const char *vout = vout_tables[0].vout;
+       int i;
+
+       if (sel < 0)
+               pr_err("%s: error, invalid sel %d\n", __func__, sel);
+
+       for (i = 0; ARRAY_SIZE(vout_tables); i++) {
+               if (vout_tables[i].sel == sel) {
+                       return vout_tables[i].vout;
+               }
+       }
+
+       pr_err("%s: warning, default voltage selected. sel %d\n", __func__, sel);
+
+       return vout;
+}
+
+int fan53555_enable_vsel0(struct i2c_client *client, int on_off)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(client, REG_VSEL0);
+       if(ret < 0){
+               pr_err("%s: read error = %d , try again", __func__, ret);
+               ret = i2c_smbus_read_byte_data(client, REG_VSEL0);
+               if (ret < 0)
+                       pr_err("%s: read 2nd error = %d", __func__, ret);
+       }
+
+       ret &= (~VSEL0_BUCK_EN0);
+       ret |= (on_off << VSEL0_BUCK_EN0_SHIFT);
+
+       ret = i2c_smbus_write_byte_data(client, REG_VSEL0, (BYTE)ret);
+       if (ret < 0){
+               pr_err("%s: write error = %d , try again", __func__, ret);
+               ret = i2c_smbus_write_byte_data(client, REG_VSEL0, (BYTE)ret);
+               if (ret < 0)
+                       pr_err("%s: write 2nd error = %d", __func__, ret);
+       }
+       return ret;
+}
+
+/**
+ * fan53555_set_vsel0_vout: set dcdc vout with i2c register value.
+ */
+int fan53555_set_vsel0_vout(struct i2c_client *client, int vout)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(client, REG_VSEL0);
+       if(ret < 0){
+               pr_err("%s: read error = %d , try again", __func__, ret);
+               ret = i2c_smbus_read_byte_data(client, REG_VSEL0);
+               if (ret < 0)
+                       pr_err("%s: read 2nd error = %d", __func__, ret);
+       }
+
+       ret &= (~VSEL0_NSEL0);
+       ret |= vout;
+
+       ret = i2c_smbus_write_byte_data(client, REG_VSEL0, (BYTE)ret);
+       if (ret < 0){
+               pr_err("%s: write error = %d , try again", __func__, ret);
+               ret = i2c_smbus_write_byte_data(client, REG_VSEL0, (BYTE)ret);
+               if (ret < 0)
+                       pr_err("%s: write 2nd error = %d", __func__, ret);
+       }
+       return ret;
+}
+
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-fan53555.h b/drivers/media/platform/exynos/fimc-is/fimc-is-fan53555.h
new file mode 100644 (file)
index 0000000..24e5f91
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "fimc-is-core.h"
+
+typedef unsigned char BYTE;
+
+#define REG_VSEL0              0x00
+#define VSEL0_NSEL0            0x3f
+#define VSEL0_BUCK_EN0_SHIFT   7
+#define VSEL0_BUCK_EN0         (0x01 << VSEL0_BUCK_EN0_SHIFT)
+#define VSEL0_INIT_VAL         VSEL0_BUCK_EN0 | FAN53555_VOUT_1P00
+
+// FAN53555UC08X : Vout = 0.60V + NSELx * 10mV
+enum{
+    FAN53555_VOUT_0P60 = 0,
+       FAN53555_VOUT_0P61,
+       FAN53555_VOUT_0P62,
+       FAN53555_VOUT_0P63,
+       FAN53555_VOUT_0P64,
+       FAN53555_VOUT_0P65,
+       FAN53555_VOUT_0P66,
+       FAN53555_VOUT_0P67,
+       FAN53555_VOUT_0P68,
+       FAN53555_VOUT_0P69,
+
+       FAN53555_VOUT_0P70 = 10,
+       FAN53555_VOUT_0P71,
+       FAN53555_VOUT_0P72,
+       FAN53555_VOUT_0P73,
+       FAN53555_VOUT_0P74,
+       FAN53555_VOUT_0P75,
+       FAN53555_VOUT_0P76,
+       FAN53555_VOUT_0P77,
+       FAN53555_VOUT_0P78,
+       FAN53555_VOUT_0P79,
+
+       FAN53555_VOUT_0P80 = 20,
+       FAN53555_VOUT_0P81,
+       FAN53555_VOUT_0P82,
+       FAN53555_VOUT_0P83,
+       FAN53555_VOUT_0P84,
+       FAN53555_VOUT_0P85,
+       FAN53555_VOUT_0P86,
+       FAN53555_VOUT_0P87,
+       FAN53555_VOUT_0P88,
+       FAN53555_VOUT_0P89,
+
+       FAN53555_VOUT_0P90 = 30,
+       FAN53555_VOUT_0P91,
+       FAN53555_VOUT_0P92,
+       FAN53555_VOUT_0P93,
+       FAN53555_VOUT_0P94,
+       FAN53555_VOUT_0P95,
+       FAN53555_VOUT_0P96,
+       FAN53555_VOUT_0P97,
+       FAN53555_VOUT_0P98,
+       FAN53555_VOUT_0P99,
+
+       FAN53555_VOUT_1P00 = 40,
+       FAN53555_VOUT_1P01,
+       FAN53555_VOUT_1P02,  // VSEL0 default, 08X
+       FAN53555_VOUT_1P03,
+       FAN53555_VOUT_1P04,
+       FAN53555_VOUT_1P05,
+       FAN53555_VOUT_1P06,
+       FAN53555_VOUT_1P07,
+       FAN53555_VOUT_1P08,
+       FAN53555_VOUT_1P09,
+
+       FAN53555_VOUT_1P10 = 50,
+       FAN53555_VOUT_1P11,
+       FAN53555_VOUT_1P12,
+       FAN53555_VOUT_1P13,
+       FAN53555_VOUT_1P14,
+       FAN53555_VOUT_1P15,  // VSEL1 default, 08X
+       FAN53555_VOUT_1P16,
+       FAN53555_VOUT_1P17,
+       FAN53555_VOUT_1P18,
+       FAN53555_VOUT_1P19,
+
+       FAN53555_VOUT_1P20 = 60,
+       FAN53555_VOUT_1P21,
+       FAN53555_VOUT_1P22,
+       FAN53555_VOUT_1P23,
+};
+
+struct fan53555_vout {
+       int sel;        /* selector, unique value for vout entry and indepedant to dcdc vendor */
+       int val;        /* dcdc-specific value for vout register */
+       char vout[7];   /* voltage level string */
+};
+
+int fan53555_get_vout_val(int sel);
+const char *fan53555_get_vout_str(int sel);
+int fan53555_enable_vsel0(struct i2c_client *client, int on_off);
+int fan53555_set_vsel0_vout(struct i2c_client *client, int vout);
+
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-framemgr.c b/drivers/media/platform/exynos/fimc-is/fimc-is-framemgr.c
new file mode 100644 (file)
index 0000000..ccb74e5
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+
+#include "fimc-is-device-sensor.h"
+
+int fimc_is_frame_s_free_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (item) {
+               item->state = FIMC_IS_FRAME_STATE_FREE;
+
+               list_add_tail(&item->list, &this->frame_free_head);
+               this->frame_fre_cnt++;
+
+#ifdef TRACE_FRAME
+               fimc_is_frame_print_free_list(this);
+#endif
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+
+int fimc_is_frame_g_free_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       int ret = 0;
+
+       if (item) {
+               if (this->frame_fre_cnt) {
+                       *item = container_of(this->frame_free_head.next,
+                               struct fimc_is_frame, list);
+                       list_del(&(*item)->list);
+                       this->frame_fre_cnt--;
+
+                       (*item)->state = FIMC_IS_FRAME_STATE_INVALID;
+               } else {
+                       *item = NULL;
+               }
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+void fimc_is_frame_free_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       if (this->frame_fre_cnt)
+               *item = container_of(this->frame_free_head.next,
+                       struct fimc_is_frame, list);
+       else
+               *item = NULL;
+}
+
+void fimc_is_frame_print_free_list(struct fimc_is_framemgr *this)
+{
+       struct list_head *temp;
+       struct fimc_is_frame *shot;
+
+       if (!(TRACE_ID & this->id))
+               return;
+
+       printk(KERN_ERR "[FRM] fre(%d, %d) :", this->id, this->frame_fre_cnt);
+
+       list_for_each(temp, &this->frame_free_head) {
+               shot = list_entry(temp, struct fimc_is_frame, list);
+               printk(KERN_CONT "%d->", shot->index);
+       }
+
+       printk(KERN_CONT "X\n");
+}
+
+int fimc_is_frame_s_request_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (item) {
+               list_add_tail(&item->list, &this->frame_request_head);
+               this->frame_req_cnt++;
+
+               item->state = FIMC_IS_FRAME_STATE_REQUEST;
+
+#ifdef TRACE_FRAME
+               fimc_is_frame_print_request_list(this);
+#endif
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+int fimc_is_frame_g_request_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       int ret = 0;
+
+       if (item) {
+               if (this->frame_req_cnt) {
+                       *item = container_of(this->frame_request_head.next,
+                               struct fimc_is_frame, list);
+                       list_del(&(*item)->list);
+                       this->frame_req_cnt--;
+
+                       (*item)->state = FIMC_IS_FRAME_STATE_INVALID;
+               } else {
+                       *item = NULL;
+               }
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+void fimc_is_frame_request_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       if (this->frame_req_cnt)
+               *item = container_of(this->frame_request_head.next,
+                       struct fimc_is_frame, list);
+       else
+               *item = NULL;
+}
+
+void fimc_is_frame_print_request_list(struct fimc_is_framemgr *this)
+{
+       struct list_head *temp;
+       struct fimc_is_frame *shot;
+
+       if (!(TRACE_ID & this->id))
+               return;
+
+       printk(KERN_ERR "[FRM] req(%d, %d) :",
+               this->id, this->frame_req_cnt);
+
+       list_for_each(temp, &this->frame_request_head) {
+               shot = list_entry(temp, struct fimc_is_frame, list);
+               printk(KERN_CONT "%d->", shot->index);
+       }
+
+       printk(KERN_CONT "X\n");
+}
+
+int fimc_is_frame_s_process_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (item) {
+               list_add_tail(&item->list, &this->frame_process_head);
+               this->frame_pro_cnt++;
+
+               item->state = FIMC_IS_FRAME_STATE_PROCESS;
+
+#ifdef TRACE_FRAME
+               fimc_is_frame_print_process_list(this);
+#endif
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+int fimc_is_frame_g_process_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       int ret = 0;
+
+       if (item) {
+               if (this->frame_pro_cnt) {
+                       *item = container_of(this->frame_process_head.next,
+                               struct fimc_is_frame, list);
+                       list_del(&(*item)->list);
+                       this->frame_pro_cnt--;
+
+                       (*item)->state = FIMC_IS_FRAME_STATE_INVALID;
+               } else {
+                       *item = NULL;
+               }
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+void fimc_is_frame_process_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       if (this->frame_pro_cnt)
+               *item = container_of(this->frame_process_head.next,
+                       struct fimc_is_frame, list);
+       else
+               *item = NULL;
+}
+
+void fimc_is_frame_print_process_list(struct fimc_is_framemgr *this)
+{
+       struct list_head *temp;
+       struct fimc_is_frame *shot;
+
+       if (!(TRACE_ID & this->id))
+               return;
+
+       printk(KERN_ERR "[FRM] pro(%d, %d) :",
+               this->id, this->frame_pro_cnt);
+
+       list_for_each(temp, &this->frame_process_head) {
+               shot = list_entry(temp, struct fimc_is_frame, list);
+               printk(KERN_CONT "%d(%d)->", shot->index, shot->fcount);
+       }
+
+       printk(KERN_CONT "X\n");
+}
+
+int fimc_is_frame_s_complete_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (item) {
+               list_add_tail(&item->list, &this->frame_complete_head);
+               this->frame_com_cnt++;
+
+               item->state = FIMC_IS_FRAME_STATE_COMPLETE;
+
+#ifdef TRACE_FRAME
+               fimc_is_frame_print_complete_list(this);
+#endif
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+
+int fimc_is_frame_g_complete_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       int ret = 0;
+
+       if (item) {
+               if (this->frame_com_cnt) {
+                       *item = container_of(this->frame_complete_head.next,
+                               struct fimc_is_frame, list);
+                       list_del(&(*item)->list);
+                       this->frame_com_cnt--;
+
+                       (*item)->state = FIMC_IS_FRAME_STATE_INVALID;
+               } else {
+                       *item = NULL;
+               }
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+void fimc_is_frame_complete_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **item)
+{
+       if (this->frame_com_cnt)
+               *item = container_of(this->frame_complete_head.next,
+                       struct fimc_is_frame, list);
+       else
+               *item = NULL;
+}
+
+void fimc_is_frame_print_complete_list(struct fimc_is_framemgr *this)
+{
+       struct list_head *temp;
+       struct fimc_is_frame *shot;
+
+       if (!(TRACE_ID & this->id))
+               return;
+
+       printk(KERN_ERR "[FRM] com(%d, %d) :",
+               this->id, this->frame_com_cnt);
+
+       list_for_each(temp, &this->frame_complete_head) {
+               shot = list_entry(temp, struct fimc_is_frame, list);
+               printk(KERN_CONT "%d->", shot->index);
+       }
+
+       printk(KERN_CONT "X\n");
+}
+
+int fimc_is_frame_trans_fre_to_req(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_fre_cnt) {
+               err("shot free count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_fre_cnt--;
+
+       fimc_is_frame_s_request_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_req_to_pro(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_req_cnt) {
+               err("shot request count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_req_cnt--;
+
+       fimc_is_frame_s_process_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_req_to_com(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_req_cnt) {
+               err("shot request count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_req_cnt--;
+
+       fimc_is_frame_s_complete_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_req_to_fre(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_req_cnt) {
+               err("shot request count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_req_cnt--;
+
+       fimc_is_frame_s_free_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_pro_to_com(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_pro_cnt) {
+               err("shot process count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_pro_cnt--;
+
+       fimc_is_frame_s_complete_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_pro_to_fre(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_pro_cnt) {
+               err("shot process count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_pro_cnt--;
+
+       fimc_is_frame_s_free_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_fre_to_com(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_fre_cnt) {
+               err("shot free count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_fre_cnt--;
+
+       fimc_is_frame_s_complete_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_trans_com_to_fre(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item)
+{
+       int ret = 0;
+
+       if (!this->frame_com_cnt) {
+               err("shot complete count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       this->frame_com_cnt--;
+
+       fimc_is_frame_s_free_shot(this, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_swap_process_head(struct fimc_is_framemgr *this)
+{
+       int ret = 0;
+       struct fimc_is_frame *head;
+       struct fimc_is_frame *next;
+
+       if (!this->frame_pro_cnt) {
+               err("shot process count is zero\n");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       fimc_is_frame_process_head(this, &head);
+
+       list_del(&head->list);
+       this->frame_pro_cnt--;
+
+       /* list swap operation */
+       fimc_is_frame_process_head(this, &next);
+       if (next) {
+               list_del(&next->list);
+               this->frame_pro_cnt--;
+               fimc_is_frame_s_process_shot(this, next);
+               head->has_fcount = false;
+       }
+
+       fimc_is_frame_s_process_shot(this, head);
+
+exit:
+       return ret;
+}
+
+int fimc_is_frame_probe(struct fimc_is_framemgr *this, u32 id)
+{
+       int ret = 0;
+
+       this->id = id;
+       spin_lock_init(&this->slock);
+
+       return ret;
+}
+
+int fimc_is_frame_open(struct fimc_is_framemgr *this, u32 buffers)
+{
+       int ret = 0;
+       u32 i, j;
+
+       INIT_LIST_HEAD(&this->frame_free_head);
+       INIT_LIST_HEAD(&this->frame_request_head);
+       INIT_LIST_HEAD(&this->frame_process_head);
+       INIT_LIST_HEAD(&this->frame_complete_head);
+
+       this->frame_cnt = buffers;
+       this->frame_fre_cnt = 0;
+       this->frame_req_cnt = 0;
+       this->frame_pro_cnt = 0;
+       this->frame_com_cnt = 0;
+
+       for (i = 0; i < buffers; ++i) {
+               clear_bit(FRAME_INI_MEM, &this->frame[i].memory);
+               clear_bit(FRAME_MAP_MEM, &this->frame[i].memory);
+               this->frame[i].work_data1 = NULL;
+               this->frame[i].work_data2 = NULL;
+               this->frame[i].index = i;
+               this->frame[i].fcount = 0;
+               this->frame[i].rcount = 0;
+               this->frame[i].req_flag = 0;
+               this->frame[i].out_flag = 0;
+
+               this->frame[i].vb = NULL;
+               this->frame[i].shot = NULL;
+               this->frame[i].shot_ext = NULL;
+               this->frame[i].shot_size = 0;
+
+               this->frame[i].stream = NULL;
+               this->frame[i].stream_size = 0;
+
+               this->frame[i].planes = 0;
+               for (j = 0; j < FIMC_IS_MAX_PLANES; ++j) {
+                       this->frame[i].kvaddr_buffer[j] = 0;
+                       this->frame[i].dvaddr_buffer[j] = 0;
+               }
+
+               this->frame[i].kvaddr_shot = 0;
+               this->frame[i].dvaddr_shot = 0;
+               this->frame[i].has_fcount = false;
+               fimc_is_frame_s_free_shot(this, &this->frame[i]);
+       }
+
+       return ret;
+}
+
+int fimc_is_frame_close(struct fimc_is_framemgr *this)
+{
+       int ret = 0;
+       u32 buffers;
+       u32 i, j;
+
+       buffers = this->frame_cnt;
+
+       for (i = 0; i < buffers; ++i) {
+               clear_bit(FRAME_INI_MEM, &this->frame[i].memory);
+               clear_bit(FRAME_MAP_MEM, &this->frame[i].memory);
+               this->frame[i].index = i;
+               this->frame[i].fcount = 0;
+               this->frame[i].rcount = 0;
+               this->frame[i].req_flag = 0;
+
+               this->frame[i].vb = NULL;
+               this->frame[i].shot = NULL;
+               this->frame[i].shot_ext = NULL;
+               this->frame[i].shot_size = 0;
+
+               this->frame[i].stream = NULL;
+               this->frame[i].stream_size = 0;
+
+               this->frame[i].planes = 0;
+               for (j = 0; j < FIMC_IS_MAX_PLANES; ++j) {
+                       this->frame[i].kvaddr_buffer[j] = 0;
+                       this->frame[i].dvaddr_buffer[j] = 0;
+               }
+
+               this->frame[i].kvaddr_shot = 0;
+               this->frame[i].dvaddr_shot = 0;
+               this->frame[i].has_fcount = false;
+       }
+
+       return ret;
+}
+
+void fimc_is_frame_print_all(struct fimc_is_framemgr *this)
+{
+       fimc_is_frame_print_free_list(this);
+       fimc_is_frame_print_request_list(this);
+       fimc_is_frame_print_process_list(this);
+       fimc_is_frame_print_complete_list(this);
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-framemgr.h b/drivers/media/platform/exynos/fimc-is/fimc-is-framemgr.h
new file mode 100644 (file)
index 0000000..7b373ca
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/kthread.h>
+
+#ifndef FIMC_IS_FRAME_MGR_H
+#define FIMC_IS_FRAME_MGR_H
+
+#define FIMC_IS_MAX_BUFS            VIDEO_MAX_FRAME
+#define FIMC_IS_MAX_PLANES          VIDEO_MAX_PLANES
+
+#define FRAMEMGR_ID_INVALID    0x000000
+#define FRAMEMGR_ID_SENSOR     0x000100
+#define FRAMEMGR_ID_3AA_GRP    0x000200
+#define FRAMEMGR_ID_3AAC       0x000400
+#define FRAMEMGR_ID_3AAP       0x000800
+#define FRAMEMGR_ID_ISP_GRP    0x001000
+#define FRAMEMGR_ID_SCC                0x002000
+#define FRAMEMGR_ID_DIS                0x004000
+#define FRAMEMGR_ID_DIS_GRP    0x008000
+#define FRAMEMGR_ID_SCP                0x010000
+#define FRAMEMGR_ID_SHOT       (FRAMEMGR_ID_SENSOR | FRAMEMGR_ID_3AA_GRP | \
+                               FRAMEMGR_ID_ISP_GRP | FRAMEMGR_ID_DIS_GRP)
+#define FRAMEMGR_ID_STREAM     (FRAMEMGR_ID_3AAC | FRAMEMGR_ID_3AAP | \
+                               FRAMEMGR_ID_SCC | FRAMEMGR_ID_DIS | \
+                               FRAMEMGR_ID_SCP)
+/* #define TRACE_FRAME */
+#define TRACE_ID               (FRAMEMGR_ID_SHOT | FRAMEMGR_ID_STREAM)
+
+#define FRAMEMGR_MAX_REQUEST   VIDEO_MAX_FRAME
+
+/*flite frame start tasklet*/
+#define FMGR_IDX_0             (0x10)
+/*flite frame end tasklet*/
+#define FMGR_IDX_1             (0x20)
+/*sensor queue*/
+#define FMGR_IDX_2             (0x30)
+/*sensor dequeue*/
+#define FMGR_IDX_3             (0x40)
+/*dev framedone*/
+#define FMGR_IDX_4             (0x50)
+/*scc framedone*/
+#define FMGR_IDX_5             (0x60)
+/*scp framedone*/
+#define FMGR_IDX_6             (0x70)
+/*isp framedone*/
+#define FMGR_IDX_7             (0x80)
+/*scc callback*/
+#define FMGR_IDX_8             (0x90)
+/*scp callback*/
+#define FMGR_IDX_9             (0xA0)
+/*3a0c callback*/
+#define FMGR_IDX_10            (0xB0)
+/*3a1c callback*/
+#define FMGR_IDX_11            (0xC0)
+
+#define framemgr_e_barrier_irqs(this, index, flag) \
+       spin_lock_irqsave(&this->slock, flag)
+#define framemgr_x_barrier_irqr(this, index, flag) \
+       spin_unlock_irqrestore(&this->slock, flag)
+#define framemgr_e_barrier_irq(this, index) \
+       spin_lock_irq(&this->slock)
+#define framemgr_x_barrier_irq(this, index) \
+       spin_unlock_irq(&this->slock)
+#define framemgr_e_barrier(this, index) \
+       spin_lock(&this->slock)
+#define framemgr_x_barrier(this, index) \
+       spin_unlock(&this->slock)
+
+enum fimc_is_frame_shot_state {
+       FIMC_IS_FRAME_STATE_FREE,
+       FIMC_IS_FRAME_STATE_REQUEST,
+       FIMC_IS_FRAME_STATE_PROCESS,
+       FIMC_IS_FRAME_STATE_COMPLETE,
+       FIMC_IS_FRAME_STATE_INVALID
+};
+
+enum fimc_is_frame_reqeust {
+       /* SCC, SCP frame done,
+          ISP meta done */
+       REQ_FRAME,
+       /* 3AA shot done */
+       REQ_3AA_SHOT,
+       /* ISP shot done */
+       REQ_ISP_SHOT,
+       /* DIS shot done */
+       REQ_DIS_SHOT
+};
+
+enum fimc_is_frame_output {
+       /* 3AAC frame done */
+       OUT_3AAC_FRAME,
+       /* 3AAP frame done */
+       OUT_3AAP_FRAME,
+       /* SCC frame done */
+       OUT_SCC_FRAME,
+       /* DIS frame done */
+       OUT_DIS_FRAME,
+       /* SCP frame done */
+       OUT_SCP_FRAME
+};
+
+enum fimc_is_frame_mem {
+       /* initialized memory */
+       FRAME_INI_MEM,
+       /* mapped memory */
+       FRAME_MAP_MEM
+};
+
+struct fimc_is_frame {
+       struct list_head        list;
+       struct kthread_work     work;
+       void                    *work_data1;
+       void                    *work_data2;
+
+       /* group leader use */
+       struct camera2_shot     *shot;
+       struct camera2_shot_ext *shot_ext;
+       u32                     kvaddr_shot;
+       u32                     dvaddr_shot;
+       u32                     cookie_shot;
+       u32                     shot_size;
+
+       /* stream use */
+       struct camera2_stream   *stream;
+       u32                     stream_size;
+
+       /* common use */
+       u32                     planes;
+       u32                     kvaddr_buffer[FIMC_IS_MAX_PLANES];
+       u32                     dvaddr_buffer[FIMC_IS_MAX_PLANES];
+
+       /* internal use */
+       unsigned long           memory;
+       u32                     state;
+       u32                     fcount;
+       u32                     rcount;
+       u32                     index;
+       unsigned long           req_flag;
+       unsigned long           out_flag;
+       struct vb2_buffer       *vb;
+
+       /* for overwriting framecount check */
+       bool                    has_fcount;
+
+       /* time measure externally */
+       struct timeval          *tzone;
+       /* time measure internally */
+       struct timeval          time_queued;
+       struct timeval          time_shot;
+       struct timeval          time_shotdone;
+       struct timeval          time_dequeued;
+};
+
+struct fimc_is_framemgr {
+       struct fimc_is_frame    frame[FRAMEMGR_MAX_REQUEST];
+
+       struct list_head        frame_free_head;
+       struct list_head        frame_request_head;
+       struct list_head        frame_process_head;
+       struct list_head        frame_complete_head;
+
+       spinlock_t              slock;
+
+       u32                     frame_cnt;
+       u32                     frame_fre_cnt;
+       u32                     frame_req_cnt;
+       u32                     frame_pro_cnt;
+       u32                     frame_com_cnt;
+
+       u32                     id;
+};
+
+int fimc_is_frame_probe(struct fimc_is_framemgr *this, u32 id);
+int fimc_is_frame_open(struct fimc_is_framemgr *this, u32 buffers);
+int fimc_is_frame_close(struct fimc_is_framemgr *this);
+void fimc_is_frame_print_all(struct fimc_is_framemgr *this);
+
+int fimc_is_frame_s_free_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_g_free_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_free_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_print_free_list(struct fimc_is_framemgr *this);
+
+int fimc_is_frame_s_request_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_g_request_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_request_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_print_request_list(struct fimc_is_framemgr *this);
+
+int fimc_is_frame_s_process_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_g_process_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_process_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_print_process_list(struct fimc_is_framemgr *this);
+
+int fimc_is_frame_s_complete_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_g_complete_shot(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_complete_head(struct fimc_is_framemgr *this,
+       struct fimc_is_frame **frame);
+void fimc_is_frame_print_complete_list(struct fimc_is_framemgr *this);
+
+int fimc_is_frame_trans_fre_to_req(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_trans_fre_to_com(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_trans_req_to_pro(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_trans_req_to_com(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_trans_req_to_fre(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *item);
+int fimc_is_frame_trans_pro_to_com(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_trans_pro_to_fre(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+int fimc_is_frame_trans_com_to_fre(struct fimc_is_framemgr *this,
+       struct fimc_is_frame *frame);
+
+int fimc_is_frame_swap_process_head(struct fimc_is_framemgr *this);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-groupmgr.c b/drivers/media/platform/exynos/fimc-is/fimc-is-groupmgr.c
new file mode 100644 (file)
index 0000000..7223243
--- /dev/null
@@ -0,0 +1,1932 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-framemgr.h"
+#include "fimc-is-groupmgr.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-dvfs.h"
+
+/* sysfs variable for debug */
+extern struct fimc_is_sysfs_debug sysfs_debug;
+
+static void fimc_is_gframe_s_info(struct fimc_is_group_frame *item,
+       u32 group_id, struct fimc_is_frame *frame)
+{
+       BUG_ON(!item);
+       BUG_ON(!frame);
+       BUG_ON(!frame->shot_ext);
+
+       memcpy(&item->group_cfg[group_id], &frame->shot_ext->node_group,
+               sizeof(struct camera2_node_group));
+}
+
+static void fimc_is_gframe_free_head(struct fimc_is_group_framemgr *framemgr,
+       struct fimc_is_group_frame **item)
+{
+       if (framemgr->frame_free_cnt)
+               *item = container_of(framemgr->frame_free_head.next,
+                       struct fimc_is_group_frame, list);
+       else
+               *item = NULL;
+}
+
+static void fimc_is_gframe_s_free(struct fimc_is_group_framemgr *framemgr,
+       struct fimc_is_group_frame *item)
+{
+       BUG_ON(!framemgr);
+       BUG_ON(!item);
+
+       list_add_tail(&item->list, &framemgr->frame_free_head);
+       framemgr->frame_free_cnt++;
+}
+
+static void fimc_is_gframe_print_free(struct fimc_is_group_framemgr *framemgr)
+{
+       struct list_head *temp;
+       struct fimc_is_group_frame *gframe;
+
+       BUG_ON(!framemgr);
+
+       printk(KERN_ERR "[GFRM] fre(%d) :", framemgr->frame_free_cnt);
+
+       list_for_each(temp, &framemgr->frame_free_head) {
+               gframe = list_entry(temp, struct fimc_is_group_frame, list);
+               printk(KERN_CONT "%d->", gframe->fcount);
+       }
+
+       printk(KERN_CONT "X\n");
+}
+
+static void fimc_is_gframe_group_head(struct fimc_is_group *group,
+       struct fimc_is_group_frame **item)
+{
+       if (group->frame_group_cnt)
+               *item = container_of(group->frame_group_head.next,
+                       struct fimc_is_group_frame, list);
+       else
+               *item = NULL;
+}
+
+static void fimc_is_gframe_s_group(struct fimc_is_group *group,
+       struct fimc_is_group_frame *item)
+{
+       BUG_ON(!group);
+       BUG_ON(!item);
+
+       list_add_tail(&item->list, &group->frame_group_head);
+       group->frame_group_cnt++;
+}
+
+static void fimc_is_gframe_print_group(struct fimc_is_group *group)
+{
+       struct list_head *temp;
+       struct fimc_is_group_frame *gframe;
+
+       BUG_ON(!group);
+
+       printk(KERN_ERR "[GFRM] req(%d, %d) :", group->id, group->frame_group_cnt);
+
+       list_for_each(temp, &group->frame_group_head) {
+               gframe = list_entry(temp, struct fimc_is_group_frame, list);
+               printk(KERN_CONT "%d->", gframe->fcount);
+       }
+
+       printk(KERN_CONT "X\n");
+}
+
+static int fimc_is_gframe_trans_fre_to_grp(struct fimc_is_group_framemgr *prev,
+       struct fimc_is_group *next,
+       struct fimc_is_group_frame *item)
+{
+       int ret = 0;
+
+       BUG_ON(!prev);
+       BUG_ON(!next);
+       BUG_ON(!item);
+
+       if (!prev->frame_free_cnt) {
+               err("frame_free_cnt is zero");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       prev->frame_free_cnt--;
+
+       fimc_is_gframe_s_group(next, item);
+
+exit:
+       return ret;
+}
+
+static int fimc_is_gframe_trans_grp_to_grp(struct fimc_is_group *prev,
+       struct fimc_is_group *next,
+       struct fimc_is_group_frame *item)
+{
+       int ret = 0;
+       u32 *input_crop, *output_crop;
+
+       BUG_ON(!prev);
+       BUG_ON(!next);
+       BUG_ON(!item);
+
+       if (!prev->frame_group_cnt) {
+               err("frame_group_cnt is zero");
+               ret = -EFAULT;
+               goto p_err;
+       }
+
+       list_del(&item->list);
+       prev->frame_group_cnt--;
+
+       fimc_is_gframe_s_group(next, item);
+
+       if (item->group_cfg[prev->id].capture[0].vid == next->source_vid) {
+               output_crop = item->group_cfg[prev->id].capture[0].output.cropRegion;
+               input_crop = item->group_cfg[next->id].leader.input.cropRegion;
+       } else if (item->group_cfg[prev->id].capture[1].vid == next->source_vid) {
+               output_crop = item->group_cfg[prev->id].capture[1].output.cropRegion;
+               input_crop = item->group_cfg[next->id].leader.input.cropRegion;
+       } else {
+               merr("vid(%d) is invalid", prev, next->source_vid);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if ((output_crop[0] != input_crop[0]) || (output_crop[1] != input_crop[1]) ||
+               (output_crop[2] != input_crop[2]) || (output_crop[3] != input_crop[3])) {
+               mwarn("GRP%d & GRP%d is incoincidence((%d,%d,%d,%d) != (%d,%d,%d,%d))",
+                       prev, prev->id, next->id,
+                       output_crop[0], output_crop[1], output_crop[2], output_crop[3],
+                       input_crop[0], input_crop[1], input_crop[2], input_crop[3]);
+               input_crop[0] = output_crop[0];
+               input_crop[1] = output_crop[1];
+               input_crop[2] = output_crop[2];
+               input_crop[3] = output_crop[3];
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_gframe_trans_grp_to_fre(struct fimc_is_group *prev,
+       struct fimc_is_group_framemgr *next,
+       struct fimc_is_group_frame *item)
+{
+       int ret = 0;
+
+       BUG_ON(!prev);
+       BUG_ON(!next);
+       BUG_ON(!item);
+
+       if (!prev->frame_group_cnt) {
+               err("frame_group_cnt is zero");
+               ret = -EFAULT;
+               goto exit;
+       }
+
+       list_del(&item->list);
+       prev->frame_group_cnt--;
+
+       fimc_is_gframe_s_free(next, item);
+
+exit:
+       return ret;
+}
+
+int fimc_is_gframe_cancel(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 target_fcount)
+{
+       int ret = -EINVAL;
+       struct fimc_is_group_framemgr *gframemgr;
+       struct fimc_is_group_frame *gframe, *temp;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+
+       gframemgr = &groupmgr->framemgr[group->instance];
+
+       spin_lock_irq(&gframemgr->frame_slock);
+
+       list_for_each_entry_safe(gframe, temp, &group->frame_group_head, list) {
+               if (gframe->fcount == target_fcount) {
+                       list_del(&gframe->list);
+                       group->frame_group_cnt--;
+                       mwarn("gframe%d is cancelled", group, target_fcount);
+                       fimc_is_gframe_s_free(gframemgr, gframe);
+                       ret = 0;
+                       break;
+               }
+       }
+
+       spin_unlock_irq(&gframemgr->frame_slock);
+
+       return ret;
+}
+
+void * fimc_is_gframe_rewind(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 target_fcount)
+{
+       struct fimc_is_group_framemgr *gframemgr;
+       struct fimc_is_group_frame *gframe, *temp;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+
+       gframemgr = &groupmgr->framemgr[group->instance];
+
+       list_for_each_entry_safe(gframe, temp, &group->frame_group_head, list) {
+               if (gframe->fcount == target_fcount)
+                       break;
+
+               if (gframe->fcount > target_fcount) {
+                       mwarn("target fcount is invalid(%d > %d)", group,
+                               gframe->fcount, target_fcount);
+                       gframe = NULL;
+                       break;
+               }
+
+               list_del(&gframe->list);
+               group->frame_group_cnt--;
+               mwarn("gframe%d is cancelled(count : %d)", group,
+                       gframe->fcount, group->frame_group_cnt);
+               fimc_is_gframe_s_free(gframemgr, gframe);
+       }
+
+       if (!group->frame_group_cnt) {
+               merr("gframe%d can't be found", group, target_fcount);
+               gframe = NULL;
+       }
+
+       return gframe;
+}
+
+int fimc_is_gframe_flush(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group)
+{
+       int ret = 0;
+       struct fimc_is_group_framemgr *gframemgr;
+       struct fimc_is_group_frame *gframe, *temp;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+
+       gframemgr = &groupmgr->framemgr[group->instance];
+
+       spin_lock_irq(&gframemgr->frame_slock);
+
+       list_for_each_entry_safe(gframe, temp, &group->frame_group_head, list) {
+               list_del(&gframe->list);
+               group->frame_group_cnt--;
+               mwarn("gframe%d is flushed(count : %d)", group,
+                       gframe->fcount, group->frame_group_cnt);
+               fimc_is_gframe_s_free(gframemgr, gframe);
+       }
+
+       spin_unlock_irq(&gframemgr->frame_slock);
+
+       return ret;
+}
+
+static void fimc_is_group_3a0_cancel(struct fimc_is_framemgr *framemgr,
+       struct fimc_is_frame *frame,
+       struct fimc_is_queue *queue,
+       struct fimc_is_video_ctx *vctx,
+       u32 instance)
+{
+       BUG_ON(!vctx);
+       BUG_ON(!framemgr);
+       BUG_ON(!frame);
+       BUG_ON(!queue);
+
+       pr_err("[3A0:D:%d:%d] GRP0 CANCEL(%d, %d)\n", instance,
+               V4L2_TYPE_IS_OUTPUT(queue->vbq->type),
+               frame->fcount, frame->index);
+
+       fimc_is_frame_trans_req_to_com(framemgr, frame);
+       queue_done(vctx, queue, frame->index, VB2_BUF_STATE_ERROR);
+}
+
+static void fimc_is_group_3a1_cancel(struct fimc_is_framemgr *framemgr,
+       struct fimc_is_frame *frame,
+       struct fimc_is_queue *queue,
+       struct fimc_is_video_ctx *vctx,
+       u32 instance)
+{
+       BUG_ON(!vctx);
+       BUG_ON(!framemgr);
+       BUG_ON(!frame);
+       BUG_ON(!queue);
+
+       pr_err("[3A1:D:%d:%d] GRP1 CANCEL(%d, %d)\n", instance,
+               V4L2_TYPE_IS_OUTPUT(queue->vbq->type),
+               frame->fcount, frame->index);
+
+       fimc_is_frame_trans_req_to_com(framemgr, frame);
+       queue_done(vctx, queue, frame->index, VB2_BUF_STATE_ERROR);
+}
+
+static void fimc_is_group_isp_cancel(struct fimc_is_framemgr *framemgr,
+       struct fimc_is_frame *frame,
+       struct fimc_is_video_ctx *vctx,
+       u32 instance)
+{
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!framemgr);
+       BUG_ON(!frame);
+
+       pr_err("[ISP:D:%d] GRP2 CANCEL(%d, %d)\n", instance,
+               frame->fcount, frame->index);
+
+       queue = GET_SRC_QUEUE(vctx);
+
+       fimc_is_frame_trans_req_to_com(framemgr, frame);
+       queue_done(vctx, queue, frame->index, VB2_BUF_STATE_ERROR);
+}
+
+static void fimc_is_group_dis_cancel(struct fimc_is_framemgr *framemgr,
+       struct fimc_is_frame *frame,
+       struct fimc_is_video_ctx *vctx,
+       u32 instance)
+{
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!framemgr);
+       BUG_ON(!frame);
+
+       pr_err("[DIS:D:%d] GRP3 CANCEL(%d, %d)\n", instance,
+               frame->fcount, frame->index);
+
+       queue = GET_SRC_QUEUE(vctx);
+
+       fimc_is_frame_trans_req_to_com(framemgr, frame);
+       queue_done(vctx, queue, frame->index, VB2_BUF_STATE_ERROR);
+}
+
+static void fimc_is_group_cancel(struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame)
+{
+       unsigned long flags;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_framemgr *ldr_framemgr;
+       /* for M2M device */
+       struct fimc_is_framemgr *sub_framemgr = NULL;
+       struct fimc_is_queue *ldr_queue, *sub_queue;
+       struct fimc_is_frame *sub_frame;
+
+       BUG_ON(!group);
+       BUG_ON(!ldr_frame);
+
+       vctx = group->leader.vctx;
+       if (!vctx) {
+               merr("vctx is NULL, critical error", group);
+               return;
+       }
+
+       ldr_framemgr = GET_SRC_FRAMEMGR(vctx);
+       if (!ldr_framemgr) {
+               merr("ldr_framemgr is NULL, critical error", group);
+               return;
+       }
+
+       framemgr_e_barrier_irqs(ldr_framemgr, 0, flags);
+
+       switch (group->id) {
+       case GROUP_ID_3A0:
+               ldr_queue = GET_SRC_QUEUE(vctx);
+               fimc_is_group_3a0_cancel(ldr_framemgr, ldr_frame,
+                       ldr_queue, vctx, group->instance);
+               /* for M2M device */
+               sub_framemgr = GET_DST_FRAMEMGR(vctx);
+               break;
+       case GROUP_ID_3A1:
+               ldr_queue = GET_SRC_QUEUE(vctx);
+               fimc_is_group_3a1_cancel(ldr_framemgr, ldr_frame,
+                       ldr_queue, vctx, group->instance);
+               /* for M2M device */
+               sub_framemgr = GET_DST_FRAMEMGR(vctx);
+               break;
+       case GROUP_ID_ISP:
+               fimc_is_group_isp_cancel(ldr_framemgr, ldr_frame,
+                       vctx, group->instance);
+               break;
+       case GROUP_ID_DIS:
+               fimc_is_group_dis_cancel(ldr_framemgr, ldr_frame,
+                       vctx, group->instance);
+               break;
+       default:
+               err("unresolved group id %d", group->id);
+               break;
+       }
+
+       framemgr_x_barrier_irqr(ldr_framemgr, 0, flags);
+
+       if (sub_framemgr) {
+               framemgr_e_barrier_irqs(sub_framemgr, 0, flags);
+
+               switch (group->id) {
+                       case GROUP_ID_3A0:
+                               sub_queue = GET_DST_QUEUE(vctx);
+                               fimc_is_frame_request_head(sub_framemgr, &sub_frame);
+                               if (sub_frame)
+                                       fimc_is_group_3a0_cancel(sub_framemgr, sub_frame,
+                                                       sub_queue, vctx, group->instance);
+                               break;
+                       case GROUP_ID_3A1:
+                               sub_queue = GET_DST_QUEUE(vctx);
+                               fimc_is_frame_request_head(sub_framemgr, &sub_frame);
+                               if (sub_frame)
+                                       fimc_is_group_3a1_cancel(sub_framemgr, sub_frame,
+                                                       sub_queue, vctx, group->instance);
+                               break;
+                       default:
+                               err("unresolved group id %d", group->id);
+                               break;
+               }
+
+               framemgr_x_barrier_irqr(sub_framemgr, 0, flags);
+       }
+}
+#ifdef CONFIG_USE_VENDER_FEATURE
+/* Flash Mode Control */
+#ifdef CONFIG_LEDS_LM3560
+extern int lm3560_reg_update_export(u8 reg, u8 mask, u8 data);
+#endif
+#ifdef CONFIG_LEDS_SKY81296
+extern int sky81296_torch_ctrl(int state);
+#endif
+
+static void fimc_is_group_set_torch(struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame)
+{
+       if (group->prev)
+               return;
+
+       if (group->aeflashMode != ldr_frame->shot->ctl.aa.aeflashMode) {
+               group->aeflashMode = ldr_frame->shot->ctl.aa.aeflashMode;
+               switch (group->aeflashMode) {
+               case AA_FLASHMODE_ON_ALWAYS: /*TORCH mode*/
+#ifdef CONFIG_LEDS_LM3560
+                       lm3560_reg_update_export(0xE0, 0xFF, 0xEF);
+#elif defined(CONFIG_LEDS_SKY81296)
+                       sky81296_torch_ctrl(1);
+#endif
+                       break;
+               case AA_FLASHMODE_START: /*Pre flash mode*/
+#ifdef CONFIG_LEDS_LM3560
+                       lm3560_reg_update_export(0xE0, 0xFF, 0xEF);
+#elif defined(CONFIG_LEDS_SKY81296)
+                       sky81296_torch_ctrl(1);
+#endif
+                       break;
+               case AA_FLASHMODE_CAPTURE: /*Main flash mode*/
+                       break;
+               case AA_FLASHMODE_OFF: /*OFF mode*/
+#ifdef CONFIG_LEDS_SKY81296
+                       sky81296_torch_ctrl(0);
+#endif
+                       break;
+               default:
+                       break;
+               }
+       }
+       return;
+}
+#endif
+
+#ifdef DEBUG_AA
+static void fimc_is_group_debug_aa_shot(struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame)
+{
+       if (group->prev)
+               return;
+
+#ifdef DEBUG_FLASH
+       if (ldr_frame->shot->ctl.aa.aeflashMode != group->flashmode) {
+               group->flashmode = ldr_frame->shot->ctl.aa.aeflashMode;
+               pr_info("flash ctl : %d(%d)\n", group->flashmode, ldr_frame->fcount);
+       }
+#endif
+}
+
+static void fimc_is_group_debug_aa_done(struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame)
+{
+       if (group->prev)
+               return;
+
+#ifdef DEBUG_FLASH
+       if (ldr_frame->shot->dm.flash.firingStable != group->flash.firingStable) {
+               group->flash.firingStable = ldr_frame->shot->dm.flash.firingStable;
+               pr_info("flash stable : %d(%d)\n", group->flash.firingStable, ldr_frame->fcount);
+       }
+
+       if (ldr_frame->shot->dm.flash.flashReady!= group->flash.flashReady) {
+               group->flash.flashReady = ldr_frame->shot->dm.flash.flashReady;
+               pr_info("flash ready : %d(%d)\n", group->flash.flashReady, ldr_frame->fcount);
+       }
+
+       if (ldr_frame->shot->dm.flash.flashOffReady!= group->flash.flashOffReady) {
+               group->flash.flashOffReady = ldr_frame->shot->dm.flash.flashOffReady;
+               pr_info("flash off : %d(%d)\n", group->flash.flashOffReady, ldr_frame->fcount);
+       }
+#endif
+}
+#endif
+
+static void fimc_is_group_start_trigger(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_frame *frame)
+{
+       BUG_ON(!group);
+       BUG_ON(!frame);
+
+       atomic_inc(&group->rcount);
+       queue_kthread_work(group->worker, &frame->work);
+}
+
+static void fimc_is_group_pump(struct kthread_work *work)
+{
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_frame *frame;
+
+       frame = container_of(work, struct fimc_is_frame, work);
+       groupmgr = frame->work_data1;
+       group = frame->work_data2;
+
+       fimc_is_group_start(groupmgr, group, frame);
+}
+
+int fimc_is_groupmgr_probe(struct fimc_is_groupmgr *groupmgr)
+{
+       int ret = 0;
+       u32 i, j;
+
+       for (i = 0; i < FIMC_IS_MAX_NODES; ++i) {
+               spin_lock_init(&groupmgr->framemgr[i].frame_slock);
+               INIT_LIST_HEAD(&groupmgr->framemgr[i].frame_free_head);
+               groupmgr->framemgr[i].frame_free_cnt = 0;
+
+               for (j = 0; j < FIMC_IS_MAX_GFRAME; ++j) {
+                       groupmgr->framemgr[i].frame[j].fcount = 0;
+                       fimc_is_gframe_s_free(&groupmgr->framemgr[i],
+                               &groupmgr->framemgr[i].frame[j]);
+               }
+
+               for (j = 0; j < GROUP_ID_MAX; ++j)
+                       groupmgr->group[i][j] = NULL;
+       }
+
+       for (i = 0; i < GROUP_ID_MAX; ++i) {
+               atomic_set(&groupmgr->group_refcount[i], 0);
+               clear_bit(FIMC_IS_GGROUP_START, &groupmgr->group_state[i]);
+               clear_bit(FIMC_IS_GGROUP_INIT, &groupmgr->group_state[i]);
+               clear_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[i]);
+       }
+
+       return ret;
+}
+
+int fimc_is_group_probe(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       u32 entry)
+{
+       int ret = 0;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+
+       group->id = GROUP_ID_INVALID;
+       group->leader.entry = entry;
+
+       clear_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
+       clear_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state);
+       clear_bit(FIMC_IS_GROUP_SHOT, &group->state);
+       clear_bit(FIMC_IS_GROUP_READY, &group->state);
+       clear_bit(FIMC_IS_GROUP_RUN, &group->state);
+       clear_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state);
+       clear_bit(FIMC_IS_GROUP_INIT, &group->state);
+
+       return ret;
+}
+
+int fimc_is_group_open(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 id, u32 instance,
+       struct fimc_is_video_ctx *vctx,
+       struct fimc_is_device_ischain *device,
+       fimc_is_start_callback start_callback)
+{
+       int ret = 0, i;
+       char name[30];
+       struct fimc_is_core *core;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_framemgr *framemgr;
+       struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!device);
+       BUG_ON(!vctx);
+       BUG_ON(instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(id >= GROUP_ID_MAX);
+
+       leader = &group->leader;
+       framemgr = GET_SRC_FRAMEMGR(vctx);
+       core = (struct fimc_is_core *)device->interface->core;
+
+       mdbgd_ischain("%s(id %d)\n", device, __func__, id);
+
+       if (test_bit(FIMC_IS_GROUP_OPEN, &group->state)) {
+               merr("group%d already open", device, id);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       /* 1. start kthread */
+       if (!test_bit(FIMC_IS_GGROUP_START, &groupmgr->group_state[id])) {
+               init_kthread_worker(&groupmgr->group_worker[id]);
+               snprintf(name, sizeof(name), "fimc_is_gworker%d", id);
+               groupmgr->group_task[id] = kthread_run(kthread_worker_fn,
+                       &groupmgr->group_worker[id], name);
+               if (IS_ERR(groupmgr->group_task[id])) {
+                       err("failed to create group_task%d\n", id);
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+
+               ret = sched_setscheduler_nocheck(groupmgr->group_task[id], SCHED_FIFO, &param);
+               if (ret) {
+                       merr("sched_setscheduler_nocheck is fail(%d)", group, ret);
+                       goto p_err;
+               }
+
+               set_bit(FIMC_IS_GGROUP_START, &groupmgr->group_state[id]);
+       }
+
+       group->worker = &groupmgr->group_worker[id];
+       for (i = 0; i < FRAMEMGR_MAX_REQUEST; ++i)
+               init_kthread_work(&framemgr->frame[i].work, fimc_is_group_pump);
+
+       /* 2. Init Group */
+       clear_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
+       clear_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state);
+       clear_bit(FIMC_IS_GROUP_SHOT, &group->state);
+       clear_bit(FIMC_IS_GROUP_READY, &group->state);
+       clear_bit(FIMC_IS_GROUP_RUN, &group->state);
+       clear_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state);
+       clear_bit(FIMC_IS_GROUP_INIT, &group->state);
+
+       group->start_callback = start_callback;
+       group->device = device;
+       group->id = id;
+       group->instance = instance;
+       group->source_vid = 0;
+       group->fcount = 0;
+       group->pcount = 0;
+       group->aeflashMode = 0; /* Flash Mode Control */
+       atomic_set(&group->scount, 0);
+       atomic_set(&group->rcount, 0);
+       atomic_set(&group->backup_fcount, 0);
+       atomic_set(&group->sensor_fcount, 1);
+       sema_init(&group->smp_trigger, 0);
+
+       INIT_LIST_HEAD(&group->frame_group_head);
+       group->frame_group_cnt = 0;
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+       measure_init(&group->time, group->instance, group->id, 66);
+#endif
+#endif
+
+       /* 3. Subdev Init */
+       mutex_init(&leader->mutex_state);
+       leader->vctx = vctx;
+       leader->group = group;
+       leader->leader = NULL;
+       leader->input.width = 0;
+       leader->input.height = 0;
+       leader->output.width = 0;
+       leader->output.height = 0;
+       clear_bit(FIMC_IS_SUBDEV_START, &leader->state);
+       set_bit(FIMC_IS_SUBDEV_OPEN, &leader->state);
+
+       /* 4. Configure Group & Subdev List */
+       switch (id) {
+       case GROUP_ID_3A0:
+       case GROUP_ID_3A1:
+               /* path configuration */
+               group->prev = NULL;
+               if (GET_FIMC_IS_NUM_OF_SUBIP(core, isp)) {
+                       group->next = &device->group_isp;
+                       /* HACK */
+                       group->next->prev = group;
+               } else {
+                       group->next = NULL;
+               }
+               group->subdev[ENTRY_SCALERC] = NULL;
+               group->subdev[ENTRY_DIS] = NULL;
+               group->subdev[ENTRY_TDNR] = NULL;
+               group->subdev[ENTRY_SCALERP] = NULL;
+               group->subdev[ENTRY_LHFD] = NULL;
+               group->subdev[ENTRY_3AAC] = &device->taac;
+               group->subdev[ENTRY_3AAP] = &device->taap;
+
+               device->taac.leader = leader;
+               device->taap.leader = leader;
+
+               device->taac.group = group;
+               device->taap.group = group;
+
+               set_bit(FIMC_IS_GROUP_ACTIVE, &group->state);
+               break;
+       case GROUP_ID_ISP:
+               /* path configuration */
+               group->prev = NULL;
+               group->next = NULL;
+               if (GET_FIMC_IS_NUM_OF_SUBIP(core, scc))
+                       group->subdev[ENTRY_SCALERC] = &device->scc;
+               else
+                       group->subdev[ENTRY_SCALERC] = NULL;
+               /* dis is not included to any group initially */
+               group->subdev[ENTRY_DIS] = NULL;
+               if (GET_FIMC_IS_NUM_OF_SUBIP(core, dnr))
+                       group->subdev[ENTRY_TDNR] = &device->dnr;
+               else
+                       group->subdev[ENTRY_TDNR] = NULL;
+
+               if (GET_FIMC_IS_NUM_OF_SUBIP(core, scp))
+                       group->subdev[ENTRY_SCALERP] = &device->scp;
+               else
+                       group->subdev[ENTRY_SCALERP] = NULL;
+
+               if (GET_FIMC_IS_NUM_OF_SUBIP(core, fd))
+                       group->subdev[ENTRY_LHFD] = &device->fd;
+               else
+                       group->subdev[ENTRY_LHFD] = NULL;
+               group->subdev[ENTRY_3AAC] = NULL;
+               group->subdev[ENTRY_3AAP] = NULL;
+
+               device->scc.leader = leader;
+               device->dis.leader = leader;
+               device->dnr.leader = leader;
+               device->scp.leader = leader;
+               device->fd.leader = leader;
+
+               device->scc.group = group;
+               device->dis.group = group;
+               device->dnr.group = group;
+               device->scp.group = group;
+               device->fd.group = group;
+
+               set_bit(FIMC_IS_GROUP_ACTIVE, &group->state);
+               break;
+       case GROUP_ID_DIS:
+               /* path configuration */
+               group->prev = NULL;
+               group->next = NULL;
+               group->subdev[ENTRY_SCALERC] = NULL;
+               group->subdev[ENTRY_DIS] = NULL;
+               group->subdev[ENTRY_TDNR] = NULL;
+               group->subdev[ENTRY_SCALERP] = NULL;
+               group->subdev[ENTRY_LHFD] = NULL;
+               group->subdev[ENTRY_3AAC] = NULL;
+               group->subdev[ENTRY_3AAP] = NULL;
+
+               clear_bit(FIMC_IS_GROUP_ACTIVE, &group->state);
+               break;
+       default:
+               merr("group id(%d) is invalid", vctx, id);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* 5. Update Group Manager */
+       groupmgr->group[instance][id] = group;
+       atomic_inc(&groupmgr->group_refcount[id]);
+       set_bit(FIMC_IS_GROUP_OPEN, &group->state);
+
+p_err:
+       mdbgd_group("%s(%d)\n", group, __func__, ret);
+       return ret;
+}
+
+int fimc_is_group_close(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group)
+{
+       int ret = 0;
+       u32 refcount, i;
+       struct fimc_is_group_framemgr *gframemgr;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+
+       refcount = atomic_read(&groupmgr->group_refcount[group->id]);
+
+       if (!test_bit(FIMC_IS_GROUP_OPEN, &group->state)) {
+               merr("group%d already close", group, group->id);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       /*
+        * Maybe there are some waiting smp_shot semaphores when finishing kthread
+        * in group close. This situation caused waiting kthread_stop to finish it
+        * We should check if there are smp_shot in waiting list.
+        */
+       if (test_bit(FIMC_IS_GROUP_INIT, &group->state)) {
+               while (!list_empty(&group->smp_shot.wait_list)) {
+                       warn("group%d frame reqs are waiting in semaphore[%d] when closing",
+                                       group->id, group->smp_shot.count);
+                       up(&group->smp_shot);
+               }
+       }
+
+       if ((refcount == 1) &&
+               test_bit(FIMC_IS_GGROUP_INIT, &groupmgr->group_state[group->id]) &&
+               groupmgr->group_task[group->id]) {
+
+               set_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[group->id]);
+
+               /* flush semaphore shot */
+               atomic_inc(&group->smp_shot_count);
+
+               /* flush semaphore trigger */
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state))
+                       up(&group->smp_trigger);
+
+               /*
+                * flush kthread wait until all work is complete
+                * it's dangerous if all is not finished
+                * so it's commented currently
+                * flush_kthread_worker(&groupmgr->group_worker[group->id]);
+                */
+               kthread_stop(groupmgr->group_task[group->id]);
+
+               clear_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[group->id]);
+               clear_bit(FIMC_IS_GGROUP_START, &groupmgr->group_state[group->id]);
+               clear_bit(FIMC_IS_GGROUP_INIT, &groupmgr->group_state[group->id]);
+       }
+
+       groupmgr->group[group->instance][group->id] = NULL;
+       atomic_dec(&groupmgr->group_refcount[group->id]);
+
+       /* all group is closed */
+       if (!groupmgr->group[group->instance][GROUP_ID_3A0] &&
+               !groupmgr->group[group->instance][GROUP_ID_3A1] &&
+               !groupmgr->group[group->instance][GROUP_ID_ISP] &&
+               !groupmgr->group[group->instance][GROUP_ID_DIS]) {
+               gframemgr = &groupmgr->framemgr[group->instance];
+               if (gframemgr->frame_free_cnt != FIMC_IS_MAX_GFRAME) {
+                       mwarn("gframemgr free count is invalid(%d)", group,
+                               gframemgr->frame_free_cnt);
+                       INIT_LIST_HEAD(&gframemgr->frame_free_head);
+                       gframemgr->frame_free_cnt = 0;
+                       for (i = 0; i < FIMC_IS_MAX_GFRAME; ++i) {
+                               gframemgr->frame[i].fcount = 0;
+                               fimc_is_gframe_s_free(gframemgr,
+                                       &gframemgr->frame[i]);
+                       }
+               }
+       }
+
+       group->id = GROUP_ID_INVALID;
+       clear_bit(FIMC_IS_GROUP_INIT, &group->state);
+       clear_bit(FIMC_IS_GROUP_OPEN, &group->state);
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &group->leader.state);
+
+p_err:
+       mdbgd_group("%s(ref %d, %d)", group, __func__, (refcount - 1), ret);
+       return ret;
+}
+
+int fimc_is_group_init(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       bool otf_input,
+       u32 video_id)
+{
+       int ret = 0;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+
+       if (test_bit(FIMC_IS_GROUP_INIT, &group->state)) {
+               merr("already initialized", group);
+               /* HACK */
+               /* ret = -EINVAL; */
+               goto p_err;
+       }
+
+       group->source_vid = video_id;
+
+       if (!test_bit(FIMC_IS_GGROUP_INIT, &groupmgr->group_state[group->id])) {
+               if (otf_input)
+                       sema_init(&groupmgr->group_smp_res[group->id], MIN_OF_SHOT_RSC);
+               else
+                       sema_init(&groupmgr->group_smp_res[group->id], 1);
+
+               set_bit(FIMC_IS_GGROUP_INIT, &groupmgr->group_state[group->id]);
+       }
+
+       if (otf_input) {
+               sema_init(&group->smp_shot, MIN_OF_SHOT_RSC);
+               atomic_set(&group->smp_shot_count, MIN_OF_SHOT_RSC);
+               set_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state);
+               group->async_shots = MIN_OF_ASYNC_SHOTS;
+               group->sync_shots = MIN_OF_SYNC_SHOTS;
+       } else {
+               sema_init(&group->smp_shot, 1);
+               atomic_set(&group->smp_shot_count, 1);
+               clear_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state);
+               group->async_shots = 0;
+               group->sync_shots = 1;
+       }
+
+       set_bit(FIMC_IS_GROUP_INIT, &group->state);
+
+p_err:
+       mdbgd_group("%s(otf : %d, %d)\n", group, __func__, otf_input, ret);
+       return ret;
+}
+
+int fimc_is_group_change(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group_isp,
+       struct fimc_is_frame *frame)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader_isp, *leader_dis;
+       struct fimc_is_group *group_dis;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group_isp);
+       BUG_ON(!group_isp->device);
+       BUG_ON(!frame);
+
+       device = group_isp->device;
+       group_dis = &device->group_dis;
+       leader_dis = &group_dis->leader;
+       leader_isp = &group_isp->leader;
+
+       if (frame->shot->ctl.aa.videoStabilizationMode) {
+               if (!test_bit(FIMC_IS_GROUP_READY, &group_dis->state)) {
+                       merr("DIS group is not ready", group_dis);
+                       frame->shot->dm.aa.videoStabilizationMode = 0;
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!test_bit(FIMC_IS_GROUP_ACTIVE, &group_dis->state)) {
+                       pr_info("[GRP%d] Change On\n", group_isp->id);
+
+                       /* HACK */
+                       sema_init(&group_dis->smp_trigger, 0);
+
+                       group_isp->prev = &device->group_3aa;
+                       group_isp->next = group_dis;
+                       group_isp->subdev[ENTRY_SCALERC] = &device->scc;
+                       group_isp->subdev[ENTRY_DIS] = &device->dis;
+                       group_isp->subdev[ENTRY_TDNR] = NULL;
+                       group_isp->subdev[ENTRY_SCALERP] = NULL;
+                       group_isp->subdev[ENTRY_LHFD] = NULL;
+
+                       group_dis->next = NULL;
+                       group_dis->prev = group_isp;
+                       group_dis->subdev[ENTRY_SCALERC] = NULL;
+                       group_dis->subdev[ENTRY_DIS] = NULL;
+                       group_dis->subdev[ENTRY_TDNR] = &device->dnr;
+                       group_dis->subdev[ENTRY_SCALERP] = &device->scp;
+                       group_dis->subdev[ENTRY_LHFD] = &device->fd;
+
+                       device->scc.leader = leader_isp;
+                       device->dis.leader = leader_isp;
+                       device->dnr.leader = leader_dis;
+                       device->scp.leader = leader_dis;
+                       device->fd.leader = leader_dis;
+
+                       device->scc.group = group_isp;
+                       device->dis.group = group_isp;
+                       device->dnr.group = group_dis;
+                       device->scp.group = group_dis;
+                       device->fd.group = group_dis;
+
+                       set_bit(FIMC_IS_GROUP_ACTIVE, &group_dis->state);
+               }
+
+               frame->shot->dm.aa.videoStabilizationMode = 1;
+       } else {
+               if (test_bit(FIMC_IS_GROUP_ACTIVE, &group_dis->state)) {
+                       pr_info("[GRP%d] Change Off\n", group_isp->id);
+                       group_isp->prev = &device->group_3aa;
+                       group_isp->next = NULL;
+                       group_isp->subdev[ENTRY_SCALERC] = &device->scc;
+                       group_isp->subdev[ENTRY_DIS] = &device->dis;
+                       group_isp->subdev[ENTRY_TDNR] = &device->dnr;
+                       group_isp->subdev[ENTRY_SCALERP] = &device->scp;
+                       group_isp->subdev[ENTRY_LHFD] = &device->fd;
+
+                       group_dis->next = NULL;
+                       group_dis->prev = NULL;
+                       group_dis->subdev[ENTRY_SCALERC] = NULL;
+                       group_dis->subdev[ENTRY_DIS] = NULL;
+                       group_dis->subdev[ENTRY_TDNR] = NULL;
+                       group_dis->subdev[ENTRY_SCALERP] = NULL;
+                       group_dis->subdev[ENTRY_LHFD] = NULL;
+
+                       device->scc.leader = leader_isp;
+                       device->dis.leader = leader_isp;
+                       device->dnr.leader = leader_isp;
+                       device->scp.leader = leader_isp;
+                       device->fd.leader = leader_isp;
+
+                       device->scc.group = group_isp;
+                       device->dis.group = group_isp;
+                       device->dnr.group = group_isp;
+                       device->scp.group = group_isp;
+                       device->fd.group = group_isp;
+
+                       clear_bit(FIMC_IS_GROUP_ACTIVE, &group_dis->state);
+               }
+
+               frame->shot->dm.aa.videoStabilizationMode = 0;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_group_process_start(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       struct fimc_is_device_sensor *sensor = NULL;
+       struct fimc_is_framemgr *framemgr = NULL;
+       u32 shot_resource = 1;
+       u32 sensor_fcount;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!group->device);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+       BUG_ON(!queue);
+       BUG_ON(!test_bit(FIMC_IS_GGROUP_INIT, &groupmgr->group_state[group->id]));
+       BUG_ON(!test_bit(FIMC_IS_GROUP_INIT, &group->state));
+
+       if (test_bit(FIMC_IS_GROUP_READY, &group->state)) {
+               warn("already group start");
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               framemgr = &queue->framemgr;
+               if (!framemgr) {
+                       err("framemgr is null\n");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               sensor = group->device->sensor;
+               if (!sensor) {
+                       err("sensor is null\n");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               /* async & sync shots */
+               if (fimc_is_sensor_g_framerate(sensor) > 30)
+                       group->async_shots = max_t(int, MIN_OF_ASYNC_SHOTS,
+                                       DIV_ROUND_UP(framemgr->frame_cnt, 3));
+               else
+                       group->async_shots = MIN_OF_ASYNC_SHOTS;
+               group->sync_shots = max_t(int, MIN_OF_SYNC_SHOTS,
+                               framemgr->frame_cnt - group->async_shots);
+
+               /* shot resource */
+               shot_resource = group->async_shots + MIN_OF_SYNC_SHOTS;
+               sema_init(&groupmgr->group_smp_res[group->id], shot_resource);
+
+               /* frame count */
+               sensor_fcount = fimc_is_sensor_g_fcount(sensor) + 1;
+               atomic_set(&group->sensor_fcount, sensor_fcount);
+               atomic_set(&group->backup_fcount, sensor_fcount - 1);
+               group->fcount = sensor_fcount - 1;
+
+               info("[OTF] framerate: %d, async shots: %d, shot resource: %d\n",
+                               fimc_is_sensor_g_framerate(sensor),
+                               group->async_shots,
+                               shot_resource);
+
+               memset(&group->intent_ctl, 0, sizeof(struct camera2_ctl));
+       }
+
+       sema_init(&group->smp_shot, shot_resource);
+       atomic_set(&group->smp_shot_count, shot_resource);
+
+       atomic_set(&group->scount, 0);
+       atomic_set(&group->rcount, 0);
+       sema_init(&group->smp_trigger, 0);
+
+       set_bit(FIMC_IS_GROUP_READY, &group->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_group_process_stop(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       int retry;
+       u32 rcount;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_device_sensor *sensor;
+       u32 group_id;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+       BUG_ON(!queue);
+
+       if (!test_bit(FIMC_IS_GROUP_READY, &group->state)) {
+               warn("already group stop");
+               goto p_err;
+       }
+
+       device = group->device;
+       if (!device) {
+               merr("device is NULL", group);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state)) {
+               warn("alredy close sensor was called");
+               goto p_err;
+       }
+
+       sensor = device->sensor;
+       framemgr = &queue->framemgr;
+
+       if (test_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state)) {
+               set_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state);
+               clear_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
+
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state) &&
+                       !list_empty(&group->smp_trigger.wait_list)) {
+                       if (!sensor) {
+                               warn("sensor is NULL, forcely trigger");
+                               up(&group->smp_trigger);
+                               goto check_completion;
+                       }
+
+                       if (!test_bit(FIMC_IS_SENSOR_OPEN, &sensor->state)) {
+                               warn("sensor is closed, forcely trigger");
+                               up(&group->smp_trigger);
+                               goto check_completion;
+                       }
+
+                       if (!test_bit(FIMC_IS_SENSOR_FRONT_START, &sensor->state)) {
+                               warn("front sensor is stopped, forcely trigger");
+                               up(&group->smp_trigger);
+                               goto check_completion;
+                       }
+
+                       if (!test_bit(FIMC_IS_SENSOR_BACK_START, &sensor->state)) {
+                               warn("back sensor is stopped, forcely trigger");
+                               up(&group->smp_trigger);
+                               goto check_completion;
+                       }
+               }
+       }
+
+check_completion:
+       retry = 150;
+       while (--retry && framemgr->frame_req_cnt) {
+               warn("%d frame reqs waiting...\n", framemgr->frame_req_cnt);
+               msleep(20);
+       }
+
+       if (!retry) {
+               merr("waiting(until request empty) is fail", group);
+               ret = -EINVAL;
+       }
+
+       if (!test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               retry = 10;
+               while (--retry && framemgr->frame_pro_cnt) {
+                       warn("%d frame pros waiting...\n", framemgr->frame_pro_cnt);
+                       msleep(20);
+               }
+
+               if (!retry) {
+                       merr("waiting(until process empty) is fail", group);
+                       ret = -EINVAL;
+               }
+       }
+
+       if (test_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state)) {
+               ret = fimc_is_itf_force_stop(device, GROUP_ID(group->id));
+               if (ret) {
+                       merr("fimc_is_itf_force_stop is fail", group);
+                       ret = -EINVAL;
+               }
+       } else {
+               /* if there's only one group of isp, send group id by 3a0 */
+               if ((group->id == GROUP_ID_ISP) &&
+                               GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0) == 0 &&
+                               GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1) == 0)
+                       group_id = GROUP_ID(GROUP_ID_3A0);
+               else
+                       group_id = GROUP_ID(group->id);
+
+               ret = fimc_is_itf_process_stop(device, group_id);
+               if (ret) {
+                       merr("fimc_is_itf_process_stop is fail", group);
+                       ret = -EINVAL;
+               }
+       }
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               retry = 10;
+               while (--retry && framemgr->frame_pro_cnt) {
+                       warn("%d frame pros waiting...\n", framemgr->frame_pro_cnt);
+                       msleep(20);
+               }
+
+               if (!retry) {
+                       merr("waiting(until process empty) is fail", group);
+                       ret = -EINVAL;
+               }
+       }
+
+       rcount = atomic_read(&group->rcount);
+       if (rcount) {
+               merr("rcount is not empty(%d)", group, rcount);
+               ret = -EINVAL;
+       }
+
+       retry = 100;
+       while (--retry && test_bit(FIMC_IS_GROUP_SHOT, &group->state)) {
+               mgwarn(" thread stop waiting...", device, group);
+               msleep(10);
+       }
+
+       if (!retry) {
+               mgerr(" waiting(until thread stop) is fail", device, group);
+               ret = -EINVAL;
+       }
+
+       fimc_is_gframe_flush(groupmgr, group);
+
+       clear_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state);
+       clear_bit(FIMC_IS_GROUP_READY, &group->state);
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state))
+               pr_info("[OTF] sensor fcount: %d, fcount: %d\n",
+                       atomic_read(&group->sensor_fcount), group->fcount);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_group_buffer_queue(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_queue *queue,
+       u32 index)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_device_sensor *sensor;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!group->device);
+       BUG_ON(!group->device->sensor);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+       BUG_ON(!queue);
+       BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
+
+       device = group->device;
+       sensor = device->sensor;
+       framemgr = &queue->framemgr;
+
+       /* 1. check frame validation */
+       frame = &framemgr->frame[index];
+       if (!frame) {
+               err("frame is null\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!test_bit(FRAME_INI_MEM, &frame->memory))) {
+               err("frame %d is NOT init", index);
+               ret = EINVAL;
+               goto p_err;
+       }
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+       do_gettimeofday(&frame->time_queued);
+#endif
+#endif
+
+       /* 2. update frame manager */
+       framemgr_e_barrier_irqs(framemgr, index, flags);
+
+       if (frame->state == FIMC_IS_FRAME_STATE_FREE) {
+               if (frame->req_flag) {
+                       merr("req_flag of buffer%d is not clear(%08X)",
+                               group, frame->index, (u32)frame->req_flag);
+                       frame->req_flag = 0;
+               }
+
+               if (test_bit(OUT_SCC_FRAME, &frame->out_flag)) {
+                       merr("scc output is not generated", group);
+                       clear_bit(OUT_SCC_FRAME, &frame->out_flag);
+               }
+
+               if (test_bit(OUT_DIS_FRAME, &frame->out_flag)) {
+                       merr("dis output is not generated", group);
+                       clear_bit(OUT_DIS_FRAME, &frame->out_flag);
+               }
+
+               if (test_bit(OUT_SCP_FRAME, &frame->out_flag)) {
+                       merr("scp output is not generated", group);
+                       clear_bit(OUT_SCP_FRAME, &frame->out_flag);
+               }
+
+               if (test_bit(OUT_3AAC_FRAME, &frame->out_flag)) {
+                       merr("3aac output is not generated", group);
+                       clear_bit(OUT_3AAC_FRAME, &frame->out_flag);
+               }
+
+               if (!test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state) &&
+                       (framemgr->frame_req_cnt >= 3))
+                       mwarn("GROUP%d is working lately(%d)",
+                               group, group->id, framemgr->frame_req_cnt);
+
+               frame->fcount = frame->shot->dm.request.frameCount;
+               frame->rcount = frame->shot->ctl.request.frameCount;
+               frame->work_data1 = groupmgr;
+               frame->work_data2 = group;
+
+#ifdef FIXED_FPS_DEBUG
+               frame->shot_ext->shot.ctl.aa.aeTargetFpsRange[0] = FIXED_FPS_VALUE;
+               frame->shot_ext->shot.ctl.aa.aeTargetFpsRange[1] = FIXED_FPS_VALUE;
+               frame->shot_ext->shot.ctl.sensor.frameDuration = 1000000000/FIXED_FPS_VALUE;
+#endif
+
+#ifdef ENABLE_FAST_SHOT
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+                       memcpy(&group->fast_ctl.aa, &frame->shot->ctl.aa,
+                               sizeof(struct camera2_aa_ctl));
+                       memcpy(&group->fast_ctl.scaler, &frame->shot->ctl.scaler,
+                               sizeof(struct camera2_scaler_ctl));
+               }
+#endif
+
+               fimc_is_frame_trans_fre_to_req(framemgr, frame);
+       } else {
+               err("frame(%d) is invalid state(%d)\n", index, frame->state);
+               fimc_is_frame_print_all(framemgr);
+               ret = -EINVAL;
+       }
+
+       framemgr_x_barrier_irqr(framemgr, index, flags);
+
+       if (unlikely(!test_bit(FRAME_MAP_MEM, &frame->memory) &&
+               !test_bit(FIMC_IS_SENSOR_FRONT_START, &sensor->state))) {
+               fimc_is_itf_map(device, GROUP_ID(group->id), frame->dvaddr_shot, frame->shot_size);
+               set_bit(FRAME_MAP_MEM, &frame->memory);
+       }
+
+       fimc_is_group_start_trigger(groupmgr, group, frame);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_group_buffer_finish(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 index)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!group->leader.vctx);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+       BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
+
+       framemgr = GET_GROUP_FRAMEMGR(group);
+
+       /* 2. update frame manager */
+       framemgr_e_barrier_irqs(framemgr, index, flags);
+
+       fimc_is_frame_complete_head(framemgr, &frame);
+       if (frame) {
+               if (frame->index == index) {
+                       fimc_is_frame_trans_com_to_fre(framemgr, frame);
+
+                       frame->shot_ext->free_cnt = framemgr->frame_fre_cnt;
+                       frame->shot_ext->request_cnt = framemgr->frame_req_cnt;
+                       frame->shot_ext->process_cnt = framemgr->frame_pro_cnt;
+                       frame->shot_ext->complete_cnt = framemgr->frame_com_cnt;
+               } else {
+                       merr("buffer index is NOT matched(G%d, %d != %d)",
+                               group, group->id, index, frame->index);
+                       fimc_is_frame_print_all(framemgr);
+                       ret = -EINVAL;
+               }
+       } else {
+               merr("frame is empty from complete", group);
+               fimc_is_frame_print_all(framemgr);
+               ret = -EINVAL;
+       }
+
+       framemgr_x_barrier_irqr(framemgr, index, flags);
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+       do_gettimeofday(&frame->time_dequeued);
+       measure_time(&group->time,
+               &frame->time_queued, &frame->time_shot,
+               &frame->time_shotdone, &frame->time_dequeued);
+#endif
+#endif
+
+       return ret;
+}
+
+int fimc_is_group_start(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame)
+{
+       int ret = 0;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_resourcemgr *resourcemgr;
+       struct fimc_is_group *group_next, *group_prev;
+       struct fimc_is_group_framemgr *gframemgr;
+       struct fimc_is_group_frame *gframe;
+       int async_step = 0;
+       bool try_sdown = false;
+       bool try_rdown = false;
+#ifdef ENABLE_DVFS
+       int scenario_id;
+#endif
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!group->leader.vctx);
+       BUG_ON(!group->start_callback);
+       BUG_ON(!group->device);
+       BUG_ON(!ldr_frame);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+
+       set_bit(FIMC_IS_GROUP_SHOT, &group->state);
+       atomic_dec(&group->rcount);
+
+       if (test_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state)) {
+               mwarn("g%dframe is cancelled(force stop)", group, group->id);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[group->id])) {
+               merr("cancel by group stop #1", group);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       PROGRAM_COUNT(1);
+       ret = down_interruptible(&group->smp_shot);
+       if (ret) {
+               err("down is fail1(%d)", ret);
+               goto p_err;
+       }
+       atomic_dec(&group->smp_shot_count);
+       try_sdown = true;
+
+       /* skip left operation, if group is closing */
+       if (!test_bit(FIMC_IS_GROUP_READY, &group->state)) {
+               mwarn("this group%d was already process stoped", group, group->id);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       PROGRAM_COUNT(2);
+       ret = down_interruptible(&groupmgr->group_smp_res[group->id]);
+       if (ret) {
+               err("down is fail2(%d)", ret);
+               goto p_err;
+       }
+       try_rdown = true;
+
+       if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+               if (atomic_read(&group->smp_shot_count) < MIN_OF_SYNC_SHOTS) {
+                       PROGRAM_COUNT(3);
+                       ret = down_interruptible(&group->smp_trigger);
+                       if (ret) {
+                               err("down is fail3(%d)", ret);
+                               goto p_err;
+                       }
+               } else {
+                       /*
+                        * backup fcount can not be bigger than sensor fcount
+                        * otherwise, duplicated shot can be generated.
+                        * this is problem can be caused by hal qbuf timing
+                        */
+                       if (atomic_read(&group->backup_fcount) >=
+                               atomic_read(&group->sensor_fcount)) {
+                               PROGRAM_COUNT(4);
+                               ret = down_interruptible(&group->smp_trigger);
+                               if (ret) {
+                                       err("down is fail4(%d)", ret);
+                                       goto p_err;
+                               }
+                       } else {
+                               /*
+                                * this statement is execued only at initial.
+                                * automatic increase the frame count of sensor
+                                * for next shot without real frame start
+                                */
+
+                               /* it's a async shot time */
+                               async_step = 1;
+                       }
+               }
+
+               if (test_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[group->id])) {
+                       err("cancel by group stop #2");
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               ldr_frame->fcount = atomic_read(&group->sensor_fcount);
+               atomic_set(&group->backup_fcount, ldr_frame->fcount);
+               ldr_frame->shot->dm.request.frameCount = ldr_frame->fcount;
+               ldr_frame->shot->dm.sensor.timeStamp = fimc_is_get_timestamp();
+
+               /* real automatic increase */
+               if (async_step && (atomic_read(&group->smp_shot_count) > MIN_OF_SYNC_SHOTS))
+                       atomic_inc(&group->sensor_fcount);
+       }
+
+       if (test_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[group->id])) {
+               err("cancel by group stop #3");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+#ifdef ENABLE_VDIS
+       if (group->id == GROUP_ID_ISP)
+               fimc_is_group_change(groupmgr, group, ldr_frame);
+
+       /* HACK */
+       if ((group->id == GROUP_ID_DIS) &&
+               test_bit(FIMC_IS_GROUP_ACTIVE, &group->state))
+               down(&group->smp_trigger);
+#endif
+
+       PROGRAM_COUNT(5);
+       device = group->device;
+       resourcemgr = device->resourcemgr;
+       group_next = group->next;
+       group_prev = group->prev;
+       gframemgr = &groupmgr->framemgr[group->instance];
+       if (!gframemgr) {
+               err("gframemgr is NULL(instance %d)", group->instance);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (group_prev && !group_next) {
+               /* tailer */
+               spin_lock_irq(&gframemgr->frame_slock);
+               fimc_is_gframe_group_head(group, &gframe);
+               if (!gframe) {
+                       merr("g%dframe is NULL1", group, group->id);
+                       warn("GRP%d(res %d, rcnt %d), GRP2(res %d, rcnt %d)",
+                               device->group_3aa.id,
+                               groupmgr->group_smp_res[device->group_3aa.id].count,
+                               atomic_read(&device->group_3aa.rcount),
+                               groupmgr->group_smp_res[device->group_isp.id].count,
+                               atomic_read(&device->group_isp.rcount));
+                       fimc_is_gframe_print_group(group_prev);
+                       fimc_is_gframe_print_free(gframemgr);
+                       spin_unlock_irq(&gframemgr->frame_slock);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (ldr_frame->fcount != gframe->fcount) {
+                       mwarn("grp%d shot mismatch(%d != %d)", group, group->id,
+                               ldr_frame->fcount, gframe->fcount);
+                       gframe = fimc_is_gframe_rewind(groupmgr, group,
+                               ldr_frame->fcount);
+                       if (!gframe) {
+                               spin_unlock_irq(&gframemgr->frame_slock);
+                               merr("rewinding is fail,can't recovery", group);
+                               goto p_err;
+                       }
+               }
+
+               fimc_is_gframe_s_info(gframe, group->id, ldr_frame);
+               fimc_is_gframe_trans_grp_to_fre(group, gframemgr, gframe);
+               spin_unlock_irq(&gframemgr->frame_slock);
+       } else if (!group_prev && group_next) {
+               /* leader */
+               group->fcount++;
+               spin_lock_irq(&gframemgr->frame_slock);
+               fimc_is_gframe_free_head(gframemgr, &gframe);
+               if (!gframe) {
+                       merr("g%dframe is NULL2", group, group->id);
+                       warn("GRP%d(res %d, rcnt %d), GRP2(res %d, rcnt %d)",
+                               device->group_3aa.id,
+                               groupmgr->group_smp_res[device->group_3aa.id].count,
+                               atomic_read(&device->group_3aa.rcount),
+                               groupmgr->group_smp_res[device->group_isp.id].count,
+                               atomic_read(&device->group_isp.rcount));
+                       fimc_is_gframe_print_free(gframemgr);
+                       fimc_is_gframe_print_group(group_next);
+                       spin_unlock_irq(&gframemgr->frame_slock);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state) &&
+                       (ldr_frame->fcount != group->fcount)) {
+                       if (ldr_frame->fcount > group->fcount) {
+                               warn("grp%d shot mismatch(%d != %d)", group->id,
+                                       ldr_frame->fcount, group->fcount);
+                               group->fcount = ldr_frame->fcount;
+                       } else {
+                               spin_unlock_irq(&gframemgr->frame_slock);
+                               err("grp%d shot mismatch(%d, %d)", group->id,
+                                       ldr_frame->fcount, group->fcount);
+                               group->fcount--;
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+               }
+
+               gframe->fcount = ldr_frame->fcount;
+               fimc_is_gframe_s_info(gframe, group->id, ldr_frame);
+               fimc_is_gframe_trans_fre_to_grp(gframemgr, group_next, gframe);
+               spin_unlock_irq(&gframemgr->frame_slock);
+       } else if (group_prev && group_next) {
+               spin_lock_irq(&gframemgr->frame_slock);
+               fimc_is_gframe_group_head(group, &gframe);
+               if (!gframe) {
+                       merr("g%dframe is NULL3", group, group->id);
+                       warn("GRP%d(res %d, rcnt %d), GRP2(res %d, rcnt %d)",
+                               device->group_3aa.id,
+                               groupmgr->group_smp_res[device->group_3aa.id].count,
+                               atomic_read(&device->group_3aa.rcount),
+                               groupmgr->group_smp_res[device->group_isp.id].count,
+                               atomic_read(&device->group_isp.rcount));
+                       fimc_is_gframe_print_group(group_prev);
+                       fimc_is_gframe_print_group(group_next);
+                       spin_unlock_irq(&gframemgr->frame_slock);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (ldr_frame->fcount != gframe->fcount) {
+                       mwarn("grp%d shot mismatch(%d != %d)", group, group->id,
+                               ldr_frame->fcount, gframe->fcount);
+                       gframe = fimc_is_gframe_rewind(groupmgr, group,
+                               ldr_frame->fcount);
+                       if (!gframe) {
+                               spin_unlock_irq(&gframemgr->frame_slock);
+                               merr("rewinding is fail,can't recovery", group);
+                               goto p_err;
+                       }
+               }
+
+               fimc_is_gframe_s_info(gframe, group->id, ldr_frame);
+               fimc_is_gframe_trans_grp_to_grp(group, group_next, gframe);
+               spin_unlock_irq(&gframemgr->frame_slock);
+       } else {
+               /* single */
+               group->fcount++;
+               spin_lock_irq(&gframemgr->frame_slock);
+               fimc_is_gframe_free_head(gframemgr, &gframe);
+               if (!gframe) {
+                       merr("g%dframe is NULL4", group, group->id);
+                       warn("GRP%d(res %d, rcnt %d), GRP2(res %d, rcnt %d)",
+                               device->group_3aa.id,
+                               groupmgr->group_smp_res[device->group_3aa.id].count,
+                               atomic_read(&device->group_3aa.rcount),
+                               groupmgr->group_smp_res[device->group_isp.id].count,
+                               atomic_read(&device->group_isp.rcount));
+                       fimc_is_gframe_print_free(gframemgr);
+                       spin_unlock_irq(&gframemgr->frame_slock);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state) &&
+                       (ldr_frame->fcount != group->fcount)) {
+                       if (ldr_frame->fcount > group->fcount) {
+                               warn("grp%d shot mismatch(%d != %d)", group->id,
+                                       ldr_frame->fcount, group->fcount);
+                               group->fcount = ldr_frame->fcount;
+                       } else {
+                               spin_unlock_irq(&gframemgr->frame_slock);
+                               err("grp%d shot mismatch(%d, %d)", group->id,
+                                       ldr_frame->fcount, group->fcount);
+                               group->fcount--;
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+               }
+
+               gframe->fcount = ldr_frame->fcount;
+               spin_unlock_irq(&gframemgr->frame_slock);
+       }
+
+#ifdef DEBUG_AA
+       fimc_is_group_debug_aa_shot(group, ldr_frame);
+#endif
+#ifdef CONFIG_USE_VENDER_FEATURE
+       /* Flash Mode Control */
+       fimc_is_group_set_torch(group, ldr_frame);
+#endif
+
+#ifdef ENABLE_DVFS
+       mutex_lock(&resourcemgr->dvfs_ctrl.lock);
+       if ((!pm_qos_request_active(&device->user_qos)) &&
+                       (sysfs_debug.en_dvfs)) {
+               /* try to find dynamic scenario to apply */
+               scenario_id = fimc_is_dvfs_sel_scenario(FIMC_IS_DYNAMIC_SN, device, ldr_frame);
+
+               if (scenario_id > 0) {
+                       struct fimc_is_dvfs_scenario_ctrl *dynamic_ctrl = resourcemgr->dvfs_ctrl.dynamic_ctrl;
+                       info("GRP:%d dynamic scenario(%d)-[%s]\n",
+                                       group->id, scenario_id,
+                                       dynamic_ctrl->scenarios[dynamic_ctrl->cur_scenario_idx].scenario_nm);
+                       fimc_is_set_dvfs(device, scenario_id);
+               }
+
+               if ((scenario_id < 0) && (resourcemgr->dvfs_ctrl.dynamic_ctrl->cur_frame_tick == 0)) {
+                       struct fimc_is_dvfs_scenario_ctrl *static_ctrl = resourcemgr->dvfs_ctrl.static_ctrl;
+                       info("GRP:%d restore scenario(%d)-[%s]\n",
+                                       group->id, static_ctrl->cur_scenario_id,
+                                       static_ctrl->scenarios[static_ctrl->cur_scenario_idx].scenario_nm);
+                       fimc_is_set_dvfs(device, static_ctrl->cur_scenario_id);
+               }
+       }
+       mutex_unlock(&resourcemgr->dvfs_ctrl.lock);
+#endif
+
+       PROGRAM_COUNT(6);
+       ret = group->start_callback(group->device, ldr_frame);
+       if (ret) {
+               merr("start_callback is fail", group);
+               fimc_is_group_cancel(group, ldr_frame);
+               fimc_is_group_done(groupmgr, group, ldr_frame, VB2_BUF_STATE_ERROR);
+       } else {
+               atomic_inc(&group->scount);
+       }
+
+       clear_bit(FIMC_IS_GROUP_SHOT, &group->state);
+       PROGRAM_COUNT(7);
+       return ret;
+
+p_err:
+       if (!test_bit(FIMC_IS_GGROUP_REQUEST_STOP, &groupmgr->group_state[group->id]))
+               fimc_is_group_cancel(group, ldr_frame);
+
+       if (try_sdown) {
+               atomic_inc(&group->smp_shot_count);
+               up(&group->smp_shot);
+       }
+
+       if (try_rdown)
+               up(&groupmgr->group_smp_res[group->id]);
+
+       clear_bit(FIMC_IS_GROUP_SHOT, &group->state);
+       PROGRAM_COUNT(8);
+
+       return ret;
+}
+
+int fimc_is_group_done(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame,
+       u32 done_state)
+{
+       int ret = 0;
+       u32 resources;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!ldr_frame);
+       BUG_ON(group->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(group->id >= GROUP_ID_MAX);
+       BUG_ON(!group->device);
+
+#ifdef ENABLE_VDIS
+       /* current group notify to next group that shot done is arrvied */
+       /* HACK */
+       if (group->next && (group->id == GROUP_ID_ISP) &&
+               test_bit(FIMC_IS_GROUP_ACTIVE, &group->next->state))
+               up(&group->next->smp_trigger);
+#endif
+
+       /* check shot & resource count validation */
+       resources = group->async_shots + group->sync_shots;
+
+       if (group->smp_shot.count >= resources) {
+               merr("G%d, shot count is invalid(%d >= %d+%d)", group,
+                       group->id, group->smp_shot.count, group->async_shots,
+                       group->sync_shots);
+               atomic_set(&group->smp_shot_count, resources - 1);
+               sema_init(&group->smp_shot, resources - 1);
+       }
+
+       if (groupmgr->group_smp_res[group->id].count >= resources) {
+               merr("G%d, resource count is invalid(%d >=  %d+%d)", group,
+                       group->id, groupmgr->group_smp_res[group->id].count,
+                       group->async_shots, group->sync_shots);
+               sema_init(&groupmgr->group_smp_res[group->id], resources - 1);
+       }
+
+       device = group->device;
+       if (test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state) &&
+               (done_state != VB2_BUF_STATE_DONE)) {
+               merr("GRP%d NOT DONE(reprocessing)\n", group, group->id);
+               fimc_is_hw_logdump(device->interface);
+       }
+
+#ifdef DEBUG_AA
+       fimc_is_group_debug_aa_done(group, ldr_frame);
+#endif
+
+       clear_bit(FIMC_IS_GROUP_RUN, &group->state);
+       atomic_inc(&group->smp_shot_count);
+       up(&group->smp_shot);
+       up(&groupmgr->group_smp_res[group->id]);
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-groupmgr.h b/drivers/media/platform/exynos/fimc-is/fimc-is-groupmgr.h
new file mode 100644 (file)
index 0000000..edf41d3
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_GROUP_MGR_H
+#define FIMC_IS_GROUP_MGR_H
+
+#include "fimc-is-config.h"
+#include "fimc-is-time.h"
+#include "fimc-is-subdev-ctrl.h"
+#include "fimc-is-video.h"
+
+/* #define DEBUG_AA */
+/* #define DEBUG_FLASH */
+
+#define TRACE_GROUP
+#define GROUP_ID_3A0           0 /* hardware : CH0 */
+#define GROUP_ID_3A1           1 /* hardware : 3AA */
+#define GROUP_ID_ISP           2 /* hardware : CH1 */
+#define GROUP_ID_DIS           3
+#define GROUP_ID_MAX           4
+#define GROUP_ID_INVALID       5
+#define GROUP_ID_PARM_MASK     (0xF)
+#define GROUP_ID_SHIFT         (16)
+#define GROUP_ID_MASK          (0xFFFF)
+#define GROUP_ID(id)           (1 << id)
+
+#define FIMC_IS_MAX_GFRAME     15 /* max shot buffer of F/W */
+#define MIN_OF_ASYNC_SHOTS     1
+#define MIN_OF_SYNC_SHOTS      2
+#define MIN_OF_SHOT_RSC                (MIN_OF_ASYNC_SHOTS + MIN_OF_SYNC_SHOTS)
+
+enum fimc_is_group_state {
+       FIMC_IS_GROUP_OPEN,
+       FIMC_IS_GROUP_INIT,
+       FIMC_IS_GROUP_READY,
+       FIMC_IS_GROUP_ACTIVE,
+       FIMC_IS_GROUP_RUN,
+       FIMC_IS_GROUP_SHOT,
+       FIMC_IS_GROUP_REQUEST_FSTOP,
+       FIMC_IS_GROUP_FORCE_STOP,
+       FIMC_IS_GROUP_OTF_INPUT
+};
+
+enum fimc_is_global_group_state {
+       FIMC_IS_GGROUP_INIT,
+       FIMC_IS_GGROUP_START,
+       FIMC_IS_GGROUP_REQUEST_STOP
+};
+
+struct fimc_is_frame;
+struct fimc_is_device_ischain;
+typedef int (*fimc_is_start_callback)(struct fimc_is_device_ischain *device,
+       struct fimc_is_frame *frame);
+
+struct fimc_is_group_frame {
+       struct list_head                list;
+       u32                             fcount;
+       struct camera2_node_group       group_cfg[GROUP_ID_MAX];
+};
+
+struct fimc_is_group_framemgr {
+       struct fimc_is_group_frame      frame[FIMC_IS_MAX_GFRAME];
+       spinlock_t                      frame_slock;
+       struct list_head                frame_free_head;
+       u32                             frame_free_cnt;
+};
+
+struct fimc_is_group {
+       struct fimc_is_group            *next;
+       struct fimc_is_group            *prev;
+
+       struct fimc_is_subdev           leader;
+       struct fimc_is_subdev           *subdev[ENTRY_END];
+       struct kthread_worker           *worker;
+
+       /* for otf interface */
+       atomic_t                        sensor_fcount;
+       atomic_t                        backup_fcount;
+       struct semaphore                smp_trigger;
+       struct semaphore                smp_shot;
+       atomic_t                        smp_shot_count;
+       u32                             async_shots;
+       u32                             sync_shots;
+       struct camera2_ctl              fast_ctl;
+       struct camera2_ctl              intent_ctl;
+
+       u32                             id; /* group id */
+       u32                             instance; /* device instance */
+       u32                             source_vid; /* source video id */
+       u32                             pcount; /* program count */
+       u32                             fcount; /* frame count */
+       atomic_t                        scount; /* shot count */
+       atomic_t                        rcount; /* request count */
+       unsigned long                   state;
+
+       struct list_head                frame_group_head;
+       u32                             frame_group_cnt;
+
+       fimc_is_start_callback          start_callback;
+       struct fimc_is_device_ischain   *device;
+
+#ifdef DEBUG_AA
+#ifdef DEBUG_FLASH
+       enum aa_ae_flashmode            flashmode;
+       struct camera2_flash_dm         flash;
+#endif
+#endif
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+       struct fimc_is_time             time;
+#endif
+#endif
+       u32                             aeflashMode; /* Flash Mode Control */
+};
+
+struct fimc_is_groupmgr {
+       struct fimc_is_group_framemgr   framemgr[FIMC_IS_MAX_NODES];
+       struct fimc_is_group            *group[FIMC_IS_MAX_NODES][GROUP_ID_MAX];
+       struct kthread_worker           group_worker[GROUP_ID_MAX];
+       struct task_struct              *group_task[GROUP_ID_MAX];
+       struct semaphore                group_smp_res[GROUP_ID_MAX];
+       unsigned long                   group_state[GROUP_ID_MAX];
+       atomic_t                        group_refcount[GROUP_ID_MAX];
+};
+
+int fimc_is_groupmgr_probe(struct fimc_is_groupmgr *groupmgr);
+int fimc_is_group_probe(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       u32 entry);
+int fimc_is_group_open(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 id, u32 instance,
+       struct fimc_is_video_ctx *vctx,
+       struct fimc_is_device_ischain *device,
+       fimc_is_start_callback start_callback);
+int fimc_is_group_close(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group);
+int fimc_is_group_init(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       bool otf_input,
+       u32 video_id);
+int fimc_is_group_process_start(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_queue *queue);
+int fimc_is_group_process_stop(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_queue *queue);
+int fimc_is_group_buffer_queue(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_queue *queue,
+       u32 index);
+int fimc_is_group_buffer_finish(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 index);
+int fimc_is_group_start(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_frame *frame);
+int fimc_is_group_done(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_frame *ldr_frame,
+       u32 done_state);
+
+int fimc_is_gframe_cancel(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group, u32 target_fcount);
+
+#define PROGRAM_COUNT(count) (group->pcount = count)
+
+#define GET_GROUP_FRAMEMGR(group) \
+       (((group) && (group)->leader.vctx) ? (&(group)->leader.vctx->q_src->framemgr) : NULL)
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-hw-csi.c b/drivers/media/platform/exynos/fimc-is/fimc-is-hw-csi.c
new file mode 100644 (file)
index 0000000..18e5ed8
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos5-mipiphy.h>
+
+#include "fimc-is-config.h"
+#include "fimc-is-type.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-hw.h"
+
+#if (FIMC_IS_CSI_VERSION == CSI_VERSION_0310_0100)
+#define CSI_REG_CTRL                                   (0x00)
+#define CSI_REG_DPHYCTRL                               (0x04)
+#define CSI_REG_INTMSK                                 (0x10)
+#define CSI_REG_INTSRC                                 (0x14)
+#define CSI_REG_CONFIG0                                        (0x08)
+#define CSI_REG_CONFIG1                                        (0x40)
+#define CSI_REG_CONFIG2                                        (0x50)
+#define CSI_REG_CONFIG3                                        (0x60)
+#define CSI_REG_RESOL0                                 (0x2c)
+#define CSI_REG_RESOL1                                 (0x44)
+#define CSI_REG_RESOL2                                 (0x54)
+#define CSI_REG_RESOL3                                 (0x64)
+#define CSI_REG_DPHYCTRL0                              (0x20)
+#define CSI_REG_DPHYCTRL1                              (0x24)
+#else
+/* CSIS global control */
+#define S5PCSIS_CTRL                                   (0x00)
+#define S5PCSIS_CTRL_DPDN_SWAP_CLOCK_DEFAULT           (0 << 31)
+#define S5PCSIS_CTRL_DPDN_SWAP_CLOCK                   (1 << 31)
+#define S5PCSIS_CTRL_DPDN_SWAP_DATA_DEFAULT            (0 << 30)
+#define S5PCSIS_CTRL_DPDN_SWAP_DATA                    (1 << 30)
+#define S5PCSIS_CTRL_INTERLEAVE_MODE(x)                        ((x & 0x3) << 22)
+#define S5PCSIS_CTRL_ALIGN_32BIT                       (1 << 20)
+#define S5PCSIS_CTRL_UPDATE_SHADOW(x)                  ((1 << (x)) << 16)
+#define S5PCSIS_CTRL_WCLK_EXTCLK                       (1 << 8)
+#define S5PCSIS_CTRL_RESET                             (1 << 4)
+#define S5PCSIS_CTRL_NUMOFDATALANE(x)                  ((x) << 2)
+#define S5PCSIS_CTRL_ENABLE                            (1 << 0)
+
+/* D-PHY control */
+#define S5PCSIS_DPHYCTRL                               (0x04)
+#define S5PCSIS_DPHYCTRL_DPHY_ON(lanes)                        ((~(0x1f << (lanes + 1))) & 0x1f)
+#if defined(CONFIG_SOC_EXYNOS5260)
+#define S5PCSIS_DPHYCTRL_HSS_MASK                      (0x1f << 27)
+#else
+#define S5PCSIS_DPHYCTRL_HSS_MASK                      (0xff << 24)
+#define S5PCSIS_DPHYCTRL_CLKSETTLEMASK                 (0x3 << 22)
+#endif
+
+/* Configuration */
+#define S5PCSIS_CONFIG                                 (0x08)
+#define S5PCSIS_CONFIG_CH1                             (0x40)
+#define S5PCSIS_CONFIG_CH2                             (0x50)
+#define S5PCSIS_CONFIG_CH3                             (0x60)
+#define S5PCSIS_CFG_LINE_INTERVAL(x)                   (x << 26)
+#define S5PCSIS_CFG_START_INTERVAL(x)                  (x << 20)
+#define S5PCSIS_CFG_END_INTERVAL(x)                    (x << 8)
+#define S5PCSIS_CFG_FMT_YCBCR422_8BIT                  (0x1e << 2)
+#define S5PCSIS_CFG_FMT_RAW8                           (0x2a << 2)
+#define S5PCSIS_CFG_FMT_RAW10                          (0x2b << 2)
+#define S5PCSIS_CFG_FMT_RAW12                          (0x2c << 2)
+/* User defined formats, x = 1...4 */
+#define S5PCSIS_CFG_FMT_USER(x)                                ((0x30 + x - 1) << 2)
+#define S5PCSIS_CFG_FMT_MASK                           (0x3f << 2)
+#define S5PCSIS_CFG_VIRTUAL_CH(x)                      (x << 0)
+#define S5PCSIS_CFG_NR_LANE_MASK                       (3)
+
+/* Interrupt mask. */
+#define S5PCSIS_INTMSK                                 (0x10)
+#if defined(CONFIG_SOC_EXYNOS5260)
+#define S5PCSIS_INTMSK_EN_ALL                          (0xfc00103f)
+#else
+#define S5PCSIS_INTMSK_EN_ALL                          (0xf1101117)
+#endif
+#define S5PCSIS_INTMSK_EVEN_BEFORE                     (1 << 31)
+#define S5PCSIS_INTMSK_EVEN_AFTER                      (1 << 30)
+#define S5PCSIS_INTMSK_ODD_BEFORE                      (1 << 29)
+#define S5PCSIS_INTMSK_ODD_AFTER                       (1 << 28)
+#define S5PCSIS_INTMSK_FRAME_START_CH3                 (1 << 27)
+#define S5PCSIS_INTMSK_FRAME_START_CH2                 (1 << 26)
+#define S5PCSIS_INTMSK_FRAME_START_CH1                 (1 << 25)
+#define S5PCSIS_INTMSK_FRAME_START_CH0                 (1 << 24)
+#define S5PCSIS_INTMSK_FRAME_END_CH3                   (1 << 23)
+#define S5PCSIS_INTMSK_FRAME_END_CH2                   (1 << 22)
+#define S5PCSIS_INTMSK_FRAME_END_CH1                   (1 << 21)
+#define S5PCSIS_INTMSK_FRAME_END_CH0                   (1 << 20)
+#define S5PCSIS_INTMSK_ERR_SOT_HS                      (1 << 16)
+#define S5PCSIS_INTMSK_ERR_LOST_FS_CH3                 (1 << 15)
+#define S5PCSIS_INTMSK_ERR_LOST_FS_CH2                 (1 << 14)
+#define S5PCSIS_INTMSK_ERR_LOST_FS_CH1                 (1 << 13)
+#define S5PCSIS_INTMSK_ERR_LOST_FS_CH0                 (1 << 12)
+#define S5PCSIS_INTMSK_ERR_LOST_FE_CH3                 (1 << 11)
+#define S5PCSIS_INTMSK_ERR_LOST_FE_CH2                 (1 << 10)
+#define S5PCSIS_INTMSK_ERR_LOST_FE_CH1                 (1 << 9)
+#define S5PCSIS_INTMSK_ERR_LOST_FE_CH0                 (1 << 8)
+#define S5PCSIS_INTMSK_ERR_OVER_CH3                    (1 << 7)
+#define S5PCSIS_INTMSK_ERR_OVER_CH2                    (1 << 6)
+#define S5PCSIS_INTMSK_ERR_OVER_CH1                    (1 << 5)
+#define S5PCSIS_INTMSK_ERR_OVER_CH0                    (1 << 4)
+#define S5PCSIS_INTMSK_ERR_ECC                         (1 << 2)
+#define S5PCSIS_INTMSK_ERR_CRC                         (1 << 1)
+#define S5PCSIS_INTMSK_ERR_ID                          (1 << 0)
+
+/* Interrupt source */
+#define S5PCSIS_INTSRC                                 (0x14)
+#define S5PCSIS_INTSRC_EVEN_BEFORE                     (1 << 31)
+#define S5PCSIS_INTSRC_EVEN_AFTER                      (1 << 30)
+#define S5PCSIS_INTSRC_EVEN                            (0x3 << 30)
+#define S5PCSIS_INTSRC_ODD_BEFORE                      (1 << 29)
+#define S5PCSIS_INTSRC_ODD_AFTER                       (1 << 28)
+#define S5PCSIS_INTSRC_ODD                             (0x3 << 28)
+#define S5PCSIS_INTSRC_FRAME_START                     (0xf << 24)
+#define S5PCSIS_INTSRC_FRAME_END                       (0xf << 20)
+#define S5PCSIS_INTSRC_ERR_SOT_HS                      (0xf << 16)
+#define S5PCSIS_INTSRC_ERR_LOST_FS                     (0xf << 12)
+#define S5PCSIS_INTSRC_ERR_LOST_FE                     (0xf << 8)
+#define S5PCSIS_INTSRC_ERR_OVER                                (0xf << 4)
+#define S5PCSIS_INTSRC_ERR_ECC                         (1 << 2)
+#define S5PCSIS_INTSRC_ERR_CRC                         (1 << 1)
+#define S5PCSIS_INTSRC_ERR_ID                          (1 << 0)
+#define S5PCSIS_INTSRC_ERRORS                          (0xf1111117)
+
+/* Pixel resolution */
+#define S5PCSIS_RESOL                                  (0x2c)
+#define CSIS_MAX_PIX_WIDTH                             (0xffff)
+#define CSIS_MAX_PIX_HEIGHT                            (0xffff)
+#endif
+
+#if (FIMC_IS_CSI_VERSION == CSI_VERSION_0310_0100)
+
+int csi_hw_reset(unsigned long __iomem *base_reg)
+{
+       int ret = 0;
+       u32 retry = 10;
+       u32 val;
+
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+       writel(val | (1 << 4), base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+
+       while (--retry) {
+               udelay(10);
+               val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+               if (!(val & (1 << 4)))
+                       break;
+       }
+
+       if (!retry) {
+               err("reset is fail(%d)", retry);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int csi_hw_s_settle(unsigned long __iomem *base_reg,
+       u32 settle)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL));
+       val = (val & ~(0xFF << 24)) | (settle << 24);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL));
+
+       return 0;
+}
+
+int csi_hw_s_dphyctrl0(unsigned long __iomem *base_reg,
+       u32 ctrl)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL0));
+       val = (val & ~(0xFFFFFFFF << 0)) | (ctrl << 0);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL0));
+
+       return 0;
+}
+
+int csi_hw_s_dphyctrl1(unsigned long __iomem *base_reg,
+       u32 ctrl)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL1));
+       val = (val & ~(0xFFFFFFFF << 0)) | (ctrl << 0);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL1));
+
+       return 0;
+}
+
+int csi_hw_s_control(unsigned long __iomem *base_reg,
+       u32 pixelformat, u32 mode, u32 lanes)
+{
+       int ret = 0;
+       u32 val;
+
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+       val = (val & ~(0x3 << 2)) | (lanes << 2);
+       val = (val & ~(0x3 << 22)) | (mode << 22);
+
+       /* all channel use extclk for wrapper clock source */
+       val |= (0xF << 8);
+
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+       case V4L2_PIX_FMT_SBGGR16:
+       case V4L2_PIX_FMT_JPEG:
+               /* output width of CH0 is not 32 bits(normal output) */
+               val &= ~(1 << 20);
+               break;
+       case V4L2_PIX_FMT_YVU420:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_YUYV:
+               /* output width of CH0 is 32 bits(32bit align) */
+               val |= (1 << 20);
+               break;
+       default:
+               err("unsupported format(%X)", pixelformat);
+               ret = -EINVAL;
+               goto p_err;
+               break;
+       }
+
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+
+p_err:
+       return ret;
+}
+
+int csi_hw_s_config(unsigned long __iomem *base_reg,
+       u32 vc_src, u32 vc_dst, u32 pixelformat, u32 width, u32 height)
+{
+       int ret = 0;
+       u32 val, format;
+
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               format = HW_FORMAT_RAW8;
+               break;
+       case V4L2_PIX_FMT_SBGGR10:
+       case V4L2_PIX_FMT_SGBRG10:
+       case V4L2_PIX_FMT_SGRBG10:
+       case V4L2_PIX_FMT_SRGGB10:
+               format = HW_FORMAT_RAW10;
+               break;
+       case V4L2_PIX_FMT_SBGGR12:
+       case V4L2_PIX_FMT_SGBRG12:
+       case V4L2_PIX_FMT_SGRBG12:
+       case V4L2_PIX_FMT_SRGGB12:
+               format = HW_FORMAT_RAW10;
+               /* HACK : format = HW_FORMAT_RAW12; */
+               break;
+       case V4L2_PIX_FMT_SBGGR16:
+               format = HW_FORMAT_RAW10;
+               /* HACK : format = HW_FORMAT_RAW12; */
+               break;
+       case V4L2_PIX_FMT_YVU420:
+       case V4L2_PIX_FMT_NV21:
+               format = HW_FORMAT_YUV420_8BIT;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               format = HW_FORMAT_YUV422_8BIT;
+               break;
+       case V4L2_PIX_FMT_JPEG:
+               format = HW_FORMAT_USER;
+               break;
+       default:
+               err("unsupported format(%X)", pixelformat);
+               ret = -EINVAL;
+               goto p_err;
+               break;
+       }
+
+       switch (vc_src) {
+       case CSI_VIRTUAL_CH_0:
+               val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG0));
+               val = (val & ~(0x3 << 0)) | (vc_dst << 0);
+               val = (val & ~(0x3f << 2)) | (format << 2);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG0));
+
+               val = (width << 16) | (height << 0);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_RESOL0));
+               break;
+       case CSI_VIRTUAL_CH_1:
+               val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG1));
+               val = (val & ~(0x3 << 0)) | (vc_dst << 0);
+               val = (val & ~(0x3f << 2)) | (format << 2);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG1));
+
+               val = (width << 16) | (height << 0);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_RESOL1));
+               break;
+       case CSI_VIRTUAL_CH_2:
+               val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG2));
+               val = (val & ~(0x3 << 0)) | (vc_dst << 0);
+               val = (val & ~(0x3f << 2)) | (format << 2);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG2));
+
+               val = (width << 16) | (height << 0);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_RESOL2));
+               break;
+       case CSI_VIRTUAL_CH_3:
+               val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG3));
+               val = (val & ~(0x3 << 0)) | (vc_dst << 0);
+               val = (val & ~(0x3f << 2)) | (format << 2);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CONFIG3));
+
+               val = (width << 16) | (height << 0);
+               writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_RESOL3));
+               break;
+       default:
+               err("invalid channel(%d)", vc_src);
+               ret = -EINVAL;
+               goto p_err;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+int csi_hw_s_interrupt(unsigned long __iomem *base_reg, bool on)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_INTMSK));
+       val = on ? (val | 0xFFF1FFF7) : (val & ~0xFFF1FFF7);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_INTMSK));
+
+       return 0;
+}
+
+int csi_hw_g_interrupt(unsigned long __iomem *base_reg)
+{
+       u32 val;
+
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_INTSRC));
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_INTSRC));
+
+       return val;
+}
+
+int csi_hw_enable(unsigned long __iomem *base_reg)
+{
+       u32 val;
+
+       /* update shadow */
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+       val |= (0xF << 16);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+
+       /* DPHY on */
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL));
+       val |= (0x1f << 0);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL));
+
+       /* csi enable */
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+       val |= (0x1 << 0);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+
+       return 0;
+}
+
+int csi_hw_disable(unsigned long __iomem *base_reg)
+{
+       u32 val;
+
+       /* DPHY on */
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL));
+       val &= ~(0x1f << 0);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_DPHYCTRL));
+
+       /* csi enable */
+       val = readl(base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+       val &= ~(0x1 << 0);
+       writel(val, base_reg + TO_WORD_OFFSET(CSI_REG_CTRL));
+
+       return 0;
+}
+
+#else
+
+void s5pcsis_enable_interrupts(unsigned long __iomem *base_reg,
+       struct fimc_is_image *image, bool on)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_INTMSK));
+
+       val = on ? val | S5PCSIS_INTMSK_EN_ALL :
+                  val & ~S5PCSIS_INTMSK_EN_ALL;
+
+       if (image->format.field == V4L2_FIELD_INTERLACED) {
+               if (on) {
+                       val |= S5PCSIS_INTMSK_FRAME_START_CH2;
+                       val |= S5PCSIS_INTMSK_FRAME_END_CH2;
+               } else {
+                       val &= ~S5PCSIS_INTMSK_FRAME_START_CH2;
+                       val &= ~S5PCSIS_INTMSK_FRAME_END_CH2;
+               }
+       }
+
+#if defined(CONFIG_SOC_EXYNOS5260)
+       /* FIXME: hard coded, only for rhea */
+       writel(0xFFF01037, base_reg + TO_WORD_OFFSET(S5PCSIS_INTMSK));
+#else
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_INTMSK));
+#endif
+}
+
+void s5pcsis_reset(unsigned long __iomem *base_reg)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+
+       writel(val | S5PCSIS_CTRL_RESET, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+       udelay(10);
+}
+
+void s5pcsis_system_enable(unsigned long __iomem *base_reg, int on, u32 lanes)
+{
+       u32 val;
+
+       val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433) || defined(CONFIG_SOC_EXYNOS5422)
+       val |= S5PCSIS_CTRL_WCLK_EXTCLK;
+#endif
+
+       if (on) {
+               val |= S5PCSIS_CTRL_ENABLE;
+               val |= S5PCSIS_CTRL_WCLK_EXTCLK;
+       } else
+               val &= ~S5PCSIS_CTRL_ENABLE;
+#if defined(CONFIG_SOC_EXYNOS5260)
+       /* FIXME: hard coded, only for rhea */
+       writel(0x0000010D, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+#else
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+#endif
+
+       val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
+       if (on)
+               val |= S5PCSIS_DPHYCTRL_DPHY_ON(lanes);
+       else
+               val &= ~S5PCSIS_DPHYCTRL_DPHY_ON(lanes);
+#if defined(CONFIG_SOC_EXYNOS5260)
+       /* FIXME: hard coded, only for rhea */
+       writel(0x0E00001F, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
+#else
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
+#endif
+}
+
+/* Called with the state.lock mutex held */
+static void __s5pcsis_set_format(unsigned long __iomem *base_reg,
+       struct fimc_is_image *image)
+{
+       u32 val;
+
+       BUG_ON(!image);
+
+       /* Color format */
+       val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG));
+
+       if (image->format.pixelformat == V4L2_PIX_FMT_SGRBG8)
+               val = (val & ~S5PCSIS_CFG_FMT_MASK) | S5PCSIS_CFG_FMT_RAW8;
+       else
+               val = (val & ~S5PCSIS_CFG_FMT_MASK) | S5PCSIS_CFG_FMT_RAW10;
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433) || defined(CONFIG_SOC_EXYNOS5422)
+       val |= S5PCSIS_CFG_END_INTERVAL(1);
+#endif
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG));
+
+       /* Pixel resolution */
+       val = (image->window.o_width << 16) | image->window.o_height;
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_RESOL));
+
+       /* Output channel2 for DT */
+       if (image->format.field == V4L2_FIELD_INTERLACED) {
+               val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG_CH2));
+               val |= S5PCSIS_CFG_VIRTUAL_CH(2);
+               val |= S5PCSIS_CFG_END_INTERVAL(1);
+               val = (val & ~S5PCSIS_CFG_FMT_MASK) | S5PCSIS_CFG_FMT_USER(1);
+               writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG_CH2));
+       }
+}
+
+void s5pcsis_set_hsync_settle(unsigned long __iomem *base_reg, u32 settle)
+{
+       u32 val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
+
+       val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 24);
+
+#if defined(CONFIG_SOC_EXYNOS5260)
+       /* FIXME: hard coded, only for rhea */
+       writel(0x0E00001F, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
+#else
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
+#endif
+}
+
+void s5pcsis_set_params(unsigned long __iomem *base_reg,
+       struct fimc_is_image *image, u32 lanes)
+{
+       u32 val;
+
+#if defined(CONFIG_SOC_EXYNOS3470)
+       writel(0x000000AC, base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG)); /* only for carmen */
+#endif
+       __s5pcsis_set_format(base_reg, image);
+
+       val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+       val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
+
+       val |= S5PCSIS_CTRL_NUMOFDATALANE(lanes);
+
+       /* Interleaved data */
+       if (image->format.field == V4L2_FIELD_INTERLACED) {
+               pr_info("set DT only\n");
+               val |= S5PCSIS_CTRL_INTERLEAVE_MODE(1); /* DT only */
+               val |= S5PCSIS_CTRL_UPDATE_SHADOW(2); /* ch2 shadow reg */
+       }
+
+       /* Not using external clock. */
+       val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
+
+       writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+
+       /* Update the shadow register. */
+       val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+       writel(val | S5PCSIS_CTRL_UPDATE_SHADOW(0), base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
+}
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-hw-ischain.c b/drivers/media/platform/exynos/fimc-is/fimc-is-hw-ischain.c
new file mode 100644 (file)
index 0000000..b438537
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/devfreq.h>
+#include <mach/bts.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/exynos5-mipiphy.h>
+
+#include "fimc-is-config.h"
+#include "fimc-is-type.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-core.h"
+#include "fimc-is-dvfs.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#define PM_QOS_CAM_THROUGHPUT  PM_QOS_RESERVED
+#endif
+extern struct pm_qos_request exynos_isp_qos_cpu_min;
+extern struct pm_qos_request exynos_isp_qos_cpu_max;
+extern struct pm_qos_request exynos_isp_qos_int;
+extern struct pm_qos_request exynos_isp_qos_mem;
+extern struct pm_qos_request exynos_isp_qos_cam;
+extern struct pm_qos_request exynos_isp_qos_disp;
+#if defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+extern struct pm_qos_request max_cpu_qos;
+#endif
+
+#if defined(CONFIG_ARGOS)
+extern void argos_block_enable(char *req_name, bool set);
+#endif
+
+#if defined(CONFIG_PM_DEVFREQ)
+inline static void fimc_is_set_qos_init(struct fimc_is_core *core, bool on)
+{
+       int cpu_min_qos, cpu_max_qos, int_qos, mif_qos, cam_qos, disp_qos;
+
+       cpu_min_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CPU_MIN, START_DVFS_LEVEL);
+       cpu_max_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CPU_MAX, START_DVFS_LEVEL);
+       int_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_INT, START_DVFS_LEVEL);
+       mif_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_MIF, START_DVFS_LEVEL);
+       cam_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_CAM, START_DVFS_LEVEL);
+       disp_qos = fimc_is_get_qos(core, FIMC_IS_DVFS_DISP, START_DVFS_LEVEL);
+
+       core->resourcemgr.dvfs_ctrl.cur_cpu_min_qos = cpu_min_qos;
+       core->resourcemgr.dvfs_ctrl.cur_cpu_max_qos = cpu_max_qos;
+       core->resourcemgr.dvfs_ctrl.cur_int_qos = int_qos;
+       core->resourcemgr.dvfs_ctrl.cur_mif_qos = mif_qos;
+       core->resourcemgr.dvfs_ctrl.cur_cam_qos = cam_qos;
+       core->resourcemgr.dvfs_ctrl.cur_disp_qos = disp_qos;
+
+       if (on) {
+               /* DEVFREQ lock */
+               if (cpu_min_qos > 0)
+                       pm_qos_add_request(&exynos_isp_qos_cpu_min, PM_QOS_CPU_FREQ_MIN, cpu_min_qos);
+               if (cpu_max_qos > 0)
+                       pm_qos_add_request(&exynos_isp_qos_cpu_max, PM_QOS_CPU_FREQ_MAX, cpu_max_qos);
+               if (int_qos > 0)
+                       pm_qos_add_request(&exynos_isp_qos_int, PM_QOS_DEVICE_THROUGHPUT, int_qos);
+               if (mif_qos > 0)
+                       pm_qos_add_request(&exynos_isp_qos_mem, PM_QOS_BUS_THROUGHPUT, mif_qos);
+               if (cam_qos > 0)
+                       pm_qos_add_request(&exynos_isp_qos_cam, PM_QOS_CAM_THROUGHPUT, cam_qos);
+               if (disp_qos > 0)
+                       pm_qos_add_request(&exynos_isp_qos_disp, PM_QOS_DISPLAY_THROUGHPUT, disp_qos);
+
+               pr_info("[RSC] %s: QoS LOCK [INT(%d), MIF(%d), CAM(%d), DISP(%d) CPU(%d/%d)]\n",
+                               __func__, int_qos, mif_qos, cam_qos, disp_qos, cpu_min_qos, cpu_max_qos);
+       } else {
+               /* DEVFREQ unlock */
+               if (cpu_min_qos > 0)
+                       pm_qos_remove_request(&exynos_isp_qos_cpu_min);
+               if (cpu_max_qos > 0)
+                       pm_qos_remove_request(&exynos_isp_qos_cpu_max);
+               if (int_qos > 0)
+                       pm_qos_remove_request(&exynos_isp_qos_int);
+               if (mif_qos > 0)
+                       pm_qos_remove_request(&exynos_isp_qos_mem);
+               if (cam_qos > 0)
+                       pm_qos_remove_request(&exynos_isp_qos_cam);
+               if (disp_qos > 0)
+                       pm_qos_remove_request(&exynos_isp_qos_disp);
+
+               pr_info("[RSC] %s: QoS UNLOCK\n", __func__);
+       }
+}
+#endif
+
+
+#if (FIMC_IS_VERSION == FIMC_IS_VERSION_250)
+int fimc_is_runtime_suspend_post(struct device *dev)
+{
+       int ret = 0;
+       u32 timeout;
+
+       timeout = 1000;
+       while ((readl(PMUREG_ISP0_STATUS) & 0x1) && timeout) {
+               timeout--;
+               usleep_range(1000, 1000);
+       }
+       if (timeout == 0)
+               err("ISP0 power down failed(0x%08x)\n", readl(PMUREG_ISP0_STATUS));
+
+       timeout = 1000;
+       while ((readl(PMUREG_ISP1_STATUS) & 0x1) && timeout) {
+               timeout--;
+               usleep_range(1000, 1000);
+       }
+       if (timeout == 0)
+               err("ISP0 power down failed(0x%08x)\n", readl(PMUREG_ISP1_STATUS));
+
+       return ret;
+}
+
+int fimc_is_runtime_suspend(struct device *dev)
+{
+#ifndef CONFIG_PM_RUNTIME
+       int ret = 0;
+       u32 val;
+#endif
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(pdev);
+
+       BUG_ON(!core);
+       BUG_ON(!core->pdata);
+       BUG_ON(!core->pdata->clk_off);
+
+       info("FIMC_IS runtime suspend in\n");
+
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (core->mem.alloc_ctx)
+               vb2_ion_detach_iommu(core->mem.alloc_ctx);
+#endif
+
+#if defined(CONFIG_FIMC_IS_BUS_DEVFREQ)
+       exynos5_update_media_layers(TYPE_FIMC_LITE, false);
+#endif
+
+#ifndef CONFIG_PM_RUNTIME
+       /* ISP1 */
+       /* 1. set internal clock reset */
+       val = __raw_readl(PMUREG_CMU_RESET_ISP1_SYS_PWR);
+       val = (val & ~(0x1 << 0)) | (0x0 << 0);
+       __raw_writel(val, PMUREG_CMU_RESET_ISP1_SYS_PWR);
+
+       /* 2. change to OSCCLK */
+       ret = core->pdata->clk_off(pdev);
+       if (ret)
+               warn("clk_off is fail(%d)", ret);
+
+       /* 3. set feedback mode */
+       val = __raw_readl(PMUREG_ISP1_OPTION);
+       val = (val & ~(0x3 << 0)) | (0x2 << 0);
+       __raw_writel(val, PMUREG_ISP1_OPTION);
+
+       /* 4. power off */
+       val = __raw_readl(PMUREG_ISP1_CONFIGURATION);
+       val = (val & ~(0x7 << 0)) | (0x0 << 0);
+       __raw_writel(val, PMUREG_ISP1_CONFIGURATION);
+
+       /* ISP0 */
+       /* 1. set internal clock reset */
+       val = __raw_readl(PMUREG_CMU_RESET_ISP0_SYS_PWR);
+       val = (val & ~(0x1 << 0)) | (0x0 << 0);
+       __raw_writel(val, PMUREG_CMU_RESET_ISP0_SYS_PWR);
+
+       /* 2. set standbywfi a5 */
+       val = __raw_readl(PMUREG_CENTRAL_SEQ_OPTION);
+       val = (val & ~(0x1 << 18)) | (0x1 << 18);
+       __raw_writel(val, PMUREG_CENTRAL_SEQ_OPTION);
+
+       /* 3. stop a5 */
+       __raw_writel(0x00010000, PMUREG_ISP_ARM_OPTION);
+
+       /* 4. reset a5 */
+       val = __raw_readl(PMUREG_ISP_ARM_SYS_PWR_REG);
+       val = (val & ~(0x1 << 0)) | (0x1 << 0);
+       __raw_writel(val, PMUREG_ISP_ARM_SYS_PWR_REG);
+
+       /* 5. change to OSCCLK */
+
+       /* 6. set feedback mode */
+       val = __raw_readl(PMUREG_ISP0_OPTION);
+       val = (val & ~(0x3 << 0)) | (0x2 << 0);
+       __raw_writel(val, PMUREG_ISP0_OPTION);
+
+       /* 7. power off */
+       val = __raw_readl(PMUREG_ISP0_CONFIGURATION);
+       val = (val & ~(0x7 << 0)) | (0x0 << 0);
+       __raw_writel(val, PMUREG_ISP0_CONFIGURATION);
+
+       /* 8. a5 power off */
+       val = __raw_readl(PMUREG_ISP_ARM_CONFIGURATION);
+       val = (val & ~(0x1 << 0)) | (0x0 << 0);
+       __raw_writel(val, PMUREG_ISP_ARM_CONFIGURATION);
+#endif
+
+#if defined(CONFIG_PM_DEVFREQ)
+       /* DEVFREQ release */
+       fimc_is_set_qos_init(core, false);
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+       if (CALL_POPS(core, clk_off, pdev) < 0)
+               warn("clk_off is fail\n");
+#endif
+
+       info("FIMC_IS runtime suspend out\n");
+       pm_relax(dev);
+       return 0;
+}
+
+int fimc_is_runtime_resume(struct device *dev)
+{
+       int ret = 0;
+       u32 val;
+
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(pdev);
+
+       BUG_ON(!core);
+       BUG_ON(!core->pdata);
+       BUG_ON(!core->pdata->clk_cfg);
+       BUG_ON(!core->pdata->clk_on);
+
+       info("FIMC_IS runtime resume in\n");
+
+       val  = __raw_readl(PMUREG_ISP0_STATUS);
+       if((val & 0x7) != 0x7){
+           err("FIMC_IS runtime resume ISP0 : %d Power down\n",val);
+           BUG();
+       }
+
+       val = __raw_readl(PMUREG_ISP1_STATUS);
+       if((val & 0x7) != 0x7){
+           err("FIMC_IS runtime resume ISP1 : %d Power down\n",val);
+           BUG();
+       }
+
+#ifndef CONFIG_PM_RUNTIME
+       /* ISP0 */
+       /* 1. set feedback mode */
+       val = __raw_readl(PMUREG_ISP0_OPTION);
+       val = (val & ~(0x3<< 0)) | (0x2 << 0);
+       __raw_writel(val, PMUREG_ISP0_OPTION);
+
+       /* 2. power on isp0 */
+       val = __raw_readl(PMUREG_ISP0_CONFIGURATION);
+       val = (val & ~(0x7 << 0)) | (0x7 << 0);
+       __raw_writel(val, PMUREG_ISP0_CONFIGURATION);
+
+       /* ISP1 */
+       /* 3. set feedback mode */
+       val = __raw_readl(PMUREG_ISP1_OPTION);
+       val = (val & ~(0x3<< 0)) | (0x2 << 0);
+       __raw_writel(val, PMUREG_ISP1_OPTION);
+
+       /* 4. power on isp1 */
+       val = __raw_readl(PMUREG_ISP1_CONFIGURATION);
+       val = (val & ~(0x7 << 0)) | (0x7 << 0);
+       __raw_writel(val, PMUREG_ISP1_CONFIGURATION);
+#endif
+
+       ret = core->pdata->clk_cfg(pdev);
+       if (ret) {
+               err("clk_cfg is fail(%d)", ret);
+               goto p_err;
+       }
+
+       /* HACK: DVFS lock sequence is change.
+        * DVFS level should be locked after power on.
+        */
+#if defined(CONFIG_PM_DEVFREQ)
+       /* DEVFREQ set */
+       fimc_is_set_qos_init(core, true);
+#endif
+
+       /* Clock on */
+       ret = core->pdata->clk_on(pdev);
+       if (ret) {
+               err("clk_on is fail(%d)", ret);
+               goto p_err;
+       }
+
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (core->mem.alloc_ctx)
+               vb2_ion_attach_iommu(core->mem.alloc_ctx);
+#endif
+
+#if defined(CONFIG_FIMC_IS_BUS_DEVFREQ)
+       exynos5_update_media_layers(TYPE_FIMC_LITE, true);
+#endif
+
+       pm_stay_awake(dev);
+
+p_err:
+       info("FIMC-IS runtime resume out\n");
+       return ret;
+}
+
+#else
+int fimc_is_runtime_suspend_post(struct device *dev)
+{
+       int ret = 0;
+       u32 timeout;
+
+       timeout = 2000;
+       while ((readl(PMUREG_ISP_STATUS) & 0x1) && timeout) {
+               timeout--;
+               usleep_range(1000, 1000);
+       }
+       if (timeout == 0)
+               err("ISP power down failed(0x%08x)\n",
+                       readl(PMUREG_ISP_STATUS));
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       timeout = 1000;
+       while ((readl(PMUREG_CAM0_STATUS) & 0x1) && timeout) {
+               timeout--;
+               usleep_range(1000, 1000);
+       }
+       if (timeout == 0)
+               err("CAM0 power down failed(0x%08x)\n",
+                       readl(PMUREG_CAM0_STATUS));
+
+       timeout = 2000;
+       while ((readl(PMUREG_CAM1_STATUS) & 0x1) && timeout) {
+               timeout--;
+               usleep_range(1000, 1000);
+       }
+       if (timeout == 0)
+               err("CAM1 power down failed(CAM1:0x%08x, A5:0x%08x)\n",
+                       readl(PMUREG_CAM1_STATUS), readl(PMUREG_ISP_ARM_STATUS));
+#endif /* defined(CONFIG_SOC_EXYNOS5430) */
+
+#if defined(CONFIG_SOC_EXYNOS5422)
+#endif /* defined(CONFIG_SOC_EXYNOS5422) */
+
+       return ret;
+}
+
+int fimc_is_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_core *core
+               = (struct fimc_is_core *)platform_get_drvdata(pdev);
+
+       BUG_ON(!core);
+       BUG_ON(!core->pdata);
+       BUG_ON(!core->pdata->clk_off);
+
+       pr_info("FIMC_IS runtime suspend in\n");
+
+#if !(defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433))
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (core->mem.alloc_ctx)
+               vb2_ion_detach_iommu(core->mem.alloc_ctx);
+#endif
+#endif
+
+#if defined(CONFIG_PM_DEVFREQ)
+       /* DEVFREQ set */
+       fimc_is_set_qos_init(core, false);
+#endif
+
+#if defined(CONFIG_ARGOS)
+       argos_block_enable("EMMC", false);
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+       /* EGL Release */
+       pm_qos_update_request(&max_cpu_qos, PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE);
+       pm_qos_remove_request(&max_cpu_qos);
+#endif /* CONFIG_SOC_EXYNOS5422 */
+
+#if defined(CONFIG_FIMC_IS_BUS_DEVFREQ)
+       /* BTS */
+#if defined(CONFIG_SOC_EXYNOS5260)
+       bts_initialize("spd-flite-a", false);
+       bts_initialize("spd-flite-b", false);
+#elif defined(CONFIG_SOC_EXYNOS3470)
+       bts_initialize("pd-cam", false);
+#else
+       bts_initialize("pd-fimclite", false);
+#endif
+       /* media layer */
+       exynos5_update_media_layers(TYPE_FIMC_LITE, false);
+#endif /* CONFIG_FIMC_IS_BUS_DEVFREQ */
+
+       if (CALL_POPS(core, clk_off, pdev) < 0)
+               warn("clk_off is fail\n");
+
+       pr_info("FIMC_IS runtime suspend out\n");
+
+       pm_relax(dev);
+       return 0;
+}
+
+int fimc_is_runtime_resume(struct device *dev)
+{
+       int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_core *core
+               = (struct fimc_is_core *)platform_get_drvdata(pdev);
+
+       pm_stay_awake(dev);
+       pr_info("FIMC_IS runtime resume in\n");
+
+#if defined(CONFIG_ARGOS)
+       argos_block_enable("EMMC", true);
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS5430)
+       /* EGL Lock */
+       pm_qos_add_request(&max_cpu_qos, PM_QOS_CPU_FREQ_MAX, 1600000);
+#elif defined(CONFIG_SOC_EXYNOS5433)
+       /* EGL Lock */
+       pm_qos_add_request(&max_cpu_qos, PM_QOS_CPU_FREQ_MAX, 1700000);
+#endif /* CONFIG_SOC_EXYNOS5422 */
+
+       /* HACK: DVFS lock sequence is change.
+        * DVFS level should be locked after power on.
+        */
+#if defined(CONFIG_PM_DEVFREQ)
+       /* DEVFREQ set */
+       fimc_is_set_qos_init(core, true);
+#endif
+
+       /* Low clock setting */
+       if (CALL_POPS(core, clk_cfg, core->pdev) < 0) {
+               err("clk_cfg is fail\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* Clock on */
+       if (CALL_POPS(core, clk_on, core->pdev) < 0) {
+               err("clk_on is fail\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+#if !(defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433))
+#if defined(CONFIG_VIDEOBUF2_ION)
+       if (core->mem.alloc_ctx)
+               vb2_ion_attach_iommu(core->mem.alloc_ctx);
+#endif
+#endif
+
+#if defined(CONFIG_FIMC_IS_BUS_DEVFREQ)
+       /* BTS */
+#if defined(CONFIG_SOC_EXYNOS5260)
+       bts_initialize("spd-flite-a", true);
+       bts_initialize("spd-flite-b", true);
+#elif defined(CONFIG_SOC_EXYNOS3470)
+       bts_initialize("pd-cam", true);
+#else
+       bts_initialize("pd-fimclite", true);
+#endif
+       /* media layer */
+       exynos5_update_media_layers(TYPE_FIMC_LITE, true);
+#endif /* CONFIG_FIMC_IS_BUS_DEVFREQ */
+
+       pr_info("FIMC-IS runtime resume out\n");
+
+       return 0;
+
+p_err:
+       pm_relax(dev);
+       return ret;
+}
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-hw.h b/drivers/media/platform/exynos/fimc-is/fimc-is-hw.h
new file mode 100644 (file)
index 0000000..8a75671
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_HW_H
+#define FIMC_IS_HW_H
+
+#define CSI_VIRTUAL_CH_0       0
+#define CSI_VIRTUAL_CH_1       1
+#define CSI_VIRTUAL_CH_2       2
+#define CSI_VIRTUAL_CH_3       3
+#define CSI_VIRTUAL_CH_MAX     4
+
+#define CSI_DATA_LANES_1       0
+#define CSI_DATA_LANES_2       1
+#define CSI_DATA_LANES_3       2
+#define CSI_DATA_LANES_4       3
+
+#define CSI_MODE_CH0_ONLY      0
+#define CSI_MODE_DT_ONLY       1
+#define CSI_MODE_VC_ONLY       2
+#define CSI_MODE_VC_DT         3
+
+#define HW_FORMAT_YUV420_8BIT  0x18
+#define HW_FORMAT_YUV420_10BIT 0x19
+#define HW_FORMAT_YUV422_8BIT  0x1E
+#define HW_FORMAT_YUV422_10BIT 0x1F
+#define HW_FORMAT_RGB565       0x22
+#define HW_FORMAT_RGB666       0x23
+#define HW_FORMAT_RGB888       0x24
+#define HW_FORMAT_RAW6         0x28
+#define HW_FORMAT_RAW7         0x29
+#define HW_FORMAT_RAW8         0x2A
+#define HW_FORMAT_RAW10                0x2B
+#define HW_FORMAT_RAW12                0x2C
+#define HW_FORMAT_RAW14                0x2D
+#define HW_FORMAT_USER         0x30
+
+struct fimc_is_vci {
+       u32                     pixelformat;
+       u32                     vc_map[CSI_VIRTUAL_CH_MAX];
+};
+
+int csi_hw_reset(unsigned long __iomem *base_reg);
+int csi_hw_s_settle(unsigned long __iomem *base_reg, u32 settle);
+int csi_hw_s_control(unsigned long __iomem *base_reg, u32 pixelformat, u32 mode, u32 lanes);
+int csi_hw_s_config(unsigned long __iomem *base_reg, u32 vc_src, u32 vc_dst, u32 pixelformat, u32 width, u32 height);
+int csi_hw_s_interrupt(unsigned long __iomem *base_reg, bool on);
+int csi_hw_g_interrupt(unsigned long __iomem *base_reg);
+int csi_hw_enable(unsigned long __iomem *base_reg);
+int csi_hw_disable(unsigned long __iomem *base_reg);
+
+int fimc_is_runtime_suspend_post(struct device *dev);
+int fimc_is_runtime_suspend(struct device *dev);
+int fimc_is_runtime_resume(struct device *dev);
+#endif
\ No newline at end of file
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-interface.c b/drivers/media/platform/exynos/fimc-is/fimc-is-interface.c
new file mode 100644 (file)
index 0000000..e7ad6a8
--- /dev/null
@@ -0,0 +1,3213 @@
+/*
+ * drivers/media/video/exynos/fimc-is-mc2/fimc-is-interface.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * The header file related to camera
+ *
+ * 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.
+ */
+
+#include <linux/workqueue.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-groupmgr.h"
+
+#include "fimc-is-interface.h"
+#include "fimc-is-clk-gate.h"
+
+u32 __iomem *notify_fcount_sen0;
+u32 __iomem *notify_fcount_sen1;
+u32 __iomem *notify_fcount_sen2;
+u32 __iomem *last_fcount0;
+u32 __iomem *last_fcount1;
+
+#define init_request_barrier(itf) mutex_init(&itf->request_barrier)
+#define enter_request_barrier(itf) mutex_lock(&itf->request_barrier);
+#define exit_request_barrier(itf) mutex_unlock(&itf->request_barrier);
+#define init_process_barrier(itf) spin_lock_init(&itf->process_barrier);
+#define enter_process_barrier(itf) spin_lock_irq(&itf->process_barrier);
+#define exit_process_barrier(itf) spin_unlock_irq(&itf->process_barrier);
+
+extern struct fimc_is_sysfs_debug sysfs_debug;
+
+/* func to register error report callback */
+int fimc_is_set_err_report_vendor(struct fimc_is_interface *itf,
+               void *err_report_data,
+               int (*err_report_vendor)(void *data, u32 err_report_type))
+{
+       if (itf) {
+               itf->err_report_data = err_report_data;
+               itf->err_report_vendor = err_report_vendor;
+       }
+
+       return 0;
+}
+
+/* main func to handle error report */
+static int fimc_is_err_report_handler(struct fimc_is_interface *itf, struct fimc_is_msg *msg)
+{
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_core *core;
+       unsigned long dtp_wait_time;
+
+       core = itf->core;
+       device = &core->ischain[msg->instance];
+       dtp_wait_time = device->sensor->dtp_timer.expires;
+
+       err("IHC_REPORT_ERR(%d,%d,%d,%d,%d) is occured",
+                       msg->instance,
+                       msg->group,
+                       msg->parameter1,
+                       msg->parameter2,
+                       msg->parameter3);
+
+       /*
+        * if vendor error report func was registered,
+        * call the func.
+        */
+       if (itf->err_report_vendor)
+               itf->err_report_vendor(itf->err_report_data, msg->parameter2);
+
+       switch (msg->parameter2) {
+       case REPORT_ERR_CIS_ID:
+               warn("Occured the ERR_ID");
+               break;
+       case REPORT_ERR_CIS_ECC:
+               warn("Occured the ERR_ECC");
+       case REPORT_ERR_CIS_CRC:
+               warn("Occured the ERR_CRC");
+#ifdef ENABLE_DTP
+               if (dtp_wait_time >= jiffies)
+                       set_bit(FIMC_IS_BAD_FRAME_STOP, &device->sensor->force_stop);
+#endif
+               break;
+       case REPORT_ERR_CIS_OVERFLOW_VC0:
+               warn("Occured the OVERFLOW_VC0");
+               break;
+       case REPORT_ERR_CIS_LOST_FE_VC0:
+               warn("Occured the LOST_FE_VC0");
+               break;
+       case REPORT_ERR_CIS_LOST_FS_VC0:
+               warn("Occured the LOST_FS_VC0");
+               break;
+       case REPORT_ERR_CIS_SOT_VC0:
+               warn("Occured the SOT_VC0");
+               break;
+       case REPORT_ERR_CIS_SOT_VC1:
+               warn("Occured the SOT_VC1");
+               break;
+       case REPORT_ERR_CIS_SOT_VC2:
+               warn("Occured the SOT_VC2");
+               break;
+       case REPORT_ERR_CIS_SOT_VC3:
+               warn("Occured the SOT_VC3");
+               break;
+       case REPORT_ERR_3AA_OVERFLOW:
+               warn("Occured the 3AA_OVERFLOW");
+               break;
+       case REPORT_ERR_FLITE_D_OVERFLOW:
+               warn("Occured the FLITE_D_OVERFLOW");
+               break;
+       case REPORT_ERR_COMPANION_LOST_FRAME:
+               warn("Occured the COMPANION_LOST_FRAME");
+               break;
+       case REPORT_ERR_3A_ALGORITHM_DELAYED:
+               warn("Occured the 3A_ALGORITHM_DELAYED");
+               break;
+
+       default:
+               warn("parameter is default");
+               break;
+       }
+
+       return 0;
+}
+
+int print_fre_work_list(struct fimc_is_work_list *this)
+{
+       struct list_head *temp;
+       struct fimc_is_work *work;
+
+       if (!(this->id & TRACE_WORK_ID_MASK))
+               return 0;
+
+       printk(KERN_ERR "[INF] fre(%02X, %02d) :",
+               this->id, this->work_free_cnt);
+
+       list_for_each(temp, &this->work_free_head) {
+               work = list_entry(temp, struct fimc_is_work, list);
+               printk(KERN_CONT "%X(%d)->", work->msg.command, work->fcount);
+       }
+
+       printk(KERN_CONT "X\n");
+
+       return 0;
+}
+
+static int set_free_work(struct fimc_is_work_list *this,
+       struct fimc_is_work *work)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (work) {
+               spin_lock_irqsave(&this->slock_free, flags);
+
+               list_add_tail(&work->list, &this->work_free_head);
+               this->work_free_cnt++;
+#ifdef TRACE_WORK
+               print_fre_work_list(this);
+#endif
+
+               spin_unlock_irqrestore(&this->slock_free, flags);
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+static int get_free_work(struct fimc_is_work_list *this,
+       struct fimc_is_work **work)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (work) {
+               spin_lock_irqsave(&this->slock_free, flags);
+
+               if (this->work_free_cnt) {
+                       *work = container_of(this->work_free_head.next,
+                                       struct fimc_is_work, list);
+                       list_del(&(*work)->list);
+                       this->work_free_cnt--;
+               } else
+                       *work = NULL;
+
+               spin_unlock_irqrestore(&this->slock_free, flags);
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr");
+       }
+
+       return ret;
+}
+
+static int get_free_work_irq(struct fimc_is_work_list *this,
+       struct fimc_is_work **work)
+{
+       int ret = 0;
+
+       if (work) {
+               spin_lock(&this->slock_free);
+
+               if (this->work_free_cnt) {
+                       *work = container_of(this->work_free_head.next,
+                                       struct fimc_is_work, list);
+                       list_del(&(*work)->list);
+                       this->work_free_cnt--;
+               } else
+                       *work = NULL;
+
+               spin_unlock(&this->slock_free);
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr");
+       }
+
+       return ret;
+}
+
+int print_req_work_list(struct fimc_is_work_list *this)
+{
+       struct list_head *temp;
+       struct fimc_is_work *work;
+
+       if (!(this->id & TRACE_WORK_ID_MASK))
+               return 0;
+
+       printk(KERN_ERR "[INF] req(%02X, %02d) :",
+               this->id, this->work_request_cnt);
+
+       list_for_each(temp, &this->work_request_head) {
+               work = list_entry(temp, struct fimc_is_work, list);
+               printk(KERN_CONT "%X(%d)->", work->msg.command, work->fcount);
+       }
+
+       printk(KERN_CONT "X\n");
+
+       return 0;
+}
+
+static int print_work_data_state(struct fimc_is_interface *this)
+{
+       struct work_struct *work;
+       unsigned long *bits = NULL;
+
+       work = &this->work_wq[INTR_GENERAL];
+       bits = (work_data_bits(work));
+       info("INTR_GENERAL wq state : (0x%lx)", *bits);
+       work = &this->work_wq[INTR_3A0C_FDONE];
+       bits = (work_data_bits(work));
+       info("INTR_3A0C_FDONE wq state : (0x%lx)", *bits);
+       work = &this->work_wq[INTR_3A1C_FDONE];
+       bits = (work_data_bits(work));
+       info("INTR_3A1C_FDONE wq state : (0x%lx)", *bits);
+       work = &this->work_wq[INTR_SCC_FDONE];
+       bits = (work_data_bits(work));
+       info("INTR_SCC_FDONE wq state : (0x%lx)", *bits);
+       work = &this->work_wq[INTR_DIS_FDONE];
+       bits = (work_data_bits(work));
+       info("INTR_DIS_FDONE wq state : (0x%lx)", *bits);
+       work = &this->work_wq[INTR_SCP_FDONE];
+       bits = (work_data_bits(work));
+       info("INTR_SCP_FDONE wq state : (0x%lx)", *bits);
+       work = &this->work_wq[INTR_SHOT_DONE];
+       bits = (work_data_bits(work));
+       info("INTR_SHOT_DONE wq state : (0x%lx)", *bits);
+
+       return 0;
+}
+
+static int set_req_work(struct fimc_is_work_list *this,
+       struct fimc_is_work *work)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (work) {
+               spin_lock_irqsave(&this->slock_request, flags);
+
+               list_add_tail(&work->list, &this->work_request_head);
+               this->work_request_cnt++;
+#ifdef TRACE_WORK
+               print_req_work_list(this);
+#endif
+
+               spin_unlock_irqrestore(&this->slock_request, flags);
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+static int set_req_work_irq(struct fimc_is_work_list *this,
+       struct fimc_is_work *work)
+{
+       int ret = 0;
+
+       if (work) {
+               spin_lock(&this->slock_request);
+
+               list_add_tail(&work->list, &this->work_request_head);
+               this->work_request_cnt++;
+#ifdef TRACE_WORK
+               print_req_work_list(this);
+#endif
+
+               spin_unlock(&this->slock_request);
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+static int get_req_work(struct fimc_is_work_list *this,
+       struct fimc_is_work **work)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (work) {
+               spin_lock_irqsave(&this->slock_request, flags);
+
+               if (this->work_request_cnt) {
+                       *work = container_of(this->work_request_head.next,
+                                       struct fimc_is_work, list);
+                       list_del(&(*work)->list);
+                       this->work_request_cnt--;
+               } else
+                       *work = NULL;
+
+               spin_unlock_irqrestore(&this->slock_request, flags);
+       } else {
+               ret = -EFAULT;
+               err("item is null ptr\n");
+       }
+
+       return ret;
+}
+
+static void init_work_list(struct fimc_is_work_list *this, u32 id, u32 count)
+{
+       u32 i;
+
+       this->id = id;
+       this->work_free_cnt     = 0;
+       this->work_request_cnt  = 0;
+       INIT_LIST_HEAD(&this->work_free_head);
+       INIT_LIST_HEAD(&this->work_request_head);
+       spin_lock_init(&this->slock_free);
+       spin_lock_init(&this->slock_request);
+       for (i = 0; i < count; ++i)
+               set_free_work(this, &this->work[i]);
+
+       init_waitqueue_head(&this->wait_queue);
+}
+
+static int set_busystate(struct fimc_is_interface *this,
+       u32 command)
+{
+       int ret;
+
+       ret = test_and_set_bit(IS_IF_STATE_BUSY, &this->state);
+       if (ret)
+               warn("%d command : busy state is already set", command);
+
+       return ret;
+}
+
+static int clr_busystate(struct fimc_is_interface *this,
+       u32 command)
+{
+       int ret;
+
+       ret = test_and_clear_bit(IS_IF_STATE_BUSY, &this->state);
+       if (!ret)
+               warn("%d command : busy state is already clr", command);
+
+       return !ret;
+}
+
+static int test_busystate(struct fimc_is_interface *this)
+{
+       int ret = 0;
+
+       ret = test_bit(IS_IF_STATE_BUSY, &this->state);
+
+       return ret;
+}
+
+static int wait_lockstate(struct fimc_is_interface *this)
+{
+       int ret = 0;
+
+       ret = wait_event_timeout(this->lock_wait_queue,
+               !atomic_read(&this->lock_pid), FIMC_IS_COMMAND_TIMEOUT);
+       if (ret) {
+               ret = 0;
+       } else {
+               err("timeout");
+               ret = -ETIME;
+       }
+
+       return ret;
+}
+
+static int wait_idlestate(struct fimc_is_interface *this)
+{
+       int ret = 0;
+
+       ret = wait_event_timeout(this->idle_wait_queue,
+               !test_busystate(this), FIMC_IS_COMMAND_TIMEOUT);
+       if (ret) {
+               ret = 0;
+       } else {
+               err("timeout");
+               ret = -ETIME;
+       }
+
+       return ret;
+}
+
+static int wait_initstate(struct fimc_is_interface *this)
+{
+       int ret = 0;
+
+       ret = wait_event_timeout(this->init_wait_queue,
+               test_bit(IS_IF_STATE_START, &this->state),
+               FIMC_IS_STARTUP_TIMEOUT);
+       if (ret) {
+               ret = 0;
+       } else {
+               err("timeout");
+               ret = -ETIME;
+       }
+
+       return ret;
+}
+
+static void testnclr_wakeup(struct fimc_is_interface *this,
+       u32 command)
+{
+       int ret = 0;
+
+       ret = clr_busystate(this, command);
+       if (ret)
+               err("current state is invalid(%ld)", this->state);
+
+       wake_up(&this->idle_wait_queue);
+}
+
+static int waiting_is_ready(struct fimc_is_interface *interface)
+{
+       int ret = 0;
+       u32 try_count = TRY_RECV_AWARE_COUNT;
+       u32 cfg = readl(interface->regs + INTMSR0);
+       u32 status = INTMSR0_GET_INTMSD0(cfg);
+
+       while (status) {
+               cfg = readl(interface->regs + INTMSR0);
+               status = INTMSR0_GET_INTMSD0(cfg);
+               udelay(100);
+               dbg("Retry to read INTMSR0(%d)\n", try_count);
+
+               if (--try_count == 0) {
+                       err("INTMSR0's 0 bit is not cleared.");
+                       ret = -EINVAL;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static void send_interrupt(struct fimc_is_interface *interface)
+{
+       writel(INTGR0_INTGD0, interface->regs + INTGR0);
+}
+
+static int fimc_is_set_cmd(struct fimc_is_interface *itf,
+       struct fimc_is_msg *msg,
+       struct fimc_is_msg *reply)
+{
+       int ret = 0;
+       int wait_lock = 0;
+       u32 lock_pid = 0;
+       u32 id;
+       volatile struct is_common_reg __iomem *com_regs;
+#ifdef MEASURE_TIME
+#ifdef INTERFACE_TIME
+       struct timeval measure_str, measure_end;
+#endif
+#endif
+
+       BUG_ON(!itf);
+       BUG_ON(!msg);
+       BUG_ON(msg->instance >= FIMC_IS_MAX_NODES);
+       BUG_ON(msg->command >= HIC_COMMAND_END);
+       BUG_ON(!reply);
+
+       if (!test_bit(IS_IF_STATE_OPEN, &itf->state)) {
+               warn("interface close, %d cmd is cancel", msg->command);
+               goto exit;
+       }
+
+       lock_pid = atomic_read(&itf->lock_pid);
+       if (lock_pid && (lock_pid != current->pid)) {
+               pr_info("itf LOCK, %d(%d) wait\n", current->pid, msg->command);
+               wait_lock = wait_lockstate(itf);
+               pr_info("itf UNLOCK, %d(%d) go\n", current->pid, msg->command);
+               if (wait_lock) {
+                       err("wait_lockstate is fail, lock reset");
+                       atomic_set(&itf->lock_pid, 0);
+               }
+       }
+
+       dbg_interface("TP#1\n");
+       enter_request_barrier(itf);
+       dbg_interface("TP#2\n");
+
+#ifdef MEASURE_TIME
+#ifdef INTERFACE_TIME
+       do_gettimeofday(&measure_str);
+#endif
+#endif
+
+       switch (msg->command) {
+       case HIC_STREAM_ON:
+               if (itf->streaming[msg->instance] == IS_IF_STREAMING_ON)
+                       warn("already stream on");
+               break;
+       case HIC_STREAM_OFF:
+               if (itf->streaming[msg->instance] == IS_IF_STREAMING_OFF)
+                       warn("already stream off");
+               break;
+       case HIC_PROCESS_START:
+               if (itf->processing[msg->instance] == IS_IF_PROCESSING_ON)
+                       warn("already process on");
+               break;
+       case HIC_PROCESS_STOP:
+               if (itf->processing[msg->instance] == IS_IF_PROCESSING_OFF)
+                       warn("already process off");
+               break;
+       case HIC_POWER_DOWN:
+               if (itf->pdown_ready == IS_IF_POWER_DOWN_READY)
+                       warn("already powerdown ready");
+               break;
+       default:
+               if (itf->pdown_ready == IS_IF_POWER_DOWN_READY) {
+                       exit_request_barrier(itf);
+                       warn("already powerdown ready, %d cmd is cancel",
+                               msg->command);
+                       goto exit;
+               }
+               break;
+       }
+
+       enter_process_barrier(itf);
+
+       ret = waiting_is_ready(itf);
+       if (ret) {
+               exit_request_barrier(itf);
+               exit_process_barrier(itf);
+               err("waiting for ready is fail");
+               ret = -EBUSY;
+               goto exit;
+       }
+
+       set_busystate(itf, msg->command);
+       com_regs = itf->com_regs;
+       id = (msg->group << GROUP_ID_SHIFT) | msg->instance;
+       writel(msg->command, &com_regs->hicmd);
+       writel(id, &com_regs->hic_sensorid);
+       writel(msg->parameter1, &com_regs->hic_param1);
+       writel(msg->parameter2, &com_regs->hic_param2);
+       writel(msg->parameter3, &com_regs->hic_param3);
+       writel(msg->parameter4, &com_regs->hic_param4);
+       send_interrupt(itf);
+
+       exit_process_barrier(itf);
+
+       ret = wait_idlestate(itf);
+       if (ret) {
+               exit_request_barrier(itf);
+               err("%d command is timeout", msg->command);
+               fimc_is_hw_regdump(itf);
+               print_req_work_list(&itf->work_list[INTR_GENERAL]);
+               print_work_data_state(itf);
+               clr_busystate(itf, msg->command);
+               ret = -ETIME;
+               goto exit;
+       }
+
+       reply->command = itf->reply.command;
+       reply->group = itf->reply.group;
+       reply->instance = itf->reply.instance;
+       reply->parameter1 = itf->reply.parameter1;
+       reply->parameter2 = itf->reply.parameter2;
+       reply->parameter3 = itf->reply.parameter3;
+       reply->parameter4 = itf->reply.parameter4;
+
+       if (reply->command == ISR_DONE) {
+               if (msg->command != reply->parameter1) {
+                       exit_request_barrier(itf);
+                       err("invalid command reply(%d != %d)", msg->command, reply->parameter1);
+                       ret = -EINVAL;
+                       goto exit;
+               }
+
+               switch (msg->command) {
+               case HIC_STREAM_ON:
+                       itf->streaming[msg->instance] = IS_IF_STREAMING_ON;
+                       break;
+               case HIC_STREAM_OFF:
+                       itf->streaming[msg->instance] = IS_IF_STREAMING_OFF;
+                       break;
+               case HIC_PROCESS_START:
+                       itf->processing[msg->instance] = IS_IF_PROCESSING_ON;
+                       break;
+               case HIC_PROCESS_STOP:
+                       itf->processing[msg->instance] = IS_IF_PROCESSING_OFF;
+                       break;
+               case HIC_POWER_DOWN:
+                       itf->pdown_ready = IS_IF_POWER_DOWN_READY;
+                       break;
+               case HIC_OPEN_SENSOR:
+                       if (reply->parameter1 == HIC_POWER_DOWN) {
+                               err("firmware power down");
+                               itf->pdown_ready = IS_IF_POWER_DOWN_READY;
+                               ret = -ECANCELED;
+                       } else {
+                               itf->pdown_ready = IS_IF_POWER_DOWN_NREADY;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               err("ISR_NDONE is occured");
+               ret = -EINVAL;
+       }
+
+#ifdef MEASURE_TIME
+#ifdef INTERFACE_TIME
+       do_gettimeofday(&measure_end);
+       measure_time(&itf->time[msg->command],
+               msg->instance,
+               msg->group,
+               &measure_str,
+               &measure_end);
+#endif
+#endif
+
+       exit_request_barrier(itf);
+
+exit:
+       if (ret)
+               fimc_is_hw_logdump(itf);
+
+       return ret;
+}
+
+static int fimc_is_set_cmd_shot(struct fimc_is_interface *this,
+       struct fimc_is_msg *msg)
+{
+       int ret = 0;
+       u32 id;
+       volatile struct is_common_reg __iomem *com_regs;
+
+       BUG_ON(!this);
+       BUG_ON(!msg);
+       BUG_ON(msg->instance >= FIMC_IS_MAX_NODES);
+
+       if (!test_bit(IS_IF_STATE_OPEN, &this->state)) {
+               warn("interface close, %d cmd is cancel", msg->command);
+               goto exit;
+       }
+
+       enter_process_barrier(this);
+
+       ret = waiting_is_ready(this);
+       if (ret) {
+               exit_process_barrier(this);
+               err("waiting for ready is fail");
+               ret = -EBUSY;
+               goto exit;
+       }
+
+       spin_lock_irq(&this->shot_check_lock);
+       atomic_set(&this->shot_check[msg->instance], 1);
+       spin_unlock_irq(&this->shot_check_lock);
+
+       com_regs = this->com_regs;
+       id = (msg->group << GROUP_ID_SHIFT) | msg->instance;
+       writel(msg->command, &com_regs->hicmd);
+       writel(id, &com_regs->hic_sensorid);
+       writel(msg->parameter1, &com_regs->hic_param1);
+       writel(msg->parameter2, &com_regs->hic_param2);
+       writel(msg->parameter3, &com_regs->hic_param3);
+       writel(msg->parameter4, &com_regs->hic_param4);
+       send_interrupt(this);
+
+       exit_process_barrier(this);
+
+exit:
+       return ret;
+}
+
+static int fimc_is_set_cmd_nblk(struct fimc_is_interface *this,
+       struct fimc_is_work *work)
+{
+       int ret = 0;
+       u32 id;
+       struct fimc_is_msg *msg;
+       volatile struct is_common_reg __iomem *com_regs;
+
+       msg = &work->msg;
+       switch (msg->command) {
+       case HIC_SET_CAM_CONTROL:
+               set_req_work(&this->nblk_cam_ctrl, work);
+               break;
+       case HIC_MSG_TEST:
+               break;
+       default:
+               err("unresolved command\n");
+               break;
+       }
+
+       enter_process_barrier(this);
+
+       ret = waiting_is_ready(this);
+       if (ret) {
+               err("waiting for ready is fail");
+               ret = -EBUSY;
+               goto exit;
+       }
+
+       com_regs = this->com_regs;
+       id = (msg->group << GROUP_ID_SHIFT) | msg->instance;
+       writel(msg->command, &com_regs->hicmd);
+       writel(id, &com_regs->hic_sensorid);
+       writel(msg->parameter1, &com_regs->hic_param1);
+       writel(msg->parameter2, &com_regs->hic_param2);
+       writel(msg->parameter3, &com_regs->hic_param3);
+       writel(msg->parameter4, &com_regs->hic_param4);
+       send_interrupt(this);
+
+exit:
+       exit_process_barrier(this);
+       return ret;
+}
+
+static inline void fimc_is_get_cmd(struct fimc_is_interface *itf,
+       struct fimc_is_msg *msg, u32 index)
+{
+       volatile struct is_common_reg __iomem *com_regs = itf->com_regs;
+
+       switch (index) {
+       case INTR_GENERAL:
+               msg->id = 0;
+               msg->command = readl(&com_regs->ihcmd);
+               msg->instance = readl(&com_regs->ihc_sensorid);
+               msg->parameter1 = readl(&com_regs->ihc_param1);
+               msg->parameter2 = readl(&com_regs->ihc_param2);
+               msg->parameter3 = readl(&com_regs->ihc_param3);
+               msg->parameter4 = readl(&com_regs->ihc_param4);
+               break;
+       case INTR_3A0C_FDONE:
+               msg->id = 0;
+               msg->command = IHC_FRAME_DONE;
+               msg->instance = readl(&com_regs->taa0c_sensor_id);
+               msg->parameter1 = readl(&com_regs->taa0c_param1);
+               msg->parameter2 = readl(&com_regs->taa0c_param2);
+               msg->parameter3 = readl(&com_regs->taa0c_param3);
+               msg->parameter4 = 0;
+               break;
+       case INTR_3A1C_FDONE:
+               msg->id = 0;
+               msg->command = IHC_FRAME_DONE;
+               msg->instance = readl(&com_regs->taa1c_sensor_id);
+               msg->parameter1 = readl(&com_regs->taa1c_param1);
+               msg->parameter2 = readl(&com_regs->taa1c_param2);
+               msg->parameter3 = readl(&com_regs->taa1c_param3);
+               msg->parameter4 = 0;
+               break;
+       case INTR_SCC_FDONE:
+               msg->id = 0;
+               msg->command = IHC_FRAME_DONE;
+               msg->instance = readl(&com_regs->scc_sensor_id);
+               msg->parameter1 = readl(&com_regs->scc_param1);
+               msg->parameter2 = readl(&com_regs->scc_param2);
+               msg->parameter3 = readl(&com_regs->scc_param3);
+               msg->parameter4 = 0;
+               break;
+       case INTR_DIS_FDONE:
+               msg->id = 0;
+               msg->command = IHC_FRAME_DONE;
+               msg->instance = readl(&com_regs->dis_sensor_id);
+               msg->parameter1 = readl(&com_regs->dis_param1);
+               msg->parameter2 = readl(&com_regs->dis_param2);
+               msg->parameter3 = readl(&com_regs->dis_param3);
+               msg->parameter4 = 0;
+               break;
+       case INTR_SCP_FDONE:
+               msg->id = 0;
+               msg->command = IHC_FRAME_DONE;
+               msg->instance = readl(&com_regs->scp_sensor_id);
+               msg->parameter1 = readl(&com_regs->scp_param1);
+               msg->parameter2 = readl(&com_regs->scp_param2);
+               msg->parameter3 = readl(&com_regs->scp_param3);
+               msg->parameter4 = 0;
+               break;
+       case INTR_SHOT_DONE:
+               msg->id = 0;
+               msg->command = IHC_FRAME_DONE;
+               msg->instance = readl(&com_regs->shot_sensor_id);
+               msg->parameter1 = readl(&com_regs->shot_param1);
+               msg->parameter2 = readl(&com_regs->shot_param2);
+               msg->parameter3 = readl(&com_regs->shot_param3);
+               msg->parameter4 = 0;
+               break;
+       default:
+               msg->id = 0;
+               msg->command = 0;
+               msg->instance = 0;
+               msg->parameter1 = 0;
+               msg->parameter2 = 0;
+               msg->parameter3 = 0;
+               msg->parameter4 = 0;
+               err("unknown command getting\n");
+               break;
+       }
+
+       msg->group = msg->instance >> GROUP_ID_SHIFT;
+       msg->instance = msg->instance & GROUP_ID_MASK;
+}
+
+static inline u32 fimc_is_get_intr(struct fimc_is_interface *itf)
+{
+       u32 status = 0;
+       volatile struct is_common_reg __iomem *com_regs = itf->com_regs;
+
+       if (itf->need_iflag) {
+               status = readl(&com_regs->ihcmd_iflag) |
+                        readl(&com_regs->taa0c_iflag) |
+                        readl(&com_regs->taa1c_iflag) |
+                        readl(&com_regs->scc_iflag) |
+                        readl(&com_regs->dis_iflag) |
+                        readl(&com_regs->scp_iflag) |
+                        readl(&com_regs->shot_iflag);
+       }
+
+       status |= readl(itf->regs + INTMSR1);
+
+       return status;
+}
+
+static inline void fimc_is_clr_intr(struct fimc_is_interface *itf,
+       u32 index)
+{
+       volatile struct is_common_reg __iomem *com_regs = itf->com_regs;
+
+       writel((1 << index), itf->regs + INTCR1);
+
+       if (itf->need_iflag) {
+               switch (index) {
+               case INTR_GENERAL:
+                       writel(0, &com_regs->ihcmd_iflag);
+                       break;
+               case INTR_3A0C_FDONE:
+                       writel(0, &com_regs->taa0c_iflag);
+                       break;
+               case INTR_3A1C_FDONE:
+                       writel(0, &com_regs->taa1c_iflag);
+                       break;
+               case INTR_SCC_FDONE:
+                       writel(0, &com_regs->scc_iflag);
+                       break;
+               case INTR_DIS_FDONE:
+                       writel(0, &com_regs->dis_iflag);
+                       break;
+               case INTR_SCP_FDONE:
+                       writel(0, &com_regs->scp_iflag);
+                       break;
+               case INTR_SHOT_DONE:
+                       writel(0, &com_regs->shot_iflag);
+                       break;
+               default:
+                       err("unknown command clear\n");
+                       break;
+               }
+       }
+}
+
+static void wq_func_general(struct work_struct *data)
+{
+       struct fimc_is_interface *itf;
+       struct fimc_is_msg *msg;
+       struct fimc_is_work *work;
+       struct fimc_is_work *nblk_work;
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_GENERAL]);
+
+       get_req_work(&itf->work_list[INTR_GENERAL], &work);
+       while (work) {
+               msg = &work->msg;
+               switch (msg->command) {
+               case IHC_GET_SENSOR_NUMBER:
+                       info("IS Version: %d.%d [0x%02x]\n",
+                               ISDRV_VERSION, msg->parameter1,
+                               get_drv_clock_gate() |
+                               get_drv_dvfs());
+                       set_bit(IS_IF_STATE_START, &itf->state);
+                       itf->pdown_ready = IS_IF_POWER_DOWN_NREADY;
+                       wake_up(&itf->init_wait_queue);
+                       break;
+               case ISR_DONE:
+                       switch (msg->parameter1) {
+                       case HIC_OPEN_SENSOR:
+                               dbg_interface("open done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_CLOSE_SENSOR:
+                               dbg_interface("close done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_GET_SET_FILE_ADDR:
+                               dbg_interface("saddr(%p) done\n",
+                                       (void *)msg->parameter2);
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_LOAD_SET_FILE:
+                               dbg_interface("setfile done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_SET_A5_MAP:
+                               dbg_interface("mapping done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_SET_A5_UNMAP:
+                               dbg_interface("unmapping done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_PROCESS_START:
+                               dbg_interface("process_on done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_PROCESS_STOP:
+                               dbg_interface("process_off done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_STREAM_ON:
+                               dbg_interface("stream_on done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_STREAM_OFF:
+                               dbg_interface("stream_off done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_SET_PARAMETER:
+                               dbg_interface("s_param done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_GET_STATIC_METADATA:
+                               dbg_interface("g_capability done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_PREVIEW_STILL:
+                               dbg_interface("a_param(%dx%d) done\n",
+                                       msg->parameter2,
+                                       msg->parameter3);
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_POWER_DOWN:
+                               dbg_interface("powerdown done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       case HIC_I2C_CONTROL_LOCK:
+                               dbg_interface("i2c lock done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+#if (FW_HAS_SYS_CTRL_CMD)
+                       case HIC_SYSTEM_CONTROL:
+                               dbg_interface("system control done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+#endif
+#if (FW_HAS_SENSOR_MODE_CMD)
+                       case HIC_SENSOR_MODE_CHANGE:
+                               dbg_interface("sensor mode change done\n");
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+#endif
+                       /*non-blocking command*/
+                       case HIC_SHOT:
+                               err("shot done is not acceptable\n");
+                               break;
+                       case HIC_SET_CAM_CONTROL:
+                               /* this code will be used latter */
+#if 0
+                               dbg_interface("camctrl done\n");
+                               get_req_work(&itf->nblk_cam_ctrl , &nblk_work);
+                               if (nblk_work) {
+                                       nblk_work->msg.command = ISR_DONE;
+                                       set_free_work(&itf->nblk_cam_ctrl,
+                                               nblk_work);
+                               } else {
+                                       err("nblk camctrl request is empty");
+                                       print_fre_work_list(
+                                               &itf->nblk_cam_ctrl);
+                                       print_req_work_list(
+                                               &itf->nblk_cam_ctrl);
+                               }
+#else
+                               err("camctrl is not acceptable\n");
+#endif
+                               break;
+                       default:
+                               err("unknown done is invokded\n");
+                               break;
+                       }
+                       break;
+               case ISR_NDONE:
+                       switch (msg->parameter1) {
+                       case HIC_SHOT:
+                               err("[ITF:%d] shot NDONE is not acceptable",
+                                       msg->instance);
+                               break;
+                       case HIC_SET_CAM_CONTROL:
+                               dbg_interface("camctrl NOT done\n");
+                               get_req_work(&itf->nblk_cam_ctrl , &nblk_work);
+                               nblk_work->msg.command = ISR_NDONE;
+                               set_free_work(&itf->nblk_cam_ctrl, nblk_work);
+                               break;
+                       case HIC_SET_PARAMETER:
+                               err("s_param NOT done");
+                               err("param2 : 0x%08X", msg->parameter2);
+                               err("param3 : 0x%08X", msg->parameter3);
+                               err("param4 : 0x%08X", msg->parameter4);
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       default:
+                               err("a command(%d) not done", msg->parameter1);
+                               memcpy(&itf->reply, msg,
+                                       sizeof(struct fimc_is_msg));
+                               testnclr_wakeup(itf, msg->parameter1);
+                               break;
+                       }
+                       break;
+               case IHC_SET_FACE_MARK:
+                       err("FACE_MARK(%d,%d,%d) is not acceptable\n",
+                               msg->parameter1,
+                               msg->parameter2,
+                               msg->parameter3);
+                       break;
+               case IHC_AA_DONE:
+                       err("AA_DONE(%d,%d,%d) is not acceptable\n",
+                               msg->parameter1,
+                               msg->parameter2,
+                               msg->parameter3);
+                       break;
+               case IHC_FLASH_READY:
+                       err("IHC_FLASH_READY is not acceptable");
+                       break;
+               case IHC_NOT_READY:
+                       err("IHC_NOT_READY is occured, need reset");
+                       fimc_is_hw_logdump(itf);
+                       break;
+#if (FW_HAS_REPORT_ERR_CMD)
+               case IHC_REPORT_ERR:
+                       err("IHC_REPORT_ERR is occured");
+                       fimc_is_err_report_handler(itf, msg);
+                       break;
+#endif
+               default:
+                       err("func_general unknown(0x%08X) end\n", msg->command);
+                       break;
+               }
+
+               set_free_work(&itf->work_list[INTR_GENERAL], work);
+               get_req_work(&itf->work_list[INTR_GENERAL], &work);
+       }
+}
+
+static void wq_func_subdev(struct fimc_is_subdev *leader,
+       struct fimc_is_subdev *subdev,
+       u32 fcount, u32 rcount, u32 status, u32 instance)
+{
+       u32 findex, out_flag;
+       u32 capture_vid, capture_id;
+       char name;
+       unsigned long flags;
+       struct fimc_is_video_ctx *ldr_vctx, *sub_vctx;
+       struct fimc_is_framemgr *ldr_framemgr, *sub_framemgr;
+       struct fimc_is_frame *ldr_frame, *sub_frame;
+       struct camera2_node *capture;
+
+       BUG_ON(!leader);
+       BUG_ON(!subdev);
+
+       ldr_vctx = leader->vctx;
+       if (!ldr_vctx) {
+               err("ldr_vctx is NULL");
+               return;
+       }
+
+       sub_vctx = subdev->vctx;
+       if (!sub_vctx) {
+               err("sub_vctx is NULL");
+               return;
+       }
+
+       if (!sub_vctx->video) {
+               err("video is NULL");
+               return;
+       }
+
+       ldr_framemgr = GET_SRC_FRAMEMGR(ldr_vctx);
+       sub_framemgr = GET_DST_FRAMEMGR(sub_vctx);
+
+       capture_vid = sub_vctx->video->id;
+       switch (capture_vid) {
+       case FIMC_IS_VIDEO_SCC_NUM:
+               out_flag = OUT_SCC_FRAME;
+               name = 'C';
+               break;
+       case FIMC_IS_VIDEO_VDC_NUM:
+               out_flag = OUT_DIS_FRAME;
+               name = 'D';
+               break;
+       case FIMC_IS_VIDEO_SCP_NUM:
+               out_flag = OUT_SCP_FRAME;
+               name = 'P';
+               break;
+       case FIMC_IS_VIDEO_3A0C_NUM:
+               out_flag = OUT_3AAC_FRAME;
+               name = '0';
+               break;
+       case FIMC_IS_VIDEO_3A1C_NUM:
+               out_flag = OUT_3AAC_FRAME;
+               name = '1';
+               break;
+       default:
+               err("video node is invalid(%d)", sub_vctx->video->id);
+               return;
+       }
+
+       framemgr_e_barrier_irqs(sub_framemgr, 0, flags);
+
+       fimc_is_frame_process_head(sub_framemgr, &sub_frame);
+       if (sub_frame && test_bit(REQ_FRAME, &sub_frame->req_flag)) {
+
+#ifdef DBG_STREAMING
+               info("[%c:D:%d] %d(%d,%d)\n", name, instance,
+                       sub_frame->index, fcount, rcount);
+#endif
+
+               if (!sub_frame->stream) {
+                       err("stream is NULL, critical error");
+                       goto p_err;
+               }
+
+               findex = sub_frame->stream->findex;
+               if (findex >= ldr_vctx->q_src->buf_maxcount) {
+                       err("findex(%d) is invalid(max : %d)",
+                               findex, ldr_vctx->q_src->buf_maxcount);
+                       sub_frame->stream->fvalid = 0;
+                       goto done;
+               }
+
+               ldr_frame = &ldr_framemgr->frame[findex];
+               if (status) {
+                       info("[%c:D:%d] FRM%d NOT DONE(%d)\n", name,
+                               instance, fcount, status);
+                       sub_frame->stream->fvalid = 0;
+                       clear_bit(out_flag, &ldr_frame->out_flag);
+                       goto done;
+               }
+
+               if (ldr_frame->fcount != fcount) {
+                       err("%c frame mismatched(ldr%d, sub%d)", name,
+                               ldr_frame->fcount, fcount);
+                       sub_frame->stream->fvalid = 0;
+               } else {
+                       sub_frame->stream->fvalid = 1;
+                       clear_bit(out_flag, &ldr_frame->out_flag);
+               }
+
+               for (capture_id = 0; capture_id < CAPTURE_NODE_MAX; ++capture_id) {
+                       capture = &ldr_frame->shot_ext->node_group.capture[capture_id];
+                       if (capture_vid == capture->vid) {
+                               sub_frame->stream->output_crop_region[0] = capture->output.cropRegion[0];
+                               sub_frame->stream->output_crop_region[1] = capture->output.cropRegion[1];
+                               sub_frame->stream->output_crop_region[2] = capture->output.cropRegion[2];
+                               sub_frame->stream->output_crop_region[3] = capture->output.cropRegion[3];
+
+                               sub_frame->stream->input_crop_region[0] = capture->input.cropRegion[0];
+                               sub_frame->stream->input_crop_region[1] = capture->input.cropRegion[1];
+                               sub_frame->stream->input_crop_region[2] = capture->input.cropRegion[2];
+                               sub_frame->stream->input_crop_region[3] = capture->input.cropRegion[3];
+                               break;
+                       }
+               }
+
+               if (capture_id >= CAPTURE_NODE_MAX) {
+                       err("can't find capture stream(%d > %d)", capture_id, CAPTURE_NODE_MAX);
+                       sub_frame->stream->output_crop_region[0] = 0;
+                       sub_frame->stream->output_crop_region[1] = 0;
+                       sub_frame->stream->output_crop_region[2] = 0;
+                       sub_frame->stream->output_crop_region[3] = 0;
+               }
+
+done:
+               clear_bit(REQ_FRAME, &sub_frame->req_flag);
+               sub_frame->stream->fcount = fcount;
+               sub_frame->stream->rcount = rcount;
+
+               fimc_is_frame_trans_pro_to_com(sub_framemgr, sub_frame);
+               buffer_done(sub_vctx, sub_frame->index);
+       } else
+               err("done(%p) is occured without request", sub_frame);
+
+p_err:
+       framemgr_x_barrier_irqr(sub_framemgr, 0, flags);
+}
+
+static void wq_func_3a0c(struct work_struct *data)
+{
+       u32 instance, fcount, rcount, status;
+       struct fimc_is_interface *itf;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader, *subdev;
+       struct fimc_is_work *work;
+       struct fimc_is_msg *msg;
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_3A0C_FDONE]);
+
+       get_req_work(&itf->work_list[INTR_3A0C_FDONE], &work);
+       while (work) {
+               msg = &work->msg;
+               instance = msg->instance;
+               fcount = msg->parameter1;
+               status = msg->parameter2;
+               rcount = msg->parameter3;
+
+               if (instance >= FIMC_IS_MAX_NODES) {
+                       err("instance is invalid(%d)", instance);
+                       goto p_err;
+               }
+
+               device = &((struct fimc_is_core *)itf->core)->ischain[instance];
+               if (!device) {
+                       err("device is NULL");
+                       goto p_err;
+               }
+
+               subdev = &device->taac;
+               leader = subdev->leader;
+
+               wq_func_subdev(leader, subdev, fcount, rcount, status, instance);
+
+p_err:
+               set_free_work(&itf->work_list[INTR_3A0C_FDONE], work);
+               get_req_work(&itf->work_list[INTR_3A0C_FDONE], &work);
+       }
+}
+
+static void wq_func_3a1c(struct work_struct *data)
+{
+       u32 instance, fcount, rcount, status;
+       struct fimc_is_interface *itf;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader, *subdev;
+       struct fimc_is_work *work;
+       struct fimc_is_msg *msg;
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_3A1C_FDONE]);
+
+       get_req_work(&itf->work_list[INTR_3A1C_FDONE], &work);
+       while (work) {
+               msg = &work->msg;
+               instance = msg->instance;
+               fcount = msg->parameter1;
+               status = msg->parameter2;
+               rcount = msg->parameter3;
+
+               if (instance >= FIMC_IS_MAX_NODES) {
+                       err("instance is invalid(%d)", instance);
+                       goto p_err;
+               }
+
+               device = &((struct fimc_is_core *)itf->core)->ischain[instance];
+               if (!device) {
+                       err("device is NULL");
+                       goto p_err;
+               }
+
+               subdev = &device->taac;
+               leader = subdev->leader;
+
+               wq_func_subdev(leader, subdev, fcount, rcount, status, instance);
+
+p_err:
+               set_free_work(&itf->work_list[INTR_3A1C_FDONE], work);
+               get_req_work(&itf->work_list[INTR_3A1C_FDONE], &work);
+       }
+}
+
+static void wq_func_scc(struct work_struct *data)
+{
+       u32 instance, fcount, rcount, status;
+       struct fimc_is_interface *itf;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader, *subdev;
+       struct fimc_is_work *work;
+       struct fimc_is_msg *msg;
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_SCC_FDONE]);
+
+       get_req_work(&itf->work_list[INTR_SCC_FDONE], &work);
+       while (work) {
+               msg = &work->msg;
+               instance = msg->instance;
+               fcount = msg->parameter1;
+               status = msg->parameter2;
+               rcount = msg->parameter3;
+
+               if (instance >= FIMC_IS_MAX_NODES) {
+                       err("instance is invalid(%d)", instance);
+                       goto p_err;
+               }
+
+               device = &((struct fimc_is_core *)itf->core)->ischain[instance];
+               if (!device) {
+                       err("device is NULL");
+                       goto p_err;
+               }
+
+               subdev = &device->scc;
+               leader = subdev->leader;
+
+               wq_func_subdev(leader, subdev, fcount, rcount, status, instance);
+
+p_err:
+               set_free_work(&itf->work_list[INTR_SCC_FDONE], work);
+               get_req_work(&itf->work_list[INTR_SCC_FDONE], &work);
+       }
+}
+
+static void wq_func_dis(struct work_struct *data)
+{
+       u32 instance, fcount, rcount, status;
+       struct fimc_is_interface *itf;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader, *subdev;
+       struct fimc_is_work *work;
+       struct fimc_is_msg *msg;
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_DIS_FDONE]);
+
+       get_req_work(&itf->work_list[INTR_DIS_FDONE], &work);
+       while (work) {
+               msg = &work->msg;
+               instance = msg->instance;
+               fcount = msg->parameter1;
+               status = msg->parameter2;
+               rcount = msg->parameter3;
+
+               if (instance >= FIMC_IS_MAX_NODES) {
+                       err("instance is invalid(%d)", instance);
+                       goto p_err;
+               }
+
+               device = &((struct fimc_is_core *)itf->core)->ischain[instance];
+               if (!device) {
+                       err("device is NULL");
+                       goto p_err;
+               }
+
+               subdev = &device->dis;
+               leader = subdev->leader;
+
+               wq_func_subdev(leader, subdev, fcount, rcount, status, instance);
+
+p_err:
+               set_free_work(&itf->work_list[INTR_DIS_FDONE], work);
+               get_req_work(&itf->work_list[INTR_DIS_FDONE], &work);
+       }
+}
+
+static void wq_func_scp(struct work_struct *data)
+{
+       u32 instance, fcount, rcount, status;
+       struct fimc_is_interface *itf;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader, *subdev;
+       struct fimc_is_work *work;
+       struct fimc_is_msg *msg;
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_SCP_FDONE]);
+
+       get_req_work(&itf->work_list[INTR_SCP_FDONE], &work);
+       while (work) {
+               msg = &work->msg;
+               instance = msg->instance;
+               fcount = msg->parameter1;
+               status = msg->parameter2;
+               rcount = msg->parameter3;
+
+               if (instance >= FIMC_IS_MAX_NODES) {
+                       err("instance is invalid(%d)", instance);
+                       goto p_err;
+               }
+
+               device = &((struct fimc_is_core *)itf->core)->ischain[instance];
+               if (!device) {
+                       err("device is NULL");
+                       goto p_err;
+               }
+
+               subdev = &device->scp;
+               leader = subdev->leader;
+
+               wq_func_subdev(leader, subdev, fcount, rcount, status, instance);
+
+p_err:
+               set_free_work(&itf->work_list[INTR_SCP_FDONE], work);
+               get_req_work(&itf->work_list[INTR_SCP_FDONE], &work);
+       }
+}
+
+static void wq_func_group_3a0(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_framemgr *ldr_framemgr,
+       struct fimc_is_frame *ldr_frame,
+       struct fimc_is_framemgr *sub_framemgr,
+       struct fimc_is_video_ctx *vctx,
+       u32 status)
+{
+       u32 done_state = VB2_BUF_STATE_DONE;
+       unsigned long flags;
+       struct fimc_is_queue *src_queue, *dst_queue;
+       struct fimc_is_frame *sub_frame;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ldr_framemgr);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!sub_framemgr);
+
+       if (status != ISR_DONE) {
+               info("[3A0:D:%d] GRP0 NOT DONE(%d, %d)\n", group->instance,
+                       ldr_frame->fcount, ldr_frame->index);
+               done_state = VB2_BUF_STATE_ERROR;
+       } else if ((group->device->taa_size_forceset) &&
+                          (ldr_frame->fcount >= group->device->taa_size_changed_fcount)) {
+               /* Acknowledge the group size change settings */
+               group->device->taa_size_forceset = 0;
+               group->device->taa_size_changed_fcount = 0;
+       }
+
+#ifdef DBG_STREAMING
+       if (status == ISR_DONE)
+               info("[3A0:D:%d] GRP0 DONE(%d)\n", group->instance,
+                       ldr_frame->fcount);
+#endif
+
+       src_queue = GET_SRC_QUEUE(vctx);
+       dst_queue = GET_DST_QUEUE(vctx);
+
+       /* 1. sub frame done */
+       framemgr_e_barrier_irqs(sub_framemgr, 0, flags);
+
+       fimc_is_frame_process_head(sub_framemgr, &sub_frame);
+       if (sub_frame && test_bit(REQ_FRAME, &sub_frame->req_flag)) {
+               clear_bit(REQ_FRAME, &sub_frame->req_flag);
+
+               sub_frame->stream->fvalid = 1;
+               sub_frame->stream->fcount = ldr_frame->fcount;
+               sub_frame->stream->rcount = ldr_frame->rcount;
+
+               fimc_is_frame_trans_pro_to_com(sub_framemgr, sub_frame);
+               queue_done(vctx, dst_queue, sub_frame->index, done_state);
+       } else
+               err("done is occured without request(%p, %d)", sub_frame, ldr_frame->fcount);
+
+       framemgr_x_barrier_irqr(sub_framemgr, 0, flags);
+
+       /* 2. leader frame done */
+       fimc_is_ischain_meta_invalid(ldr_frame);
+
+       fimc_is_frame_trans_pro_to_com(ldr_framemgr, ldr_frame);
+       fimc_is_group_done(groupmgr, group, ldr_frame, done_state);
+       queue_done(vctx, src_queue, ldr_frame->index, done_state);
+}
+
+static void wq_func_group_3a1(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_framemgr *ldr_framemgr,
+       struct fimc_is_frame *ldr_frame,
+       struct fimc_is_framemgr *sub_framemgr,
+       struct fimc_is_video_ctx *vctx,
+       u32 status)
+{
+       u32 done_state = VB2_BUF_STATE_DONE;
+       unsigned long flags;
+       struct fimc_is_queue *src_queue, *dst_queue;
+       struct fimc_is_frame *sub_frame;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ldr_framemgr);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!sub_framemgr);
+
+       if (status != ISR_DONE) {
+               info("[3A1:D:%d] GRP1 NOT DONE(%d, %d)\n", group->instance,
+                       ldr_frame->fcount, ldr_frame->index);
+               done_state = VB2_BUF_STATE_ERROR;
+       } else if ((group->device->taa_size_forceset) &&
+                          (ldr_frame->fcount >= group->device->taa_size_changed_fcount)) {
+               /* Acknowledge the group size change settings */
+               group->device->taa_size_forceset = 0;
+               group->device->taa_size_changed_fcount = 0;
+       }
+
+#ifdef DBG_STREAMING
+       if (status == ISR_DONE)
+               info("[3A1:D:%d] GRP1 DONE(%d)\n", group->instance,
+                       ldr_frame->fcount);
+#endif
+
+       src_queue = GET_SRC_QUEUE(vctx);
+       dst_queue = GET_DST_QUEUE(vctx);
+
+       /* 1. sub frame done */
+       framemgr_e_barrier_irqs(sub_framemgr, 0, flags);
+
+       fimc_is_frame_process_head(sub_framemgr, &sub_frame);
+       if (sub_frame && test_bit(REQ_FRAME, &sub_frame->req_flag)) {
+               clear_bit(REQ_FRAME, &sub_frame->req_flag);
+
+               sub_frame->stream->fvalid = 1;
+               sub_frame->stream->fcount = ldr_frame->fcount;
+               sub_frame->stream->rcount = ldr_frame->rcount;
+
+               fimc_is_frame_trans_pro_to_com(sub_framemgr, sub_frame);
+               queue_done(vctx, dst_queue, sub_frame->index, done_state);
+       } else
+               err("done is occured without request(%p)", sub_frame);
+
+       framemgr_x_barrier_irqr(sub_framemgr, 0, flags);
+
+       /* 2. leader frame done */
+       fimc_is_ischain_meta_invalid(ldr_frame);
+
+       fimc_is_frame_trans_pro_to_com(ldr_framemgr, ldr_frame);
+       fimc_is_group_done(groupmgr, group, ldr_frame, done_state);
+       queue_done(vctx, src_queue, ldr_frame->index, done_state);
+}
+
+static void wq_func_group_isp(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_framemgr *framemgr,
+       struct fimc_is_frame *frame,
+       struct fimc_is_video_ctx *vctx,
+       u32 status)
+{
+       u32 done_state = VB2_BUF_STATE_DONE;
+       struct fimc_is_queue *queue;
+#ifdef ENABLE_SENSOR_DRIVER
+       struct camera2_lens_uctl *isp_lens_uctl;
+       struct camera2_lens_uctl *lens_uctl;
+       struct camera2_sensor_uctl *isp_sensor_uctl;
+       struct camera2_sensor_uctl *sensor_uctl;
+       struct camera2_flash_uctl *isp_flash_uctl;
+       struct camera2_flash_uctl *flash_uctl;
+#endif
+
+       BUG_ON(!framemgr);
+       BUG_ON(!frame);
+
+       if (status != ISR_DONE) {
+               info("[ISP:D:%d] GRP2 NOT DONE(%d, %d)\n", group->instance,
+                       frame->fcount, frame->index);
+               done_state = VB2_BUF_STATE_ERROR;
+       } else if ((group->device->isp_size_forceset) &&
+                          (frame->fcount >= group->device->isp_size_changed_fcount)) {
+               /* Acknowledge the group size change settings */
+               group->device->isp_size_forceset = 0;
+               group->device->isp_size_changed_fcount = 0;
+       }
+
+#ifdef DBG_STREAMING
+       if (status == ISR_DONE)
+               info("[ISP:D:%d] GRP2 DONE(%d)\n", group->instance,
+                       frame->fcount);
+#endif
+
+       queue = GET_SRC_QUEUE(vctx);
+
+       /* Cache Invalidation */
+       fimc_is_ischain_meta_invalid(frame);
+
+#ifdef ENABLE_SENSOR_DRIVER
+       isp_lens_uctl = &itf->isp_peri_ctl.lensUd;
+       isp_sensor_uctl = &itf->isp_peri_ctl.sensorUd;
+       isp_flash_uctl = &itf->isp_peri_ctl.flashUd;
+
+       if (frame->shot->uctl.uUpdateBitMap & CAM_SENSOR_CMD) {
+               sensor_uctl = &frame->shot->uctl.sensorUd;
+               isp_sensor_uctl->ctl.exposureTime =
+                       sensor_uctl->ctl.exposureTime;
+               isp_sensor_uctl->ctl.frameDuration =
+                       sensor_uctl->ctl.frameDuration;
+               isp_sensor_uctl->ctl.sensitivity =
+                       sensor_uctl->ctl.sensitivity;
+
+               frame->shot->uctl.uUpdateBitMap &=
+                       ~CAM_SENSOR_CMD;
+       }
+
+       if (frame->shot->uctl.uUpdateBitMap & CAM_LENS_CMD) {
+               lens_uctl = &frame->shot->uctl.lensUd;
+               isp_lens_uctl->ctl.focusDistance =
+                       lens_uctl->ctl.focusDistance;
+               isp_lens_uctl->maxPos =
+                       lens_uctl->maxPos;
+               isp_lens_uctl->slewRate =
+                       lens_uctl->slewRate;
+
+               frame->shot->uctl.uUpdateBitMap &=
+                       ~CAM_LENS_CMD;
+       }
+
+       if (frame->shot->uctl.uUpdateBitMap & CAM_FLASH_CMD) {
+               flash_uctl = &frame->shot->uctl.flashUd;
+               isp_flash_uctl->ctl.flashMode =
+                       flash_uctl->ctl.flashMode;
+               isp_flash_uctl->ctl.firingPower =
+                       flash_uctl->ctl.firingPower;
+               isp_flash_uctl->ctl.firingTime =
+                       flash_uctl->ctl.firingTime;
+
+               frame->shot->uctl.uUpdateBitMap &=
+                       ~CAM_FLASH_CMD;
+       }
+#endif
+
+       fimc_is_frame_trans_pro_to_com(framemgr, frame);
+       fimc_is_group_done(groupmgr, group, frame, done_state);
+       queue_done(vctx, queue, frame->index, done_state);
+}
+
+static void wq_func_group_dis(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_framemgr *framemgr,
+       struct fimc_is_frame *frame,
+       struct fimc_is_video_ctx *vctx,
+       u32 status)
+{
+       u32 done_state = VB2_BUF_STATE_DONE;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!framemgr);
+       BUG_ON(!frame);
+
+       if (status != ISR_DONE) {
+               info("[DIS:D:%d] GRP3 NOT DONE(%d, %d)\n", group->instance,
+                       frame->fcount, frame->index);
+               done_state = VB2_BUF_STATE_ERROR;
+       }
+
+#ifdef DBG_STREAMING
+       if (status == ISR_DONE)
+               info("[DIS:D:%d] GRP3 DONE(%d)\n", group->instance,
+                       frame->fcount);
+#endif
+
+       queue = GET_SRC_QUEUE(vctx);
+
+       /* Cache Invalidation */
+       fimc_is_ischain_meta_invalid(frame);
+
+       fimc_is_frame_trans_pro_to_com(framemgr, frame);
+       fimc_is_group_done(groupmgr, group, frame, done_state);
+       queue_done(vctx, queue, frame->index, done_state);
+}
+
+void wq_func_group(struct fimc_is_groupmgr *groupmgr,
+       struct fimc_is_group *group,
+       struct fimc_is_framemgr *ldr_framemgr,
+       struct fimc_is_frame *ldr_frame,
+       struct fimc_is_video_ctx *vctx,
+       u32 status1, u32 status2, u32 fcount)
+{
+       u32 lindex, hindex;
+       struct fimc_is_framemgr *sub_framemgr;
+
+       BUG_ON(!groupmgr);
+       BUG_ON(!group);
+       BUG_ON(!ldr_framemgr);
+       BUG_ON(!ldr_frame);
+       BUG_ON(!vctx);
+
+       /*
+        * complete count should be lower than 3 when
+        * buffer is queued or overflow can be occured
+        */
+       if (ldr_framemgr->frame_com_cnt >= 2)
+               warn("remained completes is %d(%X)", (ldr_framemgr->frame_com_cnt + 1), group->id);
+
+       if (status2 != IS_SHOT_SUCCESS) {
+               lindex = ldr_frame->shot->ctl.entry.lowIndexParam;
+               lindex &= ~ldr_frame->shot->dm.entry.lowIndexParam;
+               hindex = ldr_frame->shot->ctl.entry.highIndexParam;
+               hindex &= ~ldr_frame->shot->dm.entry.highIndexParam;
+               if (lindex || hindex)
+                       err("cause : %d : invalid parameter(%08X %08X)", status2, lindex, hindex);
+               else
+                       err("cause : %d", status2);
+       }
+
+       switch (group->id) {
+       case GROUP_ID_3A0:
+               sub_framemgr = GET_DST_FRAMEMGR(vctx);
+
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+                       /*
+                        * When OTF is enabled, 3A0 can have 2 more shots
+                        * done is reported to hal if frame count is same
+                        * not done is reported to hal if driver frame count is
+                        * less than firmware frame count
+                        * this correction is repeated
+                        */
+                       if (fcount != ldr_frame->fcount) {
+                               while (ldr_frame) {
+                                       if (fcount == ldr_frame->fcount) {
+                                               status1 = ISR_NDONE;
+                                               wq_func_group_3a0(groupmgr, group,
+                                                       ldr_framemgr, ldr_frame,
+                                                       sub_framemgr, vctx, status1);
+                                               break;
+                                       } else if (fcount > ldr_frame->fcount) {
+                                               err("cause: mismatch(%d != %d)",
+                                                       fcount,
+                                                       ldr_frame->fcount);
+                                               status1 = ISR_NDONE;
+                                               wq_func_group_3a0(groupmgr, group,
+                                                       ldr_framemgr, ldr_frame,
+                                                       sub_framemgr, vctx, status1);
+
+                                               /* get next leader frame */
+                                               fimc_is_frame_process_head(ldr_framemgr,
+                                                       &ldr_frame);
+                                       } else {
+                                               warn("%d done is ignored", fcount);
+                                               break;
+                                       }
+                               }
+                       } else {
+                               wq_func_group_3a0(groupmgr, group,
+                                       ldr_framemgr, ldr_frame,
+                                       sub_framemgr, vctx, status1);
+                       }
+               } else {
+                       if (fcount != ldr_frame->fcount) {
+                               err("cause : mismatch(%d != %d)", fcount, ldr_frame->fcount);
+                               status1 = ISR_NDONE;
+                       }
+
+                       wq_func_group_3a0(groupmgr, group, ldr_framemgr, ldr_frame,
+                               sub_framemgr, vctx, status1);
+               }
+               break;
+       case GROUP_ID_3A1:
+               sub_framemgr = GET_DST_FRAMEMGR(vctx);
+
+               if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) {
+                       /*
+                        * When OTF is enabled, 3A1 can have 2 more shots
+                        * done is reported to hal if frame count is same
+                        * not done is reported to hal if driver frame count is
+                        * less than firmware frame count
+                        * this correction is repeated
+                        */
+                       if (fcount != ldr_frame->fcount) {
+
+                               while (ldr_frame) {
+                                       if (fcount == ldr_frame->fcount) {
+                                               status1 = ISR_NDONE;
+                                               wq_func_group_3a1(groupmgr, group,
+                                                       ldr_framemgr, ldr_frame,
+                                                       sub_framemgr, vctx, status1);
+                                               break;
+                                       } else if (fcount > ldr_frame->fcount) {
+                                               err("cause : mismatch(%d != %d)", fcount,
+                                                       ldr_frame->fcount);
+                                               status1 = ISR_NDONE;
+                                               wq_func_group_3a1(groupmgr, group,
+                                                       ldr_framemgr, ldr_frame,
+                                                       sub_framemgr, vctx, status1);
+
+                                               /* get next leader frame */
+                                               fimc_is_frame_process_head(ldr_framemgr,
+                                                       &ldr_frame);
+                                       } else {
+                                               warn("%d done is ignored", fcount);
+                                               break;
+                                       }
+                               }
+                       } else {
+                               wq_func_group_3a1(groupmgr, group,
+                                       ldr_framemgr, ldr_frame,
+                                       sub_framemgr, vctx, status1);
+                       }
+               } else {
+                       if (fcount != ldr_frame->fcount) {
+                               err("cause : mismatch(%d != %d)", fcount, ldr_frame->fcount);
+                               status1 = ISR_NDONE;
+                       }
+
+                       wq_func_group_3a1(groupmgr, group, ldr_framemgr, ldr_frame,
+                               sub_framemgr, vctx, status1);
+
+               }
+               break;
+       case GROUP_ID_ISP:
+               if (fcount != ldr_frame->fcount) {
+                       err("cause : mismatch(%d != %d)", fcount,
+                               ldr_frame->fcount);
+                       status1 = ISR_NDONE;
+               }
+
+               wq_func_group_isp(groupmgr, group, ldr_framemgr, ldr_frame,
+                       vctx, status1);
+               break;
+       case GROUP_ID_DIS:
+               if (fcount != ldr_frame->fcount) {
+                       err("cause : mismatch(%d != %d)", fcount,
+                               ldr_frame->fcount);
+                       status1 = ISR_NDONE;
+               }
+
+               wq_func_group_dis(groupmgr, group, ldr_framemgr, ldr_frame,
+                       vctx, status1);
+               break;
+       default:
+               err("unresolved group id %d", group->id);
+               break;
+       }
+}
+
+static void wq_func_shot(struct work_struct *data)
+{
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_interface *itf;
+       struct fimc_is_msg *msg;
+       struct fimc_is_framemgr *grp_framemgr;
+       struct fimc_is_frame *frame;
+       struct fimc_is_groupmgr *groupmgr;
+       struct fimc_is_group *group;
+       struct fimc_is_work_list *work_list;
+       struct fimc_is_work *work;
+       struct fimc_is_video_ctx *vctx;
+       unsigned long flags;
+       u32 req_flag;
+       u32 fcount;
+       u32 status1, status2;
+       int instance;
+       int group_id;
+       struct fimc_is_core *core;
+
+       BUG_ON(!data);
+
+       itf = container_of(data, struct fimc_is_interface,
+               work_wq[INTR_SHOT_DONE]);
+       work_list = &itf->work_list[INTR_SHOT_DONE];
+       group  = NULL;
+       vctx = NULL;
+       grp_framemgr = NULL;
+
+       get_req_work(work_list, &work);
+       while (work) {
+               core = (struct fimc_is_core *)itf->core;
+               instance = work->msg.instance;
+               group_id = work->msg.group;
+               device = &((struct fimc_is_core *)itf->core)->ischain[instance];
+               groupmgr = device->groupmgr;
+
+               msg = &work->msg;
+               fcount = msg->parameter1;
+               status1 = msg->parameter2;
+               status2 = msg->parameter3;
+
+               switch (group_id) {
+               case GROUP_ID(GROUP_ID_3A0):
+                       /* if there's no entry to 3a1 */
+                       if (GET_FIMC_IS_NUM_OF_SUBIP(core, 3a0)) {
+                               req_flag = REQ_3AA_SHOT;
+                               group = &device->group_3aa;
+                       } else {
+                               req_flag = REQ_ISP_SHOT;
+                               group = &device->group_isp;
+                       }
+                       break;
+               case GROUP_ID(GROUP_ID_3A1):
+                       req_flag = REQ_3AA_SHOT;
+                       group = &device->group_3aa;
+                       break;
+               case GROUP_ID(GROUP_ID_ISP):
+                       req_flag = REQ_ISP_SHOT;
+                       group = &device->group_isp;
+                       break;
+               case GROUP_ID(GROUP_ID_DIS):
+                       req_flag = REQ_DIS_SHOT;
+                       group = &device->group_dis;
+                       break;
+               default:
+                       merr("unresolved group id %d", device, group_id);
+                       group = NULL;
+                       vctx = NULL;
+                       grp_framemgr = NULL;
+                       goto remain;
+               }
+
+               if (!group) {
+                       merr("group is NULL", device);
+                       goto remain;
+               }
+
+               vctx = group->leader.vctx;
+               if (!vctx) {
+                       merr("vctx is NULL", device);
+                       goto remain;
+               }
+
+               grp_framemgr = GET_SRC_FRAMEMGR(vctx);
+               if (!grp_framemgr) {
+                       merr("grp_framemgr is NULL", device);
+                       goto remain;
+               }
+
+               framemgr_e_barrier_irqs(grp_framemgr, FMGR_IDX_7, flags);
+
+               fimc_is_frame_process_head(grp_framemgr, &frame);
+
+               if (frame) {
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+                       do_gettimeofday(&frame->time_shotdone);
+#endif
+#ifdef EXTERNAL_TIME
+                       do_gettimeofday(&frame->tzone[TM_SHOT_D]);
+#endif
+#endif
+
+                       clear_bit(req_flag, &frame->req_flag);
+                       if (frame->req_flag)
+                               merr("group(%d) req flag is not clear all(%X)",
+                                       device, group->id, (u32)frame->req_flag);
+
+#ifdef ENABLE_CLOCK_GATE
+                       /* dynamic clock off */
+                       if (sysfs_debug.en_clk_gate &&
+                                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+                               fimc_is_clk_gate_set(core, group->id, false, false, true);
+#endif
+                       wq_func_group(groupmgr, group, grp_framemgr, frame,
+                               vctx, status1, status2, fcount);
+               } else {
+                       merr("GRP%d DONE(%d) is occured without request",
+                               device, group->id, fcount);
+                       fimc_is_frame_print_all(grp_framemgr);
+               }
+
+               framemgr_x_barrier_irqr(grp_framemgr, FMGR_IDX_7, flags);
+#ifdef ENABLE_CLOCK_GATE
+               if (fcount == 1 &&
+                               sysfs_debug.en_clk_gate &&
+                               sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+                       fimc_is_clk_gate_lock_set(core, instance, false);
+#endif
+remain:
+               set_free_work(work_list, work);
+               get_req_work(work_list, &work);
+       }
+}
+
+static inline void wq_func_schedule(struct fimc_is_interface *itf,
+       struct work_struct *work_wq)
+{
+       if (itf->workqueue)
+               queue_work(itf->workqueue, work_wq);
+       else
+               schedule_work(work_wq);
+}
+
+static void interface_timer(unsigned long data)
+{
+       u32 shot_count, scount_3ax, scount_isp;
+       u32 fcount, i;
+       unsigned long flags;
+       struct fimc_is_interface *itf = (struct fimc_is_interface *)data;
+       struct fimc_is_core *core;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_device_sensor *sensor;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_work_list *work_list;
+       struct work_struct *work_wq;
+
+       BUG_ON(!itf);
+       BUG_ON(!itf->core);
+
+       if (!test_bit(IS_IF_STATE_OPEN, &itf->state)) {
+               pr_info("shot timer is terminated\n");
+               return;
+       }
+
+       core = itf->core;
+
+       for (i = 0; i < FIMC_IS_MAX_NODES; ++i) {
+               device = &core->ischain[i];
+               shot_count = 0;
+               scount_3ax = 0;
+               scount_isp = 0;
+
+               sensor = device->sensor;
+               if (!sensor)
+                       continue;
+
+               if (!test_bit(FIMC_IS_SENSOR_FRONT_START, &sensor->state))
+                       continue;
+
+               if (test_bit(FIMC_IS_ISCHAIN_OPEN_SENSOR, &device->state)) {
+                       spin_lock_irq(&itf->shot_check_lock);
+                       if (atomic_read(&itf->shot_check[i])) {
+                               atomic_set(&itf->shot_check[i], 0);
+                               atomic_set(&itf->shot_timeout[i], 0);
+                               spin_unlock_irq(&itf->shot_check_lock);
+                               continue;
+                       }
+                       spin_unlock_irq(&itf->shot_check_lock);
+
+                       if (test_bit(FIMC_IS_GROUP_READY, &device->group_3aa.state)) {
+                               framemgr = GET_GROUP_FRAMEMGR(&device->group_3aa);
+                               framemgr_e_barrier_irqs(framemgr, 0, flags);
+                               scount_3ax = framemgr->frame_pro_cnt;
+                               shot_count += scount_3ax;
+                               framemgr_x_barrier_irqr(framemgr, 0, flags);
+                       }
+
+                       if (test_bit(FIMC_IS_GROUP_READY, &device->group_isp.state)) {
+                               framemgr = GET_GROUP_FRAMEMGR(&device->group_isp);
+                               framemgr_e_barrier_irqs(framemgr, 0, flags);
+                               scount_isp = framemgr->frame_pro_cnt;
+                               shot_count += scount_isp;
+                               framemgr_x_barrier_irqr(framemgr, 0, flags);
+                       }
+
+                       if (test_bit(FIMC_IS_GROUP_READY, &device->group_dis.state)) {
+                               framemgr = GET_GROUP_FRAMEMGR(&device->group_dis);
+                               framemgr_e_barrier_irqs(framemgr, 0, flags);
+                               shot_count += framemgr->frame_pro_cnt;
+                               framemgr_x_barrier_irqr(framemgr, 0, flags);
+                       }
+               }
+
+               if (shot_count) {
+                       atomic_inc(&itf->shot_timeout[i]);
+                       pr_err ("shot timer[%d] is increased to %d\n", i,
+                               atomic_read(&itf->shot_timeout[i]));
+               }
+
+               if (atomic_read(&itf->shot_timeout[i]) > TRY_TIMEOUT_COUNT) {
+                       merr("shot command is timeout(%d, %d(%d+%d))", device,
+                               atomic_read(&itf->shot_timeout[i]),
+                               shot_count, scount_3ax, scount_isp);
+
+                       pr_err("\n### 3ax framemgr info ###\n");
+                       if (scount_3ax) {
+                               framemgr = GET_GROUP_FRAMEMGR(&device->group_3aa);
+                               fimc_is_frame_print_all(framemgr);
+                       }
+
+                       pr_err("\n### isp framemgr info ###\n");
+                       if (scount_isp) {
+                               framemgr = GET_GROUP_FRAMEMGR(&device->group_isp);
+                               fimc_is_frame_print_all(framemgr);
+                       }
+
+                       pr_err("\n### work list info ###\n");
+                       work_list = &itf->work_list[INTR_SHOT_DONE];
+                       print_fre_work_list(work_list);
+                       print_req_work_list(work_list);
+
+                       if (work_list->work_request_cnt > 0) {
+                               pr_err("\n### processing work lately ###\n");
+                               work_wq = &itf->work_wq[INTR_SHOT_DONE];
+                               wq_func_shot(work_wq);
+
+                               atomic_set(&itf->shot_check[i], 0);
+                               atomic_set(&itf->shot_timeout[i], 0);
+                       } else {
+                               fimc_is_hw_logdump(itf);
+                               fimc_is_hw_regdump(itf);
+
+                               if (itf->need_iflag &&
+                                       readl(&itf->com_regs->shot_iflag)) {
+                                       pr_err("\n### MCUCTL check ###\n");
+                                       fimc_is_clr_intr(itf, INTR_SHOT_DONE);
+                                       fimc_is_hw_regdump(itf);
+                               }
+#ifdef BUG_ON_ENABLE
+                               BUG();
+#endif
+                               return;
+                       }
+               }
+       }
+
+       for (i = 0; i < FIMC_IS_MAX_NODES; ++i) {
+               sensor = &core->sensor[i];
+
+               if (!test_bit(FIMC_IS_SENSOR_FRONT_START, &sensor->state))
+                       continue;
+
+               fcount = fimc_is_sensor_g_fcount(sensor);
+               if (fcount == atomic_read(&itf->sensor_check[i])) {
+                       atomic_inc(&itf->sensor_timeout[i]);
+                       pr_err ("sensor timer[%d] is increased to %d(fcount : %d)\n", i,
+                               atomic_read(&itf->sensor_timeout[i]), fcount);
+               } else {
+                       atomic_set(&itf->sensor_timeout[i], 0);
+                       atomic_set(&itf->sensor_check[i], fcount);
+               }
+
+               if (atomic_read(&itf->sensor_timeout[i]) > SENSOR_TIMEOUT_COUNT) {
+                       merr("sensor is timeout(%d, %d)", sensor,
+                               atomic_read(&itf->sensor_timeout[i]),
+                               atomic_read(&itf->sensor_check[i]));
+
+                       /* print sensor clk , pwr state */
+                       CALL_POPS(core, print_clk, device->pdev);
+                       CALL_POPS(core, print_pwr, device->pdev);
+
+                       /* print sensor info */
+                       merr("sensor fcount : %d , framerate : %d\n", sensor,
+                               fimc_is_sensor_g_fcount(sensor),
+                               fimc_is_sensor_g_framerate(sensor));
+                       merr("sensor w: %d , h: %d, bns_w: %d, bns_h: %d\n", sensor,
+                               fimc_is_sensor_g_width(sensor),
+                               fimc_is_sensor_g_height(sensor),
+                               fimc_is_sensor_g_bns_width(sensor),
+                               fimc_is_sensor_g_bns_height(sensor));
+
+                       fimc_is_hw_logdump(itf);
+                       fimc_is_hw_regdump(itf);
+#ifdef BUG_ON_ENABLE
+                       BUG();
+#endif
+                       return;
+               }
+       }
+
+       mod_timer(&itf->timer, jiffies + (FIMC_IS_COMMAND_TIMEOUT/TRY_TIMEOUT_COUNT));
+}
+
+static irqreturn_t interface_isr(int irq, void *data)
+{
+       struct fimc_is_interface *itf;
+       struct work_struct *work_wq;
+       struct fimc_is_work_list *work_list;
+       struct fimc_is_work *work;
+       u32 status;
+
+       itf = (struct fimc_is_interface *)data;
+       status = fimc_is_get_intr(itf);
+
+       if (status & (1<<INTR_SHOT_DONE)) {
+               work_wq = &itf->work_wq[INTR_SHOT_DONE];
+               work_list = &itf->work_list[INTR_SHOT_DONE];
+
+               get_free_work_irq(work_list, &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_SHOT_DONE);
+                       work->fcount = work->msg.parameter1;
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else
+                       err("free work item is empty5");
+
+               status &= ~(1<<INTR_SHOT_DONE);
+               fimc_is_clr_intr(itf, INTR_SHOT_DONE);
+       }
+
+       if (status & (1<<INTR_GENERAL)) {
+               work_wq = &itf->work_wq[INTR_GENERAL];
+               work_list = &itf->work_list[INTR_GENERAL];
+
+               get_free_work_irq(&itf->work_list[INTR_GENERAL], &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_GENERAL);
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else
+                       err("free work item is empty1");
+
+               status &= ~(1<<INTR_GENERAL);
+               fimc_is_clr_intr(itf, INTR_GENERAL);
+       }
+
+       if (status & (1<<INTR_3A0C_FDONE)) {
+               work_wq = &itf->work_wq[INTR_3A0C_FDONE];
+               work_list = &itf->work_list[INTR_3A0C_FDONE];
+
+               get_free_work_irq(work_list, &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_3A0C_FDONE);
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else
+                       err("free work item is empty2");
+
+               status &= ~(1<<INTR_3A0C_FDONE);
+               fimc_is_clr_intr(itf, INTR_3A0C_FDONE);
+       }
+
+       if (status & (1<<INTR_3A1C_FDONE)) {
+               work_wq = &itf->work_wq[INTR_3A1C_FDONE];
+               work_list = &itf->work_list[INTR_3A1C_FDONE];
+
+               get_free_work_irq(work_list, &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_3A1C_FDONE);
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else
+                       err("free work item is empty2");
+
+               status &= ~(1<<INTR_3A1C_FDONE);
+               fimc_is_clr_intr(itf, INTR_3A1C_FDONE);
+       }
+
+       if (status & (1<<INTR_SCC_FDONE)) {
+               work_wq = &itf->work_wq[INTR_SCC_FDONE];
+               work_list = &itf->work_list[INTR_SCC_FDONE];
+
+               get_free_work_irq(work_list, &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_SCC_FDONE);
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else
+                       err("free work item is empty2");
+
+               status &= ~(1<<INTR_SCC_FDONE);
+               fimc_is_clr_intr(itf, INTR_SCC_FDONE);
+       }
+
+       if (status & (1<<INTR_DIS_FDONE)) {
+               work_wq = &itf->work_wq[INTR_DIS_FDONE];
+               work_list = &itf->work_list[INTR_DIS_FDONE];
+
+               get_free_work_irq(work_list, &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_DIS_FDONE);
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else {
+                       err("free work item is empty3");
+               }
+
+               status &= ~(1<<INTR_DIS_FDONE);
+               fimc_is_clr_intr(itf, INTR_DIS_FDONE);
+       }
+
+       if (status & (1<<INTR_SCP_FDONE)) {
+               work_wq = &itf->work_wq[INTR_SCP_FDONE];
+               work_list = &itf->work_list[INTR_SCP_FDONE];
+
+               get_free_work_irq(work_list, &work);
+               if (work) {
+                       fimc_is_get_cmd(itf, &work->msg, INTR_SCP_FDONE);
+                       set_req_work_irq(work_list, work);
+
+                       if (!work_pending(work_wq))
+                               wq_func_schedule(itf, work_wq);
+               } else {
+                       err("free work item is empty4");
+               }
+
+               status &= ~(1<<INTR_SCP_FDONE);
+               fimc_is_clr_intr(itf, INTR_SCP_FDONE);
+       }
+
+       if (status != 0)
+               err("status is NOT all clear(0x%08X)", status);
+
+       return IRQ_HANDLED;
+}
+
+#define VERSION_OF_NO_NEED_IFLAG 221
+int fimc_is_interface_probe(struct fimc_is_interface *this,
+       u32 regs,
+       u32 irq,
+       void *core_data)
+{
+       int ret = 0;
+       struct fimc_is_core *core = (struct fimc_is_core *)core_data;
+
+       dbg_interface("%s\n", __func__);
+
+       init_request_barrier(this);
+       init_process_barrier(this);
+       init_waitqueue_head(&this->lock_wait_queue);
+       init_waitqueue_head(&this->init_wait_queue);
+       init_waitqueue_head(&this->idle_wait_queue);
+       spin_lock_init(&this->shot_check_lock);
+
+       this->workqueue = alloc_workqueue("fimc-is/highpri", WQ_HIGHPRI, 0);
+       if (!this->workqueue)
+               warn("failed to alloc own workqueue, will be use global one");
+
+       INIT_WORK(&this->work_wq[INTR_GENERAL], wq_func_general);
+       INIT_WORK(&this->work_wq[INTR_3A0C_FDONE], wq_func_3a0c);
+       INIT_WORK(&this->work_wq[INTR_3A1C_FDONE], wq_func_3a1c);
+       INIT_WORK(&this->work_wq[INTR_SCC_FDONE], wq_func_scc);
+       INIT_WORK(&this->work_wq[INTR_DIS_FDONE], wq_func_dis);
+       INIT_WORK(&this->work_wq[INTR_SCP_FDONE], wq_func_scp);
+       INIT_WORK(&this->work_wq[INTR_SHOT_DONE], wq_func_shot);
+
+       this->regs = (void *)regs;
+       this->com_regs = (struct is_common_reg *)(regs + ISSR0);
+
+       if (GET_FIMC_IS_VER_OF_SUBIP(core, mcuctl) < VERSION_OF_NO_NEED_IFLAG)
+               this->need_iflag = true;
+       else
+               this->need_iflag = false;
+
+       ret = request_irq(irq, interface_isr, 0, "mcuctl", this);
+       if (ret)
+               err("request_irq failed\n");
+
+       notify_fcount_sen0              = &this->com_regs->fcount_sen0;
+       notify_fcount_sen1              = &this->com_regs->fcount_sen1;
+       notify_fcount_sen2              = &this->com_regs->fcount_sen2;
+       last_fcount1                    = &this->com_regs->fcount_sen3;
+       last_fcount0                    = &this->com_regs->grp1_done_frame_num;
+       this->core                      = (void *)core;
+       clear_bit(IS_IF_STATE_OPEN, &this->state);
+       clear_bit(IS_IF_STATE_START, &this->state);
+       clear_bit(IS_IF_STATE_BUSY, &this->state);
+       clear_bit(IS_IF_STATE_READY, &this->state);
+
+       init_work_list(&this->nblk_cam_ctrl,
+               TRACE_WORK_ID_CAMCTRL, MAX_NBLOCKING_COUNT);
+       init_work_list(&this->work_list[INTR_GENERAL],
+               TRACE_WORK_ID_GENERAL, MAX_WORK_COUNT);
+       init_work_list(&this->work_list[INTR_3A0C_FDONE],
+               TRACE_WORK_ID_3A0C, MAX_WORK_COUNT);
+       init_work_list(&this->work_list[INTR_3A1C_FDONE],
+               TRACE_WORK_ID_3A1C, MAX_WORK_COUNT);
+       init_work_list(&this->work_list[INTR_SCC_FDONE],
+               TRACE_WORK_ID_SCC, MAX_WORK_COUNT);
+       init_work_list(&this->work_list[INTR_DIS_FDONE],
+               TRACE_WORK_ID_DIS, MAX_WORK_COUNT);
+       init_work_list(&this->work_list[INTR_SCP_FDONE],
+               TRACE_WORK_ID_SCP, MAX_WORK_COUNT);
+       init_work_list(&this->work_list[INTR_SHOT_DONE],
+               TRACE_WORK_ID_SHOT, MAX_WORK_COUNT);
+
+       this->err_report_vendor = NULL;
+#ifdef MEASURE_TIME
+#ifdef INTERFACE_TIME
+       {
+               u32 i;
+               for (i = 0; i < HIC_COMMAND_END; ++i)
+                       measure_init(&this->time[i], i);
+       }
+#endif
+#endif
+
+       return ret;
+}
+
+int fimc_is_interface_open(struct fimc_is_interface *this)
+{
+       int i;
+       int ret = 0;
+
+       if (test_bit(IS_IF_STATE_OPEN, &this->state)) {
+               err("already open");
+               ret = -EMFILE;
+               goto exit;
+       }
+
+       dbg_interface("%s\n", __func__);
+
+       for (i = 0; i < FIMC_IS_MAX_NODES; i++) {
+               this->streaming[i] = IS_IF_STREAMING_INIT;
+               this->processing[i] = IS_IF_PROCESSING_INIT;
+               atomic_set(&this->shot_check[i], 0);
+               atomic_set(&this->shot_timeout[i], 0);
+               atomic_set(&this->sensor_check[i], 0);
+               atomic_set(&this->sensor_timeout[i], 0);
+       }
+       this->pdown_ready = IS_IF_POWER_DOWN_READY;
+       atomic_set(&this->lock_pid, 0);
+       clear_bit(IS_IF_STATE_START, &this->state);
+       clear_bit(IS_IF_STATE_BUSY, &this->state);
+       clear_bit(IS_IF_STATE_READY, &this->state);
+
+       init_timer(&this->timer);
+       this->timer.expires = jiffies +
+               (FIMC_IS_COMMAND_TIMEOUT/TRY_TIMEOUT_COUNT);
+       this->timer.data = (unsigned long)this;
+       this->timer.function = interface_timer;
+       add_timer(&this->timer);
+
+       set_bit(IS_IF_STATE_OPEN, &this->state);
+
+exit:
+       return ret;
+}
+
+int fimc_is_interface_close(struct fimc_is_interface *this)
+{
+       int ret = 0;
+       int retry;
+
+       if (!test_bit(IS_IF_STATE_OPEN, &this->state)) {
+               err("already close");
+               ret = -EMFILE;
+               goto exit;
+       }
+
+       retry = 10;
+       while (test_busystate(this) && retry) {
+               err("interface is busy");
+               msleep(20);
+               retry--;
+       }
+       if (!retry)
+               err("waiting idle is fail");
+
+       del_timer_sync(&this->timer);
+       dbg_interface("%s\n", __func__);
+
+       clear_bit(IS_IF_STATE_OPEN, &this->state);
+
+exit:
+       return ret;
+}
+
+void fimc_is_interface_lock(struct fimc_is_interface *this)
+{
+       atomic_set(&this->lock_pid, current->pid);
+}
+
+void fimc_is_interface_unlock(struct fimc_is_interface *this)
+{
+       atomic_set(&this->lock_pid, 0);
+       wake_up(&this->lock_wait_queue);
+}
+
+void fimc_is_interface_reset(struct fimc_is_interface *this)
+{
+       if (this->need_iflag) {
+               writel(0, &this->com_regs->ihcmd_iflag);
+               writel(0, &this->com_regs->taa0c_iflag);
+               writel(0, &this->com_regs->taa1c_iflag);
+               writel(0, &this->com_regs->scc_iflag);
+               writel(0, &this->com_regs->dis_iflag);
+               writel(0, &this->com_regs->scp_iflag);
+               writel(0, &this->com_regs->shot_iflag);
+       }
+}
+
+int fimc_is_hw_logdump(struct fimc_is_interface *this)
+{
+       int debug_cnt, sentence_i;
+       char *debug;
+       char letter;
+       char sentence[250];
+       int count = 0, i;
+       struct fimc_is_core *core;
+
+       if (!test_bit(IS_IF_STATE_OPEN, &this->state)) {
+               warn("interface is closed");
+               count = -EINVAL;
+               goto p_err;
+       }
+
+       pr_err("\n### firmware messsage dump ###\n");
+
+       core = (struct fimc_is_core *)this->core;
+       sentence_i = 0;
+
+       vb2_ion_sync_for_device(core->minfo.fw_cookie,
+               DEBUG_OFFSET, DEBUG_CNT, DMA_FROM_DEVICE);
+
+       debug = (char *)(core->minfo.kvaddr + DEBUG_OFFSET);
+       debug_cnt = *((int *)(core->minfo.kvaddr + DEBUGCTL_OFFSET))
+                       - DEBUG_OFFSET;
+
+       if (core->debug_cnt > debug_cnt)
+               count = (DEBUG_CNT - core->debug_cnt) + debug_cnt;
+       else
+               count = debug_cnt - core->debug_cnt;
+
+       if (count) {
+               printk(KERN_ERR "start(%d %d)\n", debug_cnt, count);
+               for (i = core->debug_cnt; count > 0; count--) {
+                       letter = debug[i];
+                       if (letter) {
+                               sentence[sentence_i] = letter;
+                               if (sentence_i >= 247) {
+                                       sentence[sentence_i + 1] = '\n';
+                                       sentence[sentence_i + 2] = 0;
+                                       printk(KERN_ERR "%s", sentence);
+                                       sentence_i = 0;
+                               } else if (letter == '\n') {
+                                       sentence[sentence_i + 1] = 0;
+                                       printk(KERN_ERR "%s", sentence);
+                                       sentence_i = 0;
+                               } else {
+                                       sentence_i++;
+                               }
+                       }
+                       i++;
+                       if (i > DEBUG_CNT)
+                               i = 0;
+               }
+               core->debug_cnt = debug_cnt;
+               printk(KERN_ERR "end\n");
+       }
+
+p_err:
+       return count;
+}
+
+int fimc_is_hw_regdump(struct fimc_is_interface *this)
+{
+       int ret = 0;
+       u32 i;
+       void __iomem *regs;
+
+       if (!test_bit(IS_IF_STATE_OPEN, &this->state)) {
+               warn("interface is closed");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("\n### MCUCTL Raw Dump ###\n");
+       regs = (this->regs);
+       for (i = 0; i < 16; ++i)
+               info("MCTL Raw[%d] : %08X\n", i, readl(regs + (4 * i)));
+
+       info("\n### COMMON REGS dump ###\n");
+       regs = this->com_regs;
+       for (i = 0; i < 64; ++i)
+               info("MCTL[%d] : %08X\n", i, readl(regs + (4 * i)));
+
+p_err:
+       return ret;
+}
+
+int fimc_is_hw_memdump(struct fimc_is_interface *this,
+       u32 start,
+       u32 end)
+{
+       int ret = 0;
+       u32 *cur;
+       u32 items, offset;
+       char term[50], sentence[250];
+
+       if (!test_bit(IS_IF_STATE_OPEN, &this->state)) {
+               warn("interface is closed");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cur = (u32 *)start;
+       items = 0;
+       offset = 0;
+
+       memset(sentence, 0, sizeof(sentence));
+       printk(KERN_ERR "Memory Dump(0x%08X ~ 0x%08X)\n", start, end);
+
+       while ((u32)cur <= end) {
+               if (!(items % 8)) {
+                       printk(KERN_ERR "%s", sentence);
+                       offset = 0;
+                       snprintf(term, sizeof(term), "%p:      ", cur);
+                       snprintf(&sentence[offset], sizeof(sentence) - offset, "%s", term);
+                       offset += strlen(term);
+               }
+
+               snprintf(term, sizeof(term), "%08X   ", *cur);
+               snprintf(&sentence[offset], sizeof(sentence) - offset, "%s", term);
+               offset += strlen(term);
+               cur++;
+               items++;
+       }
+
+       ret = (u32)cur - end;
+
+p_err:
+       return ret;
+}
+
+int fimc_is_hw_msg_test(struct fimc_is_interface *this, u32 sync_id, u32 msg_test_id)
+{
+       int ret = 0;
+       struct fimc_is_work work;
+       struct fimc_is_msg *msg;
+
+       dbg_interface("msg_test_nblk(%d)\n", msg_test_id);
+
+       msg = &work.msg;
+       msg->id = 0;
+       msg->command = HIC_MSG_TEST;
+       msg->instance = 0;
+       msg->group = 0;
+       msg->parameter1 = msg_test_id;
+       msg->parameter2 = sync_id;
+       msg->parameter3 = 0;
+       msg->parameter4 = 0;
+
+       ret = fimc_is_set_cmd_nblk(this, &work);
+
+       return ret;
+}
+
+int fimc_is_hw_enum(struct fimc_is_interface *this)
+{
+       int ret = 0;
+       struct fimc_is_msg msg;
+       volatile struct is_common_reg __iomem *com_regs;
+
+       dbg_interface("enum()\n");
+
+       /* check if hw_enum is already operated */
+       if (test_bit(IS_IF_STATE_READY, &this->state))
+           goto exit;
+
+       ret = wait_initstate(this);
+       if (ret) {
+               err("enum time out");
+               ret = -ETIME;
+               goto exit;
+       }
+
+       msg.id = 0;
+       msg.command = ISR_DONE;
+       msg.instance = 0;
+       msg.group = 0;
+       msg.parameter1 = IHC_GET_SENSOR_NUMBER;
+       /*
+        * this mean sensor numbers
+        * signel sensor: 1, dual sensor: 2, triple sensor: 3
+        */
+       msg.parameter2 = 3;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       waiting_is_ready(this);
+       com_regs = this->com_regs;
+       writel(msg.command, &com_regs->hicmd);
+       writel(msg.instance, &com_regs->hic_sensorid);
+       writel(msg.parameter1, &com_regs->hic_param1);
+       writel(msg.parameter2, &com_regs->hic_param2);
+       writel(msg.parameter3, &com_regs->hic_param3);
+       writel(msg.parameter4, &com_regs->hic_param4);
+       send_interrupt(this);
+
+       set_bit(IS_IF_STATE_READY, &this->state);
+
+exit:
+       return ret;
+}
+
+int fimc_is_hw_saddr(struct fimc_is_interface *this,
+       u32 instance, u32 *setfile_addr)
+{
+       int ret = 0;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("saddr(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_GET_SET_FILE_ADDR;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+       *setfile_addr = reply.parameter2;
+
+       return ret;
+}
+
+int fimc_is_hw_setfile(struct fimc_is_interface *this,
+       u32 instance)
+{
+       int ret = 0;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("setfile(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_LOAD_SET_FILE;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_open(struct fimc_is_interface *this,
+       u32 instance,
+       u32 module_id,
+       u32 info,
+       u32 group,
+       u32 flag,
+       u32 *mwidth,
+       u32 *mheight)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("open(%d,%d,%08X)\n", module_id, group, flag);
+
+       msg.id = 0;
+       msg.command = HIC_OPEN_SENSOR;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = module_id;
+       msg.parameter2 = info;
+       msg.parameter3 = group;
+       msg.parameter4 = flag;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       *mwidth = reply.parameter2;
+       *mheight = reply.parameter3;
+
+       return ret;
+}
+
+int fimc_is_hw_close(struct fimc_is_interface *this,
+       u32 instance)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("close sensor(instance:%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_CLOSE_SENSOR;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_stream_on(struct fimc_is_interface *this,
+       u32 instance)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       BUG_ON(!this);
+
+       dbg_interface("stream_on(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_STREAM_ON;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_stream_off(struct fimc_is_interface *this,
+       u32 instance)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("stream_off(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_STREAM_OFF;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_process_on(struct fimc_is_interface *this,
+       u32 instance, u32 group)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("process_on(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_PROCESS_START;
+       msg.instance = instance;
+       msg.group = group;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_process_off(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 mode)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       WARN_ON(mode >= 2);
+
+       dbg_interface("process_off(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_PROCESS_STOP;
+       msg.instance = instance;
+       msg.group = group;
+       msg.parameter1 = mode;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_i2c_lock(struct fimc_is_interface *this,
+       u32 instance, int i2c_clk, bool lock)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("i2c_lock(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_I2C_CONTROL_LOCK;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = lock;
+       msg.parameter2 = i2c_clk;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_s_param(struct fimc_is_interface *this,
+       u32 instance, u32 lindex, u32 hindex, u32 indexes)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("s_param(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_SET_PARAMETER;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = ISS_PREVIEW_STILL;
+       msg.parameter2 = indexes;
+       msg.parameter3 = lindex;
+       msg.parameter4 = hindex;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_a_param(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 sub_mode)
+{
+       int ret = 0;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("a_param(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_PREVIEW_STILL;
+       msg.instance = instance;
+       msg.group = group;
+       msg.parameter1 = sub_mode;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_g_capability(struct fimc_is_interface *this,
+       u32 instance, u32 address)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("g_capability(%d)\n", instance);
+
+       msg.id = 0;
+       msg.command = HIC_GET_STATIC_METADATA;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = address;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_map(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 address, u32 size)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("[%d][%d] map(%08X, %X)\n", instance, group, address, size);
+
+       msg.id = 0;
+       msg.command = HIC_SET_A5_MAP;
+       msg.instance = instance;
+       msg.group = group;
+       msg.parameter1 = address;
+       msg.parameter2 = size;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_unmap(struct fimc_is_interface *this,
+       u32 instance, u32 group)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("[%d][%d] unmap\n", instance, group);
+
+       msg.id = 0;
+       msg.command = HIC_SET_A5_UNMAP;
+       msg.instance = instance;
+       msg.group = group;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+int fimc_is_hw_power_down(struct fimc_is_interface *this,
+       u32 instance)
+{
+       int ret = 0;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("pwr_down(%d)\n", instance);
+
+       if (!test_bit(IS_IF_STATE_START, &this->state)) {
+               warn("instance(%d): FW is not initialized, wait\n", instance);
+               ret = fimc_is_hw_enum(this);
+               if (ret)
+                       err("fimc_is_itf_enum is fail(%d)", ret);
+       }
+
+       msg.id = 0;
+       msg.command = HIC_POWER_DOWN;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = 0;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+
+#if (FW_HAS_SYS_CTRL_CMD)
+int fimc_is_hw_sys_ctl(struct fimc_is_interface *this,
+       u32 instance, int cmd, int val)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("sys_ctl(cmd(%d), val(%d))\n", cmd, val);
+
+       msg.id = 0;
+       msg.command = HIC_SYSTEM_CONTROL;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = cmd;
+       msg.parameter2 = val;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+#else
+int fimc_is_hw_sys_ctl(struct fimc_is_interface *this,
+       u32 instance, int cmd, int val)
+{
+       return 0;
+}
+#endif
+
+#if (FW_HAS_SENSOR_MODE_CMD)
+int fimc_is_hw_sensor_mode(struct fimc_is_interface *this,
+       u32 instance, int cfg)
+{
+       int ret;
+       struct fimc_is_msg msg, reply;
+
+       dbg_interface("sensor mode(%d): %d\n", instance, cfg);
+
+       msg.id = 0;
+       msg.command = HIC_SENSOR_MODE_CHANGE;
+       msg.instance = instance;
+       msg.group = 0;
+       msg.parameter1 = cfg;
+       msg.parameter2 = 0;
+       msg.parameter3 = 0;
+       msg.parameter4 = 0;
+
+       ret = fimc_is_set_cmd(this, &msg, &reply);
+
+       return ret;
+}
+#else
+int fimc_is_hw_sensor_mode(struct fimc_is_interface *this,
+       u32 instance, int cfg)
+{
+       return 0;
+}
+#endif
+
+int fimc_is_hw_shot_nblk(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 bayer, u32 shot, u32 fcount, u32 rcount)
+{
+       int ret = 0;
+       struct fimc_is_msg msg;
+
+       /*dbg_interface("shot_nblk(%d, %d)\n", instance, fcount);*/
+
+       msg.id = 0;
+       msg.command = HIC_SHOT;
+       msg.instance = instance;
+       msg.group = group;
+       msg.parameter1 = bayer;
+       msg.parameter2 = shot;
+       msg.parameter3 = fcount;
+       msg.parameter4 = rcount;
+
+       ret = fimc_is_set_cmd_shot(this, &msg);
+
+       return ret;
+}
+
+int fimc_is_hw_s_camctrl_nblk(struct fimc_is_interface *this,
+       u32 instance, u32 address, u32 fcount)
+{
+       int ret = 0;
+       struct fimc_is_work *work;
+       struct fimc_is_msg *msg;
+
+       dbg_interface("cam_ctrl_nblk(%d)\n", instance);
+
+       get_free_work(&this->nblk_cam_ctrl, &work);
+
+       if (work) {
+               work->fcount = fcount;
+               msg = &work->msg;
+               msg->id = 0;
+               msg->command = HIC_SET_CAM_CONTROL;
+               msg->instance = instance;
+               msg->group = 0;
+               msg->parameter1 = address;
+               msg->parameter2 = fcount;
+               msg->parameter3 = 0;
+               msg->parameter4 = 0;
+
+               ret = fimc_is_set_cmd_nblk(this, work);
+       } else {
+               err("g_free_nblk return NULL");
+               print_fre_work_list(&this->nblk_cam_ctrl);
+               print_req_work_list(&this->nblk_cam_ctrl);
+               ret = 1;
+       }
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-interface.h b/drivers/media/platform/exynos/fimc-is/fimc-is-interface.h
new file mode 100644 (file)
index 0000000..4c814dd
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * drivers/media/video/exynos/fimc-is-mc2/fimc-is-interface.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * The header file related to camera
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_INTERFACE_H
+#define FIMC_IS_INTERFACE_H
+
+#include "fimc-is-metadata.h"
+#include "fimc-is-framemgr.h"
+#include "fimc-is-video.h"
+#include "fimc-is-time.h"
+#include "fimc-is-cmd.h"
+
+/*#define TRACE_WORK*/
+/* cam_ctrl : 1
+   shot :     2 */
+#define TRACE_WORK_ID_CAMCTRL  0x1
+#define TRACE_WORK_ID_SHOT     0x2
+#define TRACE_WORK_ID_GENERAL  0x4
+#define TRACE_WORK_ID_3A0C     0x8
+#define TRACE_WORK_ID_3A1C     0x10
+#define TRACE_WORK_ID_SCC      0x20
+#define TRACE_WORK_ID_DIS      0x40
+#define TRACE_WORK_ID_SCP      0x80
+#define TRACE_WORK_ID_MASK     0xFF
+
+#define MAX_NBLOCKING_COUNT    3
+#define MAX_WORK_COUNT         10
+
+#define TRY_TIMEOUT_COUNT      2
+#define SENSOR_TIMEOUT_COUNT   2
+#define TRY_RECV_AWARE_COUNT   100
+
+#define LOWBIT_OF(num) (num >= 32 ? 0 : (u32)1<<num)
+#define HIGHBIT_OF(num)        (num >= 32 ? (u32)1<<(num-32) : 0)
+
+enum fimc_is_interface_state {
+       IS_IF_STATE_OPEN,
+       IS_IF_STATE_START,
+       IS_IF_STATE_BUSY,
+       IS_IF_STATE_READY
+};
+
+enum interrupt_map {
+       INTR_GENERAL            = 0,
+       INTR_ISP_FDONE          = 1,
+       INTR_3A0C_FDONE         = 2,
+       INTR_3A1C_FDONE         = 3,
+       INTR_SCC_FDONE          = 4,
+       INTR_DIS_FDONE          = 5,
+       INTR_SCP_FDONE          = 6,
+       INTR_SHOT_DONE          = 7,
+       INTR_MAX_MAP
+};
+
+enum streaming_state {
+       IS_IF_STREAMING_INIT,
+       IS_IF_STREAMING_OFF,
+       IS_IF_STREAMING_ON
+};
+
+enum processing_state {
+       IS_IF_PROCESSING_INIT,
+       IS_IF_PROCESSING_OFF,
+       IS_IF_PROCESSING_ON
+};
+
+enum pdown_ready_state {
+       IS_IF_POWER_DOWN_READY,
+       IS_IF_POWER_DOWN_NREADY
+};
+
+struct fimc_is_msg {
+       u32     id;
+       u32     command;
+       u32     instance;
+       u32     group;
+       u32     parameter1;
+       u32     parameter2;
+       u32     parameter3;
+       u32     parameter4;
+};
+
+struct fimc_is_work {
+       struct list_head                list;
+       struct fimc_is_msg              msg;
+       u32                             fcount;
+       struct fimc_is_frame            *frame;
+};
+
+struct fimc_is_work_list {
+       u32                             id;
+       struct fimc_is_work             work[MAX_WORK_COUNT];
+       spinlock_t                      slock_free;
+       spinlock_t                      slock_request;
+       struct list_head                work_free_head;
+       u32                             work_free_cnt;
+       struct list_head                work_request_head;
+       u32                             work_request_cnt;
+       wait_queue_head_t               wait_queue;
+};
+
+struct fimc_is_interface {
+       void __iomem                    *regs;
+       struct is_common_reg __iomem    *com_regs;
+       bool                            need_iflag;
+       unsigned long                   state;
+       spinlock_t                      process_barrier;
+       struct mutex                    request_barrier;
+
+       atomic_t                        lock_pid;
+       wait_queue_head_t               lock_wait_queue;
+       wait_queue_head_t               init_wait_queue;
+       wait_queue_head_t               idle_wait_queue;
+       struct fimc_is_msg              reply;
+#ifdef MEASURE_TIME
+#ifdef INTERFACE_TIME
+       struct fimc_is_interface_time   time[HIC_COMMAND_END];
+#endif
+#endif
+
+       struct workqueue_struct         *workqueue;
+       struct work_struct              work_wq[INTR_MAX_MAP];
+       struct fimc_is_work_list        work_list[INTR_MAX_MAP];
+
+       /* sensor streaming flag */
+       enum streaming_state            streaming[FIMC_IS_MAX_NODES];
+       /* firmware processing flag */
+       enum processing_state           processing[FIMC_IS_MAX_NODES];
+       /* frrmware power down ready flag */
+       enum pdown_ready_state          pdown_ready;
+
+       struct fimc_is_framemgr         *framemgr;
+
+       struct fimc_is_work_list        nblk_cam_ctrl;
+
+       /* shot timeout check */
+       spinlock_t                      shot_check_lock;
+       atomic_t                        shot_check[FIMC_IS_MAX_NODES];
+       atomic_t                        shot_timeout[FIMC_IS_MAX_NODES];
+       /* sensor timeout check */
+       atomic_t                        sensor_check[FIMC_IS_MAX_NODES];
+       atomic_t                        sensor_timeout[FIMC_IS_MAX_NODES];
+       struct timer_list               timer;
+
+       /* callback func to handle error report for specific purpose */
+       void                            *err_report_data;
+       int                             (*err_report_vendor)(void *data, u32 err_report_type);
+
+       struct camera2_uctl             isp_peri_ctl;
+       void                            *core;
+};
+
+int fimc_is_interface_probe(struct fimc_is_interface *this,
+       u32 regs,
+       u32 irq,
+       void *core_data);
+int fimc_is_interface_open(struct fimc_is_interface *this);
+int fimc_is_interface_close(struct fimc_is_interface *this);
+void fimc_is_interface_lock(struct fimc_is_interface *this);
+void fimc_is_interface_unlock(struct fimc_is_interface *this);
+void fimc_is_interface_reset(struct fimc_is_interface *this);
+
+/*for debugging*/
+int print_fre_work_list(struct fimc_is_work_list *this);
+int print_req_work_list(struct fimc_is_work_list *this);
+
+int fimc_is_hw_msg_test(struct fimc_is_interface *this, u32 sync_id, u32 msg_test_id);
+int fimc_is_hw_logdump(struct fimc_is_interface *this);
+int fimc_is_hw_regdump(struct fimc_is_interface *this);
+int fimc_is_hw_memdump(struct fimc_is_interface *this,
+       u32 start,
+       u32 end);
+int fimc_is_hw_enum(struct fimc_is_interface *this);
+int fimc_is_hw_open(struct fimc_is_interface *this,
+       u32 instance, u32 module, u32 info, u32 group, u32 flag,
+       u32 *mwidth, u32 *mheight);
+int fimc_is_hw_close(struct fimc_is_interface *this,
+       u32 instance);
+int fimc_is_hw_saddr(struct fimc_is_interface *interface,
+       u32 instance, u32 *setfile_addr);
+int fimc_is_hw_setfile(struct fimc_is_interface *interface,
+       u32 instance);
+int fimc_is_hw_process_on(struct fimc_is_interface *this,
+       u32 instance, u32 group);
+int fimc_is_hw_process_off(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 mode);
+int fimc_is_hw_stream_on(struct fimc_is_interface *interface,
+       u32 instance);
+int fimc_is_hw_stream_off(struct fimc_is_interface *interface,
+       u32 instance);
+int fimc_is_hw_s_param(struct fimc_is_interface *interface,
+       u32 instance, u32 lindex, u32 hindex, u32 indexes);
+int fimc_is_hw_a_param(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 sub_mode);
+int fimc_is_hw_g_capability(struct fimc_is_interface *this,
+       u32 instance, u32 address);
+int fimc_is_hw_map(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 address, u32 size);
+int fimc_is_hw_unmap(struct fimc_is_interface *this,
+       u32 instance, u32 group);
+int fimc_is_hw_power_down(struct fimc_is_interface *interface,
+       u32 instance);
+int fimc_is_hw_i2c_lock(struct fimc_is_interface *interface,
+       u32 instance, int clk, bool lock);
+int fimc_is_hw_sys_ctl(struct fimc_is_interface *this,
+       u32 instance, int cmd, int val);
+int fimc_is_hw_sensor_mode(struct fimc_is_interface *this,
+       u32 instance, int cfg);
+
+int fimc_is_hw_shot_nblk(struct fimc_is_interface *this,
+       u32 instance, u32 group, u32 bayer, u32 shot, u32 fcount, u32 rcount);
+int fimc_is_hw_s_camctrl_nblk(struct fimc_is_interface *this,
+       u32 instance, u32 address, u32 fcount);
+
+/* func to register error report callback */
+int fimc_is_set_err_report_vendor(struct fimc_is_interface *itf,
+               void *err_report_data,
+               int (*err_report_vendor)(void *data, u32 err_report_type));
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-mem.c b/drivers/media/platform/exynos/fimc-is/fimc-is-mem.c
new file mode 100644 (file)
index 0000000..30d5dab
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+#include <linux/exynos_iovmm.h>
+#else
+#include <plat/iovmm.h>
+#endif
+
+static void *fimc_is_ion_init(struct platform_device *pdev)
+{
+       return vb2_ion_create_context(&pdev->dev, SZ_4K,
+                                       VB2ION_CTX_IOMMU |
+                                       VB2ION_CTX_VMCONTIG |
+                                       VB2ION_CTX_KVA_ONDEMAND);
+}
+
+static unsigned long plane_addr(struct vb2_buffer *vb, u32 plane_no)
+{
+       void *cookie = vb2_plane_cookie(vb, plane_no);
+       dma_addr_t dva = 0;
+
+       WARN_ON(vb2_ion_dma_address(cookie, &dva) != 0);
+
+       return dva;
+}
+
+static unsigned long plane_kvaddr(struct vb2_buffer *vb, u32 plane_no)
+{
+       void *kvaddr = vb2_plane_vaddr(vb, plane_no);
+
+       return (unsigned long)kvaddr;
+}
+
+const struct fimc_is_vb2 fimc_is_vb2_ion = {
+       .ops            = &vb2_ion_memops,
+       .init           = fimc_is_ion_init,
+       .cleanup        = vb2_ion_destroy_context,
+       .plane_addr     = plane_addr,
+       .plane_kvaddr   = plane_kvaddr,
+       .resume         = vb2_ion_attach_iommu,
+       .suspend        = vb2_ion_detach_iommu,
+       .set_cacheable  = vb2_ion_set_cached,
+};
+
+int fimc_is_mem_probe(struct fimc_is_mem *this,
+       struct platform_device *pdev)
+{
+       u32 ret = 0;
+
+       this->vb2 = &fimc_is_vb2_ion;
+
+       this->alloc_ctx = this->vb2->init(pdev);
+       if (IS_ERR(this->alloc_ctx)) {
+               ret = PTR_ERR(this->alloc_ctx);
+               goto p_err;
+       }
+
+       /* FIXME: should be different by device type */
+       exynos_create_iovmm(&pdev->dev, 1, 4);
+
+p_err:
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-mem.h b/drivers/media/platform/exynos/fimc-is/fimc-is-mem.h
new file mode 100644 (file)
index 0000000..4000162
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_MEM_H
+#define FIMC_IS_MEM_H
+
+#include <linux/platform_device.h>
+#include <media/videobuf2-core.h>
+#if defined(CONFIG_VIDEOBUF2_CMA_PHYS)
+#include <media/videobuf2-cma-phys.h>
+#elif defined(CONFIG_VIDEOBUF2_ION)
+#include <media/videobuf2-ion.h>
+#endif
+
+struct fimc_is_minfo {
+       dma_addr_t      base;           /* buffer base */
+       size_t          size;           /* total length */
+       dma_addr_t      vaddr_base;     /* buffer base */
+       dma_addr_t      vaddr_curr;     /* current addr */
+       void            *bitproc_buf;
+       void            *fw_cookie;
+
+       u32             dvaddr;
+       u32             kvaddr;
+       u32             dvaddr_debug;
+       u32             kvaddr_debug;
+       u32             dvaddr_fshared;
+       u32             kvaddr_fshared;
+       u32             dvaddr_region;
+       u32             kvaddr_region;
+       u32             dvaddr_shared; /*shared region of is region*/
+       u32             kvaddr_shared;
+       u32             dvaddr_odc;
+       u32             kvaddr_odc;
+       u32             dvaddr_dis;
+       u32             kvaddr_dis;
+       u32             dvaddr_3dnr;
+       u32             kvaddr_3dnr;
+};
+
+struct fimc_is_vb2 {
+       const struct vb2_mem_ops *ops;
+       void *(*init)(struct platform_device *pdev);
+       void (*cleanup)(void *alloc_ctx);
+
+       unsigned long (*plane_addr)(struct vb2_buffer *vb, u32 plane_no);
+       unsigned long (*plane_kvaddr)(struct vb2_buffer *vb, u32 plane_no);
+
+       int (*resume)(void *alloc_ctx);
+       void (*suspend)(void *alloc_ctx);
+
+       void (*set_cacheable)(void *alloc_ctx, bool cacheable);
+};
+
+struct fimc_is_mem {
+       struct platform_device          *pdev;
+       struct vb2_alloc_ctx            *alloc_ctx;
+
+       const struct fimc_is_vb2        *vb2;
+};
+
+int fimc_is_mem_probe(struct fimc_is_mem *this,
+       struct platform_device *pdev);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-metadata.h b/drivers/media/platform/exynos/fimc-is/fimc-is-metadata.h
new file mode 100644 (file)
index 0000000..f2f27c7
--- /dev/null
@@ -0,0 +1,1472 @@
+/* Copyright (c) 2011 Samsung Electronics Co, Ltd.
+ *
+ * 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.
+
+ *
+
+ * Alternatively, Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ */
+
+#ifndef FIMC_IS_METADATA_H_
+#define FIMC_IS_METADATA_H_
+
+#ifndef _LINUX_TYPES_H
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#endif
+
+struct rational {
+       uint32_t num;
+       uint32_t den;
+};
+
+#define CAMERA2_MAX_AVAILABLE_MODE     21
+#define CAMERA2_MAX_FACES              16
+#define CAMERA2_MAX_VENDER_LENGTH      400
+#define CAPTURE_NODE_MAX               2
+#define CAMERA2_MAX_PDAF_MULTIROI_COLUMN 9
+#define CAMERA2_MAX_PDAF_MULTIROI_ROW 5
+
+#define OPEN_MAGIC_NUMBER              0x01020304
+#define SHOT_MAGIC_NUMBER              0x23456789
+
+/*
+ *controls/dynamic metadata
+*/
+
+/* android.request */
+
+enum metadata_mode {
+       METADATA_MODE_NONE,
+       METADATA_MODE_FULL
+};
+
+struct camera2_request_ctl {
+       uint32_t                id;
+       enum metadata_mode      metadataMode;
+       uint8_t                 outputStreams[16];
+       uint32_t                frameCount;
+        uint32_t               requestCount;
+};
+
+struct camera2_request_dm {
+       uint32_t                id;
+       enum metadata_mode      metadataMode;
+       uint32_t                frameCount;
+        uint32_t               requestCount;
+};
+
+struct camera2_entry_ctl {
+       /** \brief
+               per-frame control for entry control
+               \remarks
+               low parameter is 0bit ~ 31bit flag
+               high parameter is 32bit ~ 63bit flag
+       */
+       uint32_t                lowIndexParam;
+       uint32_t                highIndexParam;
+       uint32_t                parameter[2048];
+};
+
+struct camera2_entry_dm {
+       uint32_t                lowIndexParam;
+       uint32_t                highIndexParam;
+};
+
+/* android.lens */
+
+enum optical_stabilization_mode {
+       OPTICAL_STABILIZATION_MODE_OFF = 1,
+       OPTICAL_STABILIZATION_MODE_ON = 2,
+       OPTICAL_STABILIZATION_MODE_STILL = 3,  // Still mode
+       OPTICAL_STABILIZATION_MODE_STILL_ZOOM = 4, // Still Zoom mode
+       OPTICAL_STABILIZATION_MODE_VIDEO = 5,  // Recording mode
+       OPTICAL_STABILIZATION_MODE_SINE_X = 6,  // factory mode x
+       OPTICAL_STABILIZATION_MODE_SINE_Y = 7,  // factory mode y
+       OPTICAL_STABILIZATION_MODE_CENTERING = 8 // Centering mode
+};
+
+enum lens_facing {
+       LENS_FACING_BACK,
+       LENS_FACING_FRONT
+};
+
+struct camera2_lens_ctl {
+       uint32_t                                focusDistance;
+       float                                   aperture;
+       float                                   focalLength;
+       float                                   filterDensity;
+       enum optical_stabilization_mode         opticalStabilizationMode;
+
+};
+
+struct camera2_lens_dm {
+       uint32_t                                focusDistance;
+       float                                   aperture;
+       float                                   focalLength;
+       float                                   filterDensity;
+       enum optical_stabilization_mode         opticalStabilizationMode;
+       float                                   focusRange[2];
+};
+
+struct camera2_lens_sm {
+       float                           minimumFocusDistance;
+       float                           hyperfocalDistance;
+       float                           availableFocalLength[2];
+       float                           availableApertures;
+       /*assuming 1 aperture*/
+       float                           availableFilterDensities;
+       /*assuming 1 ND filter value*/
+       enum optical_stabilization_mode availableOpticalStabilization;
+       /*assuming 1*/
+       uint32_t                        shadingMapSize;
+       float                           shadingMap[3][40][30];
+       uint32_t                        geometricCorrectionMapSize;
+       float                           geometricCorrectionMap[2][3][40][30];
+       enum lens_facing                facing;
+       float                           position[2];
+};
+
+/* android.sensor */
+
+enum sensor_colorfilterarrangement {
+       SENSOR_COLORFILTERARRANGEMENT_RGGB,
+       SENSOR_COLORFILTERARRANGEMENT_GRBG,
+       SENSOR_COLORFILTERARRANGEMENT_GBRG,
+       SENSOR_COLORFILTERARRANGEMENT_BGGR,
+       SENSOR_COLORFILTERARRANGEMENT_RGB
+};
+
+enum sensor_ref_illuminant {
+       SENSOR_ILLUMINANT_DAYLIGHT = 1,
+       SENSOR_ILLUMINANT_FLUORESCENT = 2,
+       SENSOR_ILLUMINANT_TUNGSTEN = 3,
+       SENSOR_ILLUMINANT_FLASH = 4,
+       SENSOR_ILLUMINANT_FINE_WEATHER = 9,
+       SENSOR_ILLUMINANT_CLOUDY_WEATHER = 10,
+       SENSOR_ILLUMINANT_SHADE = 11,
+       SENSOR_ILLUMINANT_DAYLIGHT_FLUORESCENT = 12,
+       SENSOR_ILLUMINANT_DAY_WHITE_FLUORESCENT = 13,
+       SENSOR_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14,
+       SENSOR_ILLUMINANT_WHITE_FLUORESCENT = 15,
+       SENSOR_ILLUMINANT_STANDARD_A = 17,
+       SENSOR_ILLUMINANT_STANDARD_B = 18,
+       SENSOR_ILLUMINANT_STANDARD_C = 19,
+       SENSOR_ILLUMINANT_D55 = 20,
+       SENSOR_ILLUMINANT_D65 = 21,
+       SENSOR_ILLUMINANT_D75 = 22,
+       SENSOR_ILLUMINANT_D50 = 23,
+       SENSOR_ILLUMINANT_ISO_STUDIO_TUNGSTEN = 24
+};
+
+struct camera2_sensor_ctl {
+       /* unit : nano */
+       uint64_t        exposureTime;
+       /* unit : nano(It's min frame duration */
+       uint64_t        frameDuration;
+       /* unit : percent(need to change ISO value?) */
+       uint32_t        sensitivity;
+};
+
+struct camera2_sensor_dm {
+       uint64_t        exposureTime;
+       uint64_t        frameDuration;
+       uint32_t        sensitivity;
+       uint64_t        timeStamp;
+       uint32_t        analogGain;
+       uint32_t        digitalGain;
+};
+
+struct camera2_sensor_sm {
+       uint32_t        exposureTimeRange[2];
+       uint32_t        maxFrameDuration;
+       /* list of available sensitivities. */
+       uint32_t        availableSensitivities[10];
+       enum sensor_colorfilterarrangement colorFilterArrangement;
+       float           physicalSize[2];
+       uint32_t        pixelArraySize[2];
+       uint32_t        activeArraySize[4];
+       uint32_t        whiteLevel;
+       uint32_t        blackLevelPattern[4];
+       struct rational colorTransform1[9];
+       struct rational colorTransform2[9];
+       enum sensor_ref_illuminant      referenceIlluminant1;
+       enum sensor_ref_illuminant      referenceIlluminant2;
+       struct rational forwardMatrix1[9];
+       struct rational forwardMatrix2[9];
+       struct rational calibrationTransform1[9];
+       struct rational calibrationTransform2[9];
+       struct rational baseGainFactor;
+       uint32_t        maxAnalogSensitivity;
+       float           noiseModelCoefficients[2];
+       uint32_t        orientation;
+};
+
+
+
+/* android.flash */
+
+enum flash_mode {
+       CAM2_FLASH_MODE_OFF = 1,
+       CAM2_FLASH_MODE_SINGLE,
+       CAM2_FLASH_MODE_TORCH,
+       CAM2_FLASH_MODE_BEST
+};
+
+enum capture_state {
+    CAPTURE_STATE_NONE = 0,
+    CAPTURE_STATE_FLASH = 1,
+    CAPTURE_STATE_HDR_DARK = 12,
+    CAPTURE_STATE_HDR_NORMAL = 13,
+    CAPTURE_STATE_HDR_BRIGHT = 14,
+    CAPTURE_STATE_ZSL_LIKE = 20,
+};
+
+struct camera2_flash_ctl {
+       enum flash_mode         flashMode;
+       uint32_t                firingPower;
+       uint64_t                firingTime;
+};
+
+struct camera2_flash_dm {
+       enum flash_mode         flashMode;
+       /*10 is max power*/
+       uint32_t                firingPower;
+       /*unit : microseconds*/
+       uint64_t                firingTime;
+       /*1 : stable, 0 : unstable*/
+       uint32_t                firingStable;
+       /*1 : success, 0 : fail*/
+       uint32_t                decision;
+       /*0: None, 1 : pre, 2 : main flash ready*/
+       uint32_t                flashReady;
+       /*0: None, 1 : pre, 2 : main flash off ready*/
+       uint32_t                flashOffReady;
+};
+
+struct camera2_flash_sm {
+       uint32_t        available;
+       uint64_t        chargeDuration;
+};
+
+
+/* android.hotpixel */
+
+enum processing_mode {
+       PROCESSING_MODE_OFF = 1,
+       PROCESSING_MODE_FAST,
+       PROCESSING_MODE_HIGH_QUALITY
+};
+
+
+struct camera2_hotpixel_ctl {
+       enum processing_mode    mode;
+};
+
+struct camera2_hotpixel_dm {
+       enum processing_mode    mode;
+};
+
+
+
+/* android.demosaic */
+
+struct camera2_demosaic_ctl {
+       enum processing_mode    mode;
+};
+
+struct camera2_demosaic_dm {
+       enum processing_mode    mode;
+};
+
+
+
+/* android.noiseReduction */
+
+struct camera2_noisereduction_ctl {
+       enum processing_mode    mode;
+       uint32_t                strength;
+};
+
+struct camera2_noisereduction_dm {
+       enum processing_mode    mode;
+       uint32_t                strength;
+};
+
+
+
+/* android.shading */
+
+struct camera2_shading_ctl {
+       enum processing_mode    mode;
+};
+
+struct camera2_shading_dm {
+       enum processing_mode    mode;
+};
+
+
+
+/* android.geometric */
+
+struct camera2_geometric_ctl {
+       enum processing_mode    mode;
+};
+
+struct camera2_geometric_dm {
+       enum processing_mode    mode;
+};
+
+
+
+/* android.colorCorrection */
+
+enum colorcorrection_mode {
+       COLORCORRECTION_MODE_FAST = 1,
+       COLORCORRECTION_MODE_HIGH_QUALITY,
+       COLORCORRECTION_MODE_TRANSFORM_MATRIX,
+       COLORCORRECTION_MODE_EFFECT_MONO,
+       COLORCORRECTION_MODE_EFFECT_NEGATIVE,
+       COLORCORRECTION_MODE_EFFECT_SOLARIZE,
+       COLORCORRECTION_MODE_EFFECT_SEPIA,
+       COLORCORRECTION_MODE_EFFECT_POSTERIZE,
+       COLORCORRECTION_MODE_EFFECT_WHITEBOARD,
+       COLORCORRECTION_MODE_EFFECT_BLACKBOARD,
+       COLORCORRECTION_MODE_EFFECT_AQUA,
+       COLORCORRECTION_MODE_EFFECT_EMBOSS,
+       COLORCORRECTION_MODE_EFFECT_EMBOSS_MONO,
+       COLORCORRECTION_MODE_EFFECT_SKETCH,
+       COLORCORRECTION_MODE_EFFECT_RED_YELLOW_POINT,
+       COLORCORRECTION_MODE_EFFECT_GREEN_POINT,
+       COLORCORRECTION_MODE_EFFECT_BLUE_POINT,
+       COLORCORRECTION_MODE_EFFECT_MAGENTA_POINT,
+       COLORCORRECTION_MODE_EFFECT_WARM_VINTAGE,
+       COLORCORRECTION_MODE_EFFECT_COLD_VINTAGE,
+       COLORCORRECTION_MODE_EFFECT_WASHED,
+       COLORCORRECTION_MODE_EFFECT_BEAUTY_FACE,
+       TOTAOCOUNT_COLORCORRECTION_MODE_EFFECT
+};
+
+
+struct camera2_colorcorrection_ctl {
+       enum colorcorrection_mode       mode;
+       float                           transform[9];
+       uint32_t                        hue;
+       uint32_t                        saturation;
+       uint32_t                        brightness;
+       uint32_t                        contrast;
+};
+
+struct camera2_colorcorrection_dm {
+       enum colorcorrection_mode       mode;
+       float                           transform[9];
+       uint32_t                        hue;
+       uint32_t                        saturation;
+       uint32_t                        brightness;
+       uint32_t                        contrast;
+};
+
+struct camera2_colorcorrection_sm {
+       /*assuming 10 supported modes*/
+       uint8_t                 availableModes[CAMERA2_MAX_AVAILABLE_MODE];
+       uint32_t                hueRange[2];
+       uint32_t                saturationRange[2];
+       uint32_t                brightnessRange[2];
+       uint32_t                contrastRange[2];
+};
+
+
+/* android.tonemap */
+
+enum tonemap_mode {
+       TONEMAP_MODE_FAST = 1,
+       TONEMAP_MODE_HIGH_QUALITY,
+       TONEMAP_MODE_CONTRAST_CURVE
+};
+
+struct camera2_tonemap_ctl {
+       enum tonemap_mode               mode;
+       /* assuming maxCurvePoints = 64 */
+       float                           curveRed[64];
+       float                           curveGreen[64];
+       float                           curveBlue[64];
+};
+
+struct camera2_tonemap_dm {
+       enum tonemap_mode               mode;
+       /* assuming maxCurvePoints = 64 */
+       float                           curveRed[64];
+       float                           curveGreen[64];
+       float                           curveBlue[64];
+};
+
+struct camera2_tonemap_sm {
+       uint32_t        maxCurvePoints;
+};
+
+/* android.edge */
+
+struct camera2_edge_ctl {
+       enum processing_mode    mode;
+       uint32_t                strength;
+};
+
+struct camera2_edge_dm {
+       enum processing_mode    mode;
+       uint32_t                strength;
+};
+
+
+
+/* android.scaler */
+
+enum scaler_availableformats {
+       SCALER_FORMAT_BAYER_RAW,
+       SCALER_FORMAT_YV12,
+       SCALER_FORMAT_NV21,
+       SCALER_FORMAT_JPEG,
+       SCALER_FORMAT_UNKNOWN
+};
+
+struct camera2_scaler_ctl {
+       uint32_t        cropRegion[4];
+       uint32_t        orientation;
+};
+
+struct camera2_scaler_dm {
+       uint32_t        cropRegion[4];
+       uint32_t        orientation;
+};
+
+struct camera2_scaler_sm {
+       enum scaler_availableformats availableFormats[4];
+       /*assuming # of availableFormats = 4*/
+       uint32_t        availableRawSizes;
+       uint64_t        availableRawMinDurations;
+       /* needs check */
+       uint32_t        availableProcessedSizes[8];
+       uint64_t        availableProcessedMinDurations[8];
+       uint32_t        availableJpegSizes[8][2];
+       uint64_t        availableJpegMinDurations[8];
+       uint32_t        availableMaxDigitalZoom[8];
+};
+
+/* android.jpeg */
+struct camera2_jpeg_ctl {
+       uint32_t        quality;
+       uint32_t        thumbnailSize[2];
+       uint32_t        thumbnailQuality;
+       double          gpsCoordinates[3];
+       uint32_t        gpsProcessingMethod;
+       uint64_t        gpsTimestamp;
+       uint32_t        orientation;
+};
+
+struct camera2_jpeg_dm {
+       uint32_t        quality;
+       uint32_t        thumbnailSize[2];
+       uint32_t        thumbnailQuality;
+       double          gpsCoordinates[3];
+       uint32_t        gpsProcessingMethod;
+       uint64_t        gpsTimestamp;
+       uint32_t        orientation;
+};
+
+struct camera2_jpeg_sm {
+       uint32_t        availableThumbnailSizes[8][2];
+       uint32_t        maxSize;
+       /*assuming supported size=8*/
+};
+
+
+
+/* android.statistics */
+
+enum facedetect_mode {
+       FACEDETECT_MODE_OFF = 1,
+       FACEDETECT_MODE_SIMPLE,
+       FACEDETECT_MODE_FULL
+};
+
+enum stats_mode {
+       STATS_MODE_OFF = 1,
+       STATS_MODE_ON
+};
+
+enum stats_lowlightmode {
+    STATE_LLS_LEVEL_ZSL = 0,
+    STATE_LLS_LEVEL_LOW = 1,
+    STATE_LLS_LEVEL_HIGH = 2,
+    STATE_LLS_LEVEL_SIS = 3,
+    STATE_LLS_LEVEL_ZSL_LIKE = 4,
+    STATE_LLS_LEVEL_ZSL_FLASH = 16,
+};
+
+struct camera2_stats_ctl {
+       enum facedetect_mode    faceDetectMode;
+       enum stats_mode         histogramMode;
+       enum stats_mode         sharpnessMapMode;
+};
+
+
+struct camera2_stats_dm {
+       enum facedetect_mode    faceDetectMode;
+       uint32_t                faceRectangles[CAMERA2_MAX_FACES][4];
+       uint8_t                 faceScores[CAMERA2_MAX_FACES];
+       uint32_t                faceLandmarks[CAMERA2_MAX_FACES][6];
+       uint32_t                faceIds[CAMERA2_MAX_FACES];
+/* PAYTON_CHECK_20120712 : histogram_mode -> stats_mode */
+       enum stats_mode         histogramMode;
+/* [hj529.kim, 2012/07/19] androd.statistics.histogram */
+       uint32_t                histogram[3 * 256];
+/* PAYTON_CHECK_20120712 : sharpnessmap_mode -> stats_mode */
+       enum stats_mode         sharpnessMapMode;
+       /*sharpnessMap*/
+       enum stats_lowlightmode LowLightMode;
+       uint32_t lls_tuning_set_index;
+       uint32_t lls_brightness_index;
+};
+
+
+struct camera2_stats_sm {
+       uint8_t         availableFaceDetectModes[CAMERA2_MAX_AVAILABLE_MODE];
+       /*assuming supported modes = 3;*/
+       uint32_t        maxFaceCount;
+       uint32_t        histogramBucketCount;
+       uint32_t        maxHistogramCount;
+       uint32_t        sharpnessMapSize[2];
+       uint32_t        maxSharpnessMapValue;
+};
+
+/* android.control */
+
+enum aa_capture_intent {
+       AA_CAPTURE_INTENT_CUSTOM = 0,
+       AA_CAPTURE_INTENT_PREVIEW,
+       AA_CAPTURE_INTENT_STILL_CAPTURE,
+       AA_CAPTURE_INTENT_VIDEO_RECORD,
+       AA_CAPTURE_INTENT_VIDEO_SNAPSHOT,
+       AA_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
+       AA_CAPTURE_INTENT_STILL_CAPTURE_OIS_SINGLE,
+       AA_CAPTURE_INTENT_STILL_CAPTURE_OIS_MULTI
+};
+
+enum aa_mode {
+       AA_CONTROL_OFF = 1,
+       AA_CONTROL_AUTO,
+       AA_CONTROL_USE_SCENE_MODE
+};
+
+enum aa_scene_mode {
+       AA_SCENE_MODE_UNSUPPORTED = 1,
+       AA_SCENE_MODE_FACE_PRIORITY,
+       AA_SCENE_MODE_ACTION,
+       AA_SCENE_MODE_PORTRAIT,
+       AA_SCENE_MODE_LANDSCAPE,
+       AA_SCENE_MODE_NIGHT,
+       AA_SCENE_MODE_NIGHT_PORTRAIT,
+       AA_SCENE_MODE_THEATRE,
+       AA_SCENE_MODE_BEACH,
+       AA_SCENE_MODE_SNOW,
+       AA_SCENE_MODE_SUNSET,
+       AA_SCENE_MODE_STEADYPHOTO,
+       AA_SCENE_MODE_FIREWORKS,
+       AA_SCENE_MODE_SPORTS,
+       AA_SCENE_MODE_PARTY,
+       AA_SCENE_MODE_CANDLELIGHT,
+       AA_SCENE_MODE_BARCODE,
+       AA_SCENE_MODE_NIGHT_CAPTURE,
+       AA_SCENE_MODE_ANTISHAKE,
+       AA_SCENE_MODE_HDR,
+       AA_SCENE_MODE_LLS,
+       AA_SCENE_MODE_FDAE,
+       AA_SCENE_MODE_DUAL,
+       AA_SCENE_MODE_DRAMA,
+       AA_SCENE_MODE_ANIMATED,
+       AA_SCENE_MODE_PANORAMA,
+       AA_SCENE_MODE_GOLF,
+       AA_SCENE_MODE_PREVIEW,
+       AA_SCENE_MODE_VIDEO,
+       AA_SCENE_MODE_SLOWMOTION_2,
+       AA_SCENE_MODE_SLOWMOTION_4_8,
+       AA_SCENE_MODE_DUAL_PREVIEW,
+       AA_SCENE_MODE_DUAL_VIDEO,
+       AA_SCENE_MODE_120_PREVIEW,
+       AA_SCENE_MODE_LIGHT_TRACE
+};
+
+enum aa_effect_mode {
+       AA_EFFECT_OFF = 1,
+       AA_EFFECT_MONO,
+       AA_EFFECT_NEGATIVE,
+       AA_EFFECT_SOLARIZE,
+       AA_EFFECT_SEPIA,
+       AA_EFFECT_POSTERIZE,
+       AA_EFFECT_WHITEBOARD,
+       AA_EFFECT_BLACKBOARD,
+       AA_EFFECT_AQUA
+};
+
+enum aa_aemode {
+       AA_AEMODE_OFF = 1,
+       AA_AEMODE_LOCKED,
+       AA_AEMODE_CENTER,
+       AA_AEMODE_AVERAGE,
+       AA_AEMODE_MATRIX,
+       AA_AEMODE_SPOT,
+       AA_AEMODE_CENTER_TOUCH,
+       AA_AEMODE_AVERAGE_TOUCH,
+       AA_AEMODE_MATRIX_TOUCH,
+       AA_AEMODE_SPOT_TOUCH
+};
+
+enum aa_ae_flashmode {
+       /*all flash control stop*/
+       AA_FLASHMODE_OFF = 1,
+       /*flash start*/
+       AA_FLASHMODE_START,
+       /*flash cancle*/
+       AA_FLASHMODE_CANCLE,
+       /*internal 3A can control flash*/
+       AA_FLASHMODE_ON,
+       /*internal 3A can do auto flash algorithm*/
+       AA_FLASHMODE_AUTO,
+       /*internal 3A can fire flash by auto result*/
+       AA_FLASHMODE_CAPTURE,
+       /*internal 3A can control flash forced*/
+       AA_FLASHMODE_ON_ALWAYS
+};
+
+enum aa_ae_antibanding_mode {
+       AA_AE_ANTIBANDING_OFF = 1,
+       AA_AE_ANTIBANDING_50HZ,
+       AA_AE_ANTIBANDING_60HZ,
+       AA_AE_ANTIBANDING_AUTO,
+       AA_AE_ANTIBANDING_AUTO_50HZ,   /*50Hz + Auto*/
+       AA_AE_ANTIBANDING_AUTO_60HZ    /*60Hz + Auto*/
+};
+
+enum aa_awbmode {
+       AA_AWBMODE_OFF = 1,
+       AA_AWBMODE_LOCKED,
+       AA_AWBMODE_WB_AUTO,
+       AA_AWBMODE_WB_INCANDESCENT,
+       AA_AWBMODE_WB_FLUORESCENT,
+       AA_AWBMODE_WB_WARM_FLUORESCENT,
+       AA_AWBMODE_WB_DAYLIGHT,
+       AA_AWBMODE_WB_CLOUDY_DAYLIGHT,
+       AA_AWBMODE_WB_TWILIGHT,
+       AA_AWBMODE_WB_SHADE
+};
+
+enum aa_afmode {
+       /* These modes are adjusted immediatly */
+       AA_AFMODE_OFF = 1,
+       AA_AFMODE_SLEEP,
+       AA_AFMODE_INFINITY,
+       AA_AFMODE_MACRO,
+       AA_AFMODE_DELAYED_OFF,
+
+       /* Single AF. These modes are adjusted when afTrigger is changed from 0 to 1 */
+       AA_AFMODE_AUTO = 11,
+       AA_AFMODE_AUTO_MACRO,
+       AA_AFMODE_AUTO_VIDEO,
+       AA_AFMODE_AUTO_FACE,
+
+       /* Continuous AF. These modes are adjusted when afTrigger is changed from 0 to 1 */
+       AA_AFMODE_CONTINUOUS_PICTURE = 21,
+       AA_AFMODE_CONTINUOUS_VIDEO,
+       AA_AFMODE_CONTINUOUS_PICTURE_FACE,
+
+       /* Special modes for PDAF */
+       AA_AFMODE_PDAF_OUTFOCUSING = 31,
+       AA_AFMODE_PDAF_OUTFOCUSING_FACE,
+       AA_AFMODE_PDAF_OUTFOCUSING_CONTINUOUS_PICTURE,
+       AA_AFMODE_PDAF_OUTFOCUSING_CONTINUOUS_PICTURE_FACE,
+
+       /* Not supported yet */
+       AA_AFMODE_EDOF = 41,
+};
+
+/* camera2_aa_ctl.afRegions[4] */
+enum aa_afmode_ext {
+       AA_AFMODE_EXT_OFF = 1000,
+       /* Increase macro range for special app */
+       AA_AFMODE_EXT_ADVANCED_MACRO_FOCUS = 1001,
+       /* Set AF region for OCR */
+       AA_AFMODE_EXT_FOCUS_LOCATION = 1002,
+};
+
+enum aa_afstate {
+       AA_AFSTATE_INACTIVE = 1,
+       AA_AFSTATE_PASSIVE_SCAN,
+       AA_AFSTATE_ACTIVE_SCAN,
+       AA_AFSTATE_AF_ACQUIRED_FOCUS,
+       AA_AFSTATE_AF_FAILED_FOCUS
+};
+
+enum ae_state {
+       AE_STATE_INACTIVE = 1,
+       AE_STATE_SEARCHING,
+       AE_STATE_CONVERGED,
+       AE_STATE_LOCKED,
+       AE_STATE_FLASH_REQUIRED,
+       AE_STATE_PRECAPTURE
+};
+
+enum awb_state {
+       AWB_STATE_INACTIVE = 1,
+       AWB_STATE_SEARCHING,
+       AWB_STATE_CONVERGED,
+       AWB_STATE_LOCKED
+};
+
+enum aa_isomode {
+       AA_ISOMODE_AUTO = 1,
+       AA_ISOMODE_MANUAL,
+};
+
+struct camera2_aa_ctl {
+       enum aa_capture_intent          captureIntent;
+       enum aa_mode                    mode;
+       /*enum aa_effect_mode           effectMode;*/
+       enum aa_scene_mode              sceneMode;
+       uint32_t                        videoStabilizationMode;
+       enum aa_aemode                  aeMode;
+       uint32_t                        aeRegions[5];
+       /*5 per region(x1,y1,x2,y2,weight). currently assuming 1 region.*/
+       int32_t                         aeExpCompensation;
+       uint32_t                        aeTargetFpsRange[2];
+       enum aa_ae_antibanding_mode     aeAntibandingMode;
+       enum aa_ae_flashmode            aeflashMode;
+       enum aa_awbmode                 awbMode;
+       uint32_t                        awbRegions[5];
+       /*5 per region(x1,y1,x2,y2,weight). currently assuming 1 region.*/
+       enum aa_afmode                  afMode;
+       uint32_t                        afRegions[5];
+       /*5 per region(x1,y1,x2,y2,weight). currently assuming 1 region.*/
+       uint32_t                        afTrigger;
+       enum aa_isomode                 isoMode;
+       uint32_t                        isoValue;
+       int32_t                 awbValue;
+       uint32_t                        reserved[10];
+};
+
+struct camera2_aa_dm {
+       enum aa_mode                            mode;
+       enum aa_effect_mode                     effectMode;
+       enum aa_scene_mode                      sceneMode;
+       uint32_t                                videoStabilizationMode;
+       enum aa_aemode                          aeMode;
+       /*needs check*/
+       uint32_t                                aeRegions[5];
+       /*5 per region(x1,y1,x2,y2,weight). currently assuming 1 region.*/
+       enum ae_state                           aeState;
+       enum aa_ae_flashmode                    aeflashMode;
+       /*needs check*/
+       enum aa_awbmode                         awbMode;
+       uint32_t                                awbRegions[5];
+       enum awb_state                          awbState;
+       /*5 per region(x1,y1,x2,y2,weight). currently assuming 1 region.*/
+       enum aa_afmode                          afMode;
+       uint32_t                                afRegions[5];
+       /*5 per region(x1,y1,x2,y2,weight). currently assuming 1 region*/
+       enum aa_afstate                         afState;
+       enum aa_isomode                         isoMode;
+       uint32_t                                isoValue;
+       uint32_t                                reserved[10];
+};
+
+struct camera2_aa_sm {
+       uint8_t         availableSceneModes[CAMERA2_MAX_AVAILABLE_MODE];
+       uint8_t         availableEffects[CAMERA2_MAX_AVAILABLE_MODE];
+       /*assuming # of available scene modes = 10*/
+       uint32_t        maxRegions;
+       uint8_t         aeAvailableModes[CAMERA2_MAX_AVAILABLE_MODE];
+       /*assuming # of available ae modes = 8*/
+       struct rational aeCompensationStep;
+       int32_t         aeCompensationRange[2];
+       uint32_t aeAvailableTargetFpsRanges[CAMERA2_MAX_AVAILABLE_MODE][2];
+       uint8_t         aeAvailableAntibandingModes[CAMERA2_MAX_AVAILABLE_MODE];
+       uint8_t         awbAvailableModes[CAMERA2_MAX_AVAILABLE_MODE];
+       /*assuming # of awbAvailableModes = 10*/
+       uint8_t         afAvailableModes[CAMERA2_MAX_AVAILABLE_MODE];
+       /*assuming # of afAvailableModes = 4*/
+       uint8_t availableVideoStabilizationModes[4];
+       /*assuming # of availableVideoStabilizationModes = 4*/
+       uint32_t        isoRange[2];
+};
+
+struct camera2_lens_usm {
+       /** Frame delay between sending command and applying frame data */
+       uint32_t        focusDistanceFrameDelay;
+};
+
+struct camera2_sensor_usm {
+       /** Frame delay between sending command and applying frame data */
+       uint32_t        exposureTimeFrameDelay;
+       uint32_t        frameDurationFrameDelay;
+       uint32_t        sensitivityFrameDelay;
+};
+
+struct camera2_flash_usm {
+       /** Frame delay between sending command and applying frame data */
+       uint32_t        flashModeFrameDelay;
+       uint32_t        firingPowerFrameDelay;
+       uint64_t        firingTimeFrameDelay;
+};
+
+struct camera2_ctl {
+       struct camera2_request_ctl              request;
+       struct camera2_lens_ctl                 lens;
+       struct camera2_sensor_ctl               sensor;
+       struct camera2_flash_ctl                flash;
+       struct camera2_hotpixel_ctl             hotpixel;
+       struct camera2_demosaic_ctl             demosaic;
+       struct camera2_noisereduction_ctl       noise;
+       struct camera2_shading_ctl              shading;
+       struct camera2_geometric_ctl            geometric;
+       struct camera2_colorcorrection_ctl      color;
+       struct camera2_tonemap_ctl              tonemap;
+       struct camera2_edge_ctl                 edge;
+       struct camera2_scaler_ctl               scaler;
+       struct camera2_jpeg_ctl                 jpeg;
+       struct camera2_stats_ctl                stats;
+       struct camera2_aa_ctl                   aa;
+       struct camera2_entry_ctl                entry;
+};
+
+struct camera2_dm {
+       struct camera2_request_dm               request;
+       struct camera2_lens_dm                  lens;
+       struct camera2_sensor_dm                sensor;
+       struct camera2_flash_dm                 flash;
+       struct camera2_hotpixel_dm              hotpixel;
+       struct camera2_demosaic_dm              demosaic;
+       struct camera2_noisereduction_dm        noise;
+       struct camera2_shading_dm               shading;
+       struct camera2_geometric_dm             geometric;
+       struct camera2_colorcorrection_dm       color;
+       struct camera2_tonemap_dm               tonemap;
+       struct camera2_edge_dm                  edge;
+       struct camera2_scaler_dm                scaler;
+       struct camera2_jpeg_dm                  jpeg;
+       struct camera2_stats_dm                 stats;
+       struct camera2_aa_dm                    aa;
+       struct camera2_entry_dm                 entry;
+};
+
+struct camera2_sm {
+       struct camera2_lens_sm                  lens;
+       struct camera2_sensor_sm                sensor;
+       struct camera2_flash_sm                 flash;
+       struct camera2_colorcorrection_sm       color;
+       struct camera2_tonemap_sm               tonemap;
+       struct camera2_scaler_sm                scaler;
+       struct camera2_jpeg_sm                  jpeg;
+       struct camera2_stats_sm                 stats;
+       struct camera2_aa_sm                    aa;
+
+       /** User-defined(ispfw specific) static metadata. */
+       struct camera2_lens_usm                 lensUd;
+       struct camera2_sensor_usm               sensorUd;
+       struct camera2_flash_usm                flashUd;
+};
+
+/** \brief
+       User-defined control for lens.
+*/
+struct camera2_lens_uctl {
+       struct camera2_lens_ctl ctl;
+
+       /** It depends by posSize */
+       uint32_t        pos;
+       /** It depends by af algorithm(AF pos bit. normally 8 or 9 or 10) */
+       uint32_t        posSize;
+       /** It depends by af algorithm */
+       uint32_t        direction;
+       /** Some actuator support slew rate control. */
+       uint32_t        slewRate;
+};
+
+/** \brief
+       User-defined metadata for lens.
+*/
+struct camera2_lens_udm {
+       /** It depends by posSize */
+       uint32_t        pos;
+       /** It depends by af algorithm(AF pos bit. normally 8 or 9 or 10) */
+       uint32_t        posSize;
+       /** It depends by af algorithm */
+       uint32_t        direction;
+       /** Some actuator support slew rate control. */
+       uint32_t        slewRate;
+};
+
+/** \brief
+ User-defined metadata for ae.
+*/
+struct camera2_ae_udm {
+       /** vendor specific length */
+       uint32_t        vsLength;
+       /** vendor specific data array */
+       uint32_t        vendorSpecific[CAMERA2_MAX_VENDER_LENGTH];
+};
+
+/** \brief
+ User-defined metadata for awb.
+*/
+struct camera2_awb_udm {
+       /** vendor specific length */
+       uint32_t        vsLength;
+       /** vendor specific data array */
+       uint32_t        vendorSpecific[CAMERA2_MAX_VENDER_LENGTH];
+};
+
+/** \brief
+ User-defined metadata for af.
+*/
+struct camera2_af_udm {
+       /** vendor specific length */
+       uint32_t        vsLength;
+       /** vendor specific data array */
+       uint32_t        vendorSpecific[CAMERA2_MAX_VENDER_LENGTH];
+       int32_t         lensPositionInfinity;
+       int32_t         lensPositionMacro;
+       int32_t         lensPositionCurrent;
+};
+
+/** \brief
+ User-defined metadata for anti-shading.
+*/
+struct camera2_as_udm {
+       /** vendor specific length */
+       uint32_t vsLength;
+       /** vendor specific data array */
+       uint32_t vendorSpecific[CAMERA2_MAX_VENDER_LENGTH];
+};
+
+/** \brief
+ User-defined metadata for anti-shading.
+*/
+struct camera2_ipc_udm {
+       /** vendor specific length */
+       uint32_t vsLength;
+       /** vendor specific data array */
+       uint32_t vendorSpecific[CAMERA2_MAX_VENDER_LENGTH];
+};
+
+/** \brief
+ User-defined metadata for aa.
+*/
+struct camera2_internal_udm {
+       /** vendor specific data array */
+       uint32_t vendorSpecific1[CAMERA2_MAX_VENDER_LENGTH];
+       uint32_t vendorSpecific2[CAMERA2_MAX_VENDER_LENGTH];
+       /*
+        * vendorSpecific2[0] : info
+        * vendorSpecific2[100] : 0:sirc 1:cml
+        * vendorSpecific2[101] : cml exposure
+        * vendorSpecific2[102] : cml iso(gain)
+        * vendorSpecific2[103] : cml Bv
+        */
+};
+
+/** \brief
+       User-defined control for sensor.
+*/
+struct camera2_sensor_uctl {
+       struct camera2_sensor_ctl ctl;
+       /** Dynamic frame duration.
+       This feature is decided to max. value between
+       'sensor.exposureTime'+alpha and 'sensor.frameDuration'.
+       */
+       uint64_t        dynamicFrameDuration;
+       uint32_t        analogGain;
+       uint32_t        digitalGain;
+       uint64_t        longExposureTime; /* For supporting WDR */
+       uint64_t        shortExposureTime;
+       uint32_t        longAnalogGain;
+       uint32_t        shortAnalogGain;
+       uint32_t        longDigitalGain;
+       uint32_t        shortDigitalGain;
+};
+
+struct camera2_scaler_uctl {
+       /** \brief
+       target address for next frame.
+       \remarks
+       [0] invalid address, stop
+       [others] valid address
+       */
+       uint32_t sccTargetAddress[4];
+       uint32_t scpTargetAddress[4];
+       uint32_t disTargetAddress[4];
+       uint32_t taapTargetAddress[4]; /* 3AA preview DMA */
+       uint32_t taacTargetAddress[4]; /* 3AA capture DMA */
+       uint32_t orientation;
+};
+
+struct camera2_flash_uctl {
+       struct camera2_flash_ctl ctl;
+};
+
+struct camera2_bayer_uctl {
+       struct camera2_scaler_ctl ctl;
+};
+
+enum companion_drc_mode {
+       COMPANION_DRC_OFF = 1,
+       COMPANION_DRC_ON,
+};
+
+enum companion_wdr_mode {
+       COMPANION_WDR_OFF = 1,
+       COMPANION_WDR_ON,
+};
+
+enum companion_paf_mode {
+       COMPANION_PAF_OFF = 1,
+       COMPANION_PAF_ON,
+};
+
+enum companion_bypass_mode {
+       COMPANION_FULL_BYPASS_OFF = 1,
+       COMPANION_FULL_BYPASS_ON,
+};
+
+enum companion_lsc_mode {
+       COMPANION_LSC_OFF = 1,
+       COMPANION_LSC_ON,
+};
+
+struct camera2_companion_uctl {
+       enum companion_drc_mode drc_mode;
+       enum companion_wdr_mode wdr_mode;
+       enum companion_paf_mode paf_mode;
+};
+
+struct camera2_bayer_udm {
+       uint32_t        width;
+       uint32_t        height;
+};
+
+struct camera2_pdaf_single_result {
+       uint16_t        mode;
+       uint16_t        goalPos;
+       uint16_t        reliability;
+       uint16_t        currentPos;
+};
+
+struct camera2_pdaf_multi_result {
+       uint16_t        mode;
+       uint16_t        goalPos;
+       uint16_t        reliability;
+};
+
+struct camera2_pdaf_udm {
+       uint16_t                                numCol; /* width of PDAF map, 0 means no multi PDAF data */
+       uint16_t                                numRow; /* height of PDAF map, 0 means no multi PDAF data */
+       struct camera2_pdaf_multi_result        multiResult[CAMERA2_MAX_PDAF_MULTIROI_COLUMN][CAMERA2_MAX_PDAF_MULTIROI_ROW];
+       struct camera2_pdaf_single_result       singleResult;
+       uint16_t                                lensPosResolution;      /* 1023(unsigned 10bit) */
+};
+
+struct camera2_companion_udm {
+       enum companion_drc_mode drc_mode;
+       enum companion_wdr_mode wdr_mode;
+       enum companion_paf_mode paf_mode;
+       struct camera2_pdaf_udm pdaf;
+};
+
+/** \brief
+       User-defined control area.
+    \remarks
+       sensor, lens, flash category is empty value.
+       It should be filled by a5 for SET_CAM_CONTROL command.
+       Other category is filled already from host.
+*/
+struct camera2_uctl {
+       /** \brief
+       Set sensor, lens, flash control for next frame.
+       \remarks
+       This flag can be combined.
+       [0 bit] lens
+       [1 bit] sensor
+       [2 bit] flash
+       */
+       uint32_t uUpdateBitMap;
+
+       /** For debugging */
+       uint32_t uFrameNumber;
+
+       /** ispfw specific control(user-defined) of lens. */
+       struct camera2_lens_uctl        lensUd;
+       /** ispfw specific control(user-defined) of sensor. */
+       struct camera2_sensor_uctl      sensorUd;
+       /** ispfw specific control(user-defined) of flash. */
+       struct camera2_flash_uctl       flashUd;
+
+       struct camera2_scaler_uctl      scalerUd;
+       /** ispfw specific control(user-defined) of Bcrop1. */
+       struct camera2_bayer_uctl       bayerUd;
+       struct camera2_companion_uctl   companionUd;
+       uint32_t        reserved[10];
+};
+
+struct camera2_udm {
+       struct camera2_lens_udm         lens;
+       struct camera2_ae_udm           ae;
+       struct camera2_awb_udm          awb;
+       struct camera2_af_udm           af;
+       struct camera2_as_udm           as;
+       struct camera2_ipc_udm          ipc;
+       /* KJ_121129 : Add udm for sirc sdk. */
+       struct camera2_internal_udm     internal;
+       /* Add udm for bayer down size. */
+       struct camera2_bayer_udm        bayer;
+       struct camera2_companion_udm    companion;
+       uint32_t        reserved[10];
+};
+
+struct camera2_shot {
+       /*google standard area*/
+       struct camera2_ctl      ctl;
+       struct camera2_dm       dm;
+       /*user defined area*/
+       struct camera2_uctl     uctl;
+       struct camera2_udm      udm;
+       /*magic : 23456789*/
+       uint32_t                magicNumber;
+};
+
+struct camera2_node_input {
+       /**     \brief
+               intput crop region
+               \remarks
+               [0] x axis
+               [1] y axie
+               [2] width
+               [3] height
+       */
+       uint32_t        cropRegion[4];
+};
+
+struct camera2_node_output {
+       /**     \brief
+               output crop region
+               \remarks
+               [0] x axis
+               [1] y axie
+               [2] width
+               [3] height
+       */
+       uint32_t        cropRegion[4];
+};
+
+struct camera2_node {
+       /**     \brief
+               video node id
+               \remarks
+               [x] video node id
+       */
+       uint32_t                        vid;
+
+       /**     \brief
+               stream control
+               \remarks
+               [0] disable stream out
+               [1] enable stream out
+       */
+       uint32_t                        request;
+
+       struct camera2_node_input       input;
+       struct camera2_node_output      output;
+};
+
+struct camera2_node_group {
+       /**     \brief
+               output device node
+               \remarks
+               this node can pull in image
+       */
+       struct camera2_node             leader;
+
+       /**     \brief
+               capture node list
+               \remarks
+               this node can get out image
+               3AAC, 3AAP, SCC, SCP, VDISC
+       */
+       struct camera2_node             capture[CAPTURE_NODE_MAX];
+};
+
+/** \brief
+       Structure for interfacing between HAL and driver.
+*/
+struct camera2_shot_ext {
+       /*
+        * ---------------------------------------------------------------------
+        * HAL Control Part
+        * ---------------------------------------------------------------------
+        */
+
+       /**     \brief
+               setfile change
+               \remarks
+               [x] mode for setfile
+       */
+       uint32_t                        setfile;
+
+       /**     \brief
+               node group control
+               \remarks
+               per frame control
+       */
+       struct camera2_node_group       node_group;
+
+       /**     \brief
+               post processing control(DRC)
+               \remarks
+               [0] bypass off
+               [1] bypass on
+       */
+       uint32_t                        drc_bypass;
+
+       /**     \brief
+               post processing control(DIS)
+               \remarks
+               [0] bypass off
+               [1] bypass on
+       */
+       uint32_t                        dis_bypass;
+
+       /**     \brief
+               post processing control(3DNR)
+               \remarks
+               [0] bypass off
+               [1] bypass on
+       */
+       uint32_t                        dnr_bypass;
+
+       /**     \brief
+               post processing control(FD)
+               \remarks
+               [0] bypass off
+               [1] bypass on
+       */
+       uint32_t                        fd_bypass;
+
+       /*
+        * ---------------------------------------------------------------------
+        * DRV Control Part
+        * ---------------------------------------------------------------------
+        */
+
+       /**     \brief
+               requested frames state.
+               driver return the information everytime
+               when dequeue is requested.
+               \remarks
+               [X] count
+       */
+       uint32_t                        free_cnt;
+       uint32_t                        request_cnt;
+       uint32_t                        process_cnt;
+       uint32_t                        complete_cnt;
+
+       /* reserved for future */
+       uint32_t                        reserved[15];
+
+       /**     \brief
+               processing time debugging
+               \remarks
+               taken time(unit : struct timeval)
+               [0][x] flite start
+               [1][x] flite end
+               [2][x] DRV Shot
+               [3][x] DRV Shot done
+               [4][x] DRV Meta done
+       */
+       uint32_t                        timeZone[10][2];
+
+       /*
+        * ---------------------------------------------------------------------
+        * Camera API
+        * ---------------------------------------------------------------------
+        */
+
+       struct camera2_shot             shot;
+};
+
+/** \brief
+       stream structure for scaler.
+*/
+struct camera2_stream {
+       /**     \brief
+               this address for verifying conincidence of index and address
+               \remarks
+               [X] kernel virtual address for this buffer
+       */
+       uint32_t                address;
+
+       /**     \brief
+               this frame count is from FLITE through dm.request.fcount,
+               this count increases every frame end. initial value is 1.
+               \remarks
+               [X] frame count
+       */
+       uint32_t                fcount;
+
+       /**     \brief
+               this request count is from HAL through ctl.request.fcount,
+               this count is the unique.
+               \remarks
+               [X] request count
+       */
+       uint32_t                rcount;
+
+       /**     \brief
+               frame index of isp framemgr.
+               this value is for driver internal debugging
+               \remarks
+               [X] frame index
+       */
+       uint32_t                findex;
+
+       /**     \brief
+               frame validation of isp framemgr.
+               this value is for driver and HAL internal debugging
+               \remarks
+               [X] frame valid
+       */
+       uint32_t                fvalid;
+
+       /**     \brief
+               output crop region
+               this value mean the output image places the axis of  memory space
+               \remarks
+               [0] crop x axis
+               [1] crop y axis
+               [2] width
+               [3] height
+       */
+       uint32_t                input_crop_region[4];
+       uint32_t                output_crop_region[4];
+};
+
+#define CAM_LENS_CMD           (0x1 << 0x0)
+#define CAM_SENSOR_CMD         (0x1 << 0x1)
+#define CAM_FLASH_CMD          (0x1 << 0x2)
+
+/* typedefs below are for firmware sources */
+
+typedef enum metadata_mode metadata_mode_t;
+typedef struct camera2_request_ctl camera2_request_ctl_t;
+typedef struct camera2_request_dm camera2_request_dm_t;
+typedef enum optical_stabilization_mode optical_stabilization_mode_t;
+typedef enum lens_facing lens_facing_t;
+typedef struct camera2_entry_ctl camera2_entry_ctl_t;
+typedef struct camera2_entry_dm camera2_entry_dm_t;
+typedef struct camera2_lens_ctl camera2_lens_ctl_t;
+typedef struct camera2_lens_dm camera2_lens_dm_t;
+typedef struct camera2_lens_sm camera2_lens_sm_t;
+typedef enum sensor_colorfilterarrangement sensor_colorfilterarrangement_t;
+typedef enum sensor_ref_illuminant sensor_ref_illuminant_t;
+typedef struct camera2_sensor_ctl camera2_sensor_ctl_t;
+typedef struct camera2_sensor_dm camera2_sensor_dm_t;
+typedef struct camera2_sensor_sm camera2_sensor_sm_t;
+typedef enum flash_mode flash_mode_t;
+typedef struct camera2_flash_ctl camera2_flash_ctl_t;
+typedef struct camera2_flash_dm camera2_flash_dm_t;
+typedef struct camera2_flash_sm camera2_flash_sm_t;
+typedef enum processing_mode processing_mode_t;
+typedef struct camera2_hotpixel_ctl camera2_hotpixel_ctl_t;
+typedef struct camera2_hotpixel_dm camera2_hotpixel_dm_t;
+
+typedef struct camera2_demosaic_ctl camera2_demosaic_ctl_t;
+typedef struct camera2_demosaic_dm camera2_demosaic_dm_t;
+typedef struct camera2_noisereduction_ctl camera2_noisereduction_ctl_t;
+typedef struct camera2_noisereduction_dm camera2_noisereduction_dm_t;
+typedef struct camera2_shading_ctl camera2_shading_ctl_t;
+typedef struct camera2_shading_dm camera2_shading_dm_t;
+typedef struct camera2_geometric_ctl camera2_geometric_ctl_t;
+typedef struct camera2_geometric_dm camera2_geometric_dm_t;
+typedef enum colorcorrection_mode colorcorrection_mode_t;
+typedef struct camera2_colorcorrection_ctl camera2_colorcorrection_ctl_t;
+typedef struct camera2_colorcorrection_dm camera2_colorcorrection_dm_t;
+typedef struct camera2_colorcorrection_sm camera2_colorcorrection_sm_t;
+typedef enum tonemap_mode tonemap_mode_t;
+typedef struct camera2_tonemap_ctl camera2_tonemap_ctl_t;
+typedef struct camera2_tonemap_dm camera2_tonemap_dm_t;
+typedef struct camera2_tonemap_sm camera2_tonemap_sm_t;
+
+typedef struct camera2_edge_ctl camera2_edge_ctl_t;
+typedef struct camera2_edge_dm camera2_edge_dm_t;
+typedef enum scaler_availableformats scaler_availableformats_t;
+typedef struct camera2_scaler_ctl camera2_scaler_ctl_t;
+typedef struct camera2_scaler_dm camera2_scaler_dm_t;
+typedef struct camera2_jpeg_ctl camera2_jpeg_ctl_t;
+typedef struct camera2_jpeg_dm camera2_jpeg_dm_t;
+typedef struct camera2_jpeg_sm camera2_jpeg_sm_t;
+typedef enum facedetect_mode facedetect_mode_t;
+typedef enum stats_mode stats_mode_t;
+typedef struct camera2_stats_ctl camera2_stats_ctl_t;
+typedef struct camera2_stats_dm camera2_stats_dm_t;
+typedef struct camera2_stats_sm camera2_stats_sm_t;
+typedef enum aa_capture_intent aa_capture_intent_t;
+typedef enum aa_mode aa_mode_t;
+typedef enum aa_scene_mode aa_scene_mode_t;
+typedef enum aa_effect_mode aa_effect_mode_t;
+typedef enum aa_aemode aa_aemode_t;
+typedef enum aa_ae_antibanding_mode aa_ae_antibanding_mode_t;
+typedef enum aa_awbmode aa_awbmode_t;
+typedef enum aa_afmode aa_afmode_t;
+typedef enum aa_afstate aa_afstate_t;
+typedef struct camera2_aa_ctl camera2_aa_ctl_t;
+typedef struct camera2_aa_dm camera2_aa_dm_t;
+typedef struct camera2_aa_sm camera2_aa_sm_t;
+typedef struct camera2_lens_usm camera2_lens_usm_t;
+typedef struct camera2_sensor_usm camera2_sensor_usm_t;
+typedef struct camera2_flash_usm camera2_flash_usm_t;
+typedef struct camera2_ctl camera2_ctl_t;
+typedef struct camera2_uctl camera2_uctl_t;
+typedef struct camera2_dm camera2_dm_t;
+typedef struct camera2_sm camera2_sm_t;
+
+typedef struct camera2_scaler_sm camera2_scaler_sm_t;
+typedef struct camera2_scaler_uctl camera2_scaler_uctl_t;
+
+typedef struct camera2_sensor_uctl camera2_sensor_uctl_t;
+typedef struct camera2_lens_uctl camera2_lens_uctl_t;
+typedef struct camera2_lens_udm camera2_lens_udm_t;
+
+typedef struct camera2_ae_udm camera2_ae_udm_t;
+typedef struct camera2_awb_udm camera2_awb_udm_t;
+typedef struct camera2_af_udm camera2_af_udm_t;
+typedef struct camera2_as_udm camera2_as_udm_t;
+typedef struct camera2_ipc_udm camera2_ipc_udm_t;
+typedef struct camera2_internal_udm camera2_internal_udm_t;
+
+typedef struct camera2_flash_uctl camera2_flash_uctl_t;
+
+typedef struct camera2_shot camera2_shot_t;
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-ncp6335b.c b/drivers/media/platform/exynos/fimc-is/fimc-is-ncp6335b.c
new file mode 100644 (file)
index 0000000..015ba00
--- /dev/null
@@ -0,0 +1,112 @@
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include "fimc-is-ncp6335b.h"
+
+/**
+ * NCP6335B Vout Tables
+ */
+static const struct ncp6335b_vout vout_tables[] = {
+       {0, NCP6335B_VOUT_1P000, "1.000"}, /* defualt voltage */
+       {1, NCP6335B_VOUT_0P875, "0.875"},
+       {2, NCP6335B_VOUT_0P900, "0.900"},
+       {3, NCP6335B_VOUT_0P925, "0.925"},
+       {4, NCP6335B_VOUT_0P950, "0.950"},
+       {5, NCP6335B_VOUT_0P975, "0.975"},
+       {6, NCP6335B_VOUT_1P000, "1.000"},
+};
+
+/**
+ * ncp6335b_get_vout_val: get i2c register value to set vout of dcdc regulator.
+ */
+int ncp6335b_get_vout_val(int sel)
+{
+       int i, vout = vout_tables[0].val;
+
+       if (sel < 0)
+               pr_err("%s: error, invalid sel %d\n", __func__, sel);
+
+       for (i = 0; ARRAY_SIZE(vout_tables); i++) {
+               if (vout_tables[i].sel == sel) {
+                       return vout_tables[i].val;
+               }
+       }
+
+       pr_err("%s: warning, default voltage selected. sel %d\n", __func__, sel);
+
+       return vout;
+}
+
+/**
+ * ncp6335b_get_vout_name: get voltage name of vout as string.
+ */
+const char *ncp6335b_get_vout_str(int sel)
+{
+       const char *vout = vout_tables[0].vout;
+       int i;
+
+       if (sel < 0)
+               pr_err("%s: error, invalid sel %d\n", __func__, sel);
+
+       for (i = 0; ARRAY_SIZE(vout_tables); i++) {
+               if (vout_tables[i].sel == sel) {
+                       return vout_tables[i].vout;
+               }
+       }
+
+       pr_err("%s: warning, default voltage selected. sel %d\n", __func__, sel);
+
+       return vout;
+}
+
+/**
+ * ncp6335b_set_voltage: set dcdc vout with i2c register value.
+ */
+int ncp6335b_set_voltage(struct i2c_client *client, int vout)
+{
+       int ret = i2c_smbus_write_byte_data(client, 0x14, 0x00);
+       if (ret < 0)
+               pr_err("[%s::%d] Write Error [%d]\n", __func__, __LINE__, ret);
+
+       ret = i2c_smbus_write_byte_data(client, 0x10, vout); /* 1.05V -> 1V (0xC0) */
+       if (ret < 0)
+               pr_err("[%s::%d] Write Error [%d]. vout 0x%X\n", __func__, __LINE__, ret, vout);
+
+       ret = i2c_smbus_write_byte_data(client, 0x11, vout); /* 1.05V -> 1V (0xC0) */
+       if (ret < 0)
+               pr_err("[%s::%d] Write Error [%d]. vout 0x%X\n", __func__, __LINE__, ret, vout);
+
+       /*pr_info("%s: vout 0x%X\n", __func__, vout);*/
+
+       return ret;
+}
+
+int ncp6335b_read_voltage(struct i2c_client *client)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(client, 0x3);
+       if (ret < 0)
+               pr_err("[%s::%d]Read Error [%d]\n", __func__, __LINE__, ret);
+       pr_err("[%s::%d]NCP6335B PID[%x]\n", __func__, __LINE__, ret);
+
+       ret = i2c_smbus_read_byte_data(client, 0x10);
+       if (ret < 0)
+               pr_err("[%s::%d]Read Error [%d]\n", __func__, __LINE__, ret);
+       pr_err("[%s::%d]NCP6335B [0x10 Read :: %x]\n", __func__, __LINE__, ret);
+
+       ret = i2c_smbus_read_byte_data(client, 0x11);
+       if (ret < 0)
+               pr_err("[%s::%d]Read Error [%d]\n", __func__, __LINE__, ret);
+       pr_err("[%s::%d]NCP6335B [0x11 Read :: %x]\n", __func__, __LINE__, ret);
+
+       ret = i2c_smbus_read_byte_data(client, 0x14);
+       if (ret < 0)
+               pr_err("[%s::%d]Read Error [%d]\n", __func__, __LINE__, ret);
+       pr_err("[%s::%d]NCP6335B [0x14 Read :: %x]\n", __func__, __LINE__, ret);
+
+       return ret;
+}
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-ncp6335b.h b/drivers/media/platform/exynos/fimc-is/fimc-is-ncp6335b.h
new file mode 100644 (file)
index 0000000..eeab7d6
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is core functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "fimc-is-core.h"
+
+enum{
+       NCP6335B_VOUT_0P875 = 0xAC,
+       NCP6335B_VOUT_0P900 = 0xB0,
+       NCP6335B_VOUT_0P925 = 0xB4,
+       NCP6335B_VOUT_0P950 = 0xB8,
+       NCP6335B_VOUT_0P975 = 0xBC,
+       NCP6335B_VOUT_1P000 = 0xC0,
+};
+
+struct ncp6335b_vout {
+       int sel;        /* selector, unique value for vout entry and indepedant to dcdc vendor */
+       int val;        /* dcdc-specific value for vout register */
+       char vout[7];   /* voltage level string */
+};
+
+int ncp6335b_get_vout_val(int sel);
+const char *ncp6335b_get_vout_str(int sel);
+int ncp6335b_set_voltage(struct i2c_client *client, int vout);
+int ncp6335b_read_voltage(struct i2c_client *client);
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-param.h b/drivers/media/platform/exynos/fimc-is/fimc-is-param.h
new file mode 100644 (file)
index 0000000..2ccf086
--- /dev/null
@@ -0,0 +1,1445 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_PARAMS_H
+#define FIMC_IS_PARAMS_H
+
+#define IS_REGION_VER 150  /* IS REGION VERSION 1.50 */
+
+/* MACROs */
+#define IS_SET_PARAM_BIT(dev, num) \
+       (num >= 32 ? set_bit((num-32), &dev->p_region_index2) \
+               : set_bit(num, &dev->p_region_index1))
+#define IS_INC_PARAM_NUM(dev)          atomic_inc(&dev->p_region_num)
+
+#define IS_PARAM_GLOBAL(dev)           (dev->is_p_region->parameter.global)
+#define IS_PARAM_ISP(dev)              (dev->is_p_region->parameter.isp)
+#define IS_PARAM_DRC(dev)              (dev->is_p_region->parameter.drc)
+#define IS_PARAM_FD(dev)               (dev->is_p_region->parameter.fd)
+#define IS_HEADER(dev)                 (dev->is_p_region->header)
+#define IS_FACE(dev)                   (dev->is_p_region->face)
+#define IS_SHARED(dev)                 (dev->is_shared_region)
+#define IS_PARAM_SIZE                  (FIMC_IS_REGION_SIZE + 1)
+
+#ifndef BIT0
+#define  BIT0     0x00000001
+#define  BIT1     0x00000002
+#define  BIT2     0x00000004
+#define  BIT3     0x00000008
+#define  BIT4     0x00000010
+#define  BIT5     0x00000020
+#define  BIT6     0x00000040
+#define  BIT7     0x00000080
+#define  BIT8     0x00000100
+#define  BIT9     0x00000200
+#define  BIT10    0x00000400
+#define  BIT11    0x00000800
+#define  BIT12    0x00001000
+#define  BIT13    0x00002000
+#define  BIT14    0x00004000
+#define  BIT15    0x00008000
+#define  BIT16    0x00010000
+#define  BIT17    0x00020000
+#define  BIT18    0x00040000
+#define  BIT19    0x00080000
+#define  BIT20    0x00100000
+#define  BIT21    0x00200000
+#define  BIT22    0x00400000
+#define  BIT23    0x00800000
+#define  BIT24    0x01000000
+#define  BIT25    0x02000000
+#define  BIT26    0x04000000
+#define  BIT27    0x08000000
+#define  BIT28    0x10000000
+#define  BIT29    0x20000000
+#define  BIT30    0x40000000
+#define  BIT31    0x80000000
+#define  BIT32    0x0000000100000000ULL
+#define  BIT33    0x0000000200000000ULL
+#define  BIT34    0x0000000400000000ULL
+#define  BIT35    0x0000000800000000ULL
+#define  BIT36    0x0000001000000000ULL
+#define  BIT37    0x0000002000000000ULL
+#define  BIT38    0x0000004000000000ULL
+#define  BIT39    0x0000008000000000ULL
+#define  BIT40    0x0000010000000000ULL
+#define  BIT41    0x0000020000000000ULL
+#define  BIT42    0x0000040000000000ULL
+#define  BIT43    0x0000080000000000ULL
+#define  BIT44    0x0000100000000000ULL
+#define  BIT45    0x0000200000000000ULL
+#define  BIT46    0x0000400000000000ULL
+#define  BIT47    0x0000800000000000ULL
+#define  BIT48    0x0001000000000000ULL
+#define  BIT49    0x0002000000000000ULL
+#define  BIT50    0x0004000000000000ULL
+#define  BIT51    0x0008000000000000ULL
+#define  BIT52    0x0010000000000000ULL
+#define  BIT53    0x0020000000000000ULL
+#define  BIT54    0x0040000000000000ULL
+#define  BIT55    0x0080000000000000ULL
+#define  BIT56    0x0100000000000000ULL
+#define  BIT57    0x0200000000000000ULL
+#define  BIT58    0x0400000000000000ULL
+#define  BIT59    0x0800000000000000ULL
+#define  BIT60    0x1000000000000000ULL
+#define  BIT61    0x2000000000000000ULL
+#define  BIT62    0x4000000000000000ULL
+#define  BIT63    0x8000000000000000ULL
+#define  INC_BIT(bit) (bit<<1)
+#define  INC_NUM(bit) (bit + 1)
+#endif
+
+#define MAGIC_NUMBER 0x01020304
+
+#define PARAMETER_MAX_SIZE    128  /* in byte */
+#define PARAMETER_MAX_MEMBER  (PARAMETER_MAX_SIZE/4)
+
+enum is_entry {
+       ENTRY_GLOBAL,
+       ENTRY_BUFFER,
+       ENTRY_SENSOR,
+       ENTRY_3AA,
+       ENTRY_ISP,
+       ENTRY_DRC,
+       ENTRY_SCALERC,
+       ENTRY_DIS,
+       ENTRY_TDNR,
+       ENTRY_SCALERP,
+       ENTRY_LHFD,
+       ENTRY_3AAC,
+       ENTRY_3AAP,
+       ENTRY_END
+};
+
+#define ADDRESS_TO_OFFSET(start, end)  ((uint32)end - (uint32)start)
+#define OFFSET_TO_NUM(offset)          ((offset)>>6)
+#define IS_OFFSET_LOWBIT(offset)       (OFFSET_TO_NUM(offset) >= \
+                                               32 ? false : true)
+#define OFFSET_TO_BIT(offset) \
+               {(IS_OFFSET_LOWBIT(offset) ? (1<<OFFSET_TO_NUM(offset)) \
+                       : (1<<(OFFSET_TO_NUM(offset)-32))}
+#define LOWBIT_OF_NUM(num)             (num >= 32 ? 0 : BIT0<<num)
+#define HIGHBIT_OF_NUM(num)            (num >= 32 ? BIT0<<(num-32) : 0)
+
+/* 0~31 */
+#define PARAM_GLOBAL_SHOTMODE          0
+#define PARAM_SENSOR_CONTROL           INC_NUM(PARAM_GLOBAL_SHOTMODE)
+#define PARAM_SENSOR_OTF_INPUT         INC_NUM(PARAM_SENSOR_CONTROL)
+#define PARAM_SENSOR_OTF_OUTPUT                INC_NUM(PARAM_SENSOR_OTF_INPUT)
+#define PARAM_SENSOR_CONFIG            INC_NUM(PARAM_SENSOR_OTF_OUTPUT)
+#define PARAM_SENSOR_DMA_OUTPUT                INC_NUM(PARAM_SENSOR_CONFIG)
+#define PARAM_BUFFER_CONTROL           INC_NUM(PARAM_SENSOR_DMA_OUTPUT)
+#define PARAM_BUFFER_OTF_INPUT         INC_NUM(PARAM_BUFFER_CONTROL)
+#define PARAM_BUFFER_OTF_OUTPUT                INC_NUM(PARAM_BUFFER_OTF_INPUT)
+#define PARAM_3AA_CONTROL              INC_NUM(PARAM_BUFFER_OTF_OUTPUT)
+#define PARAM_3AA_OTF_INPUT            INC_NUM(PARAM_3AA_CONTROL)
+#define PARAM_3AA_VDMA1_INPUT          INC_NUM(PARAM_3AA_OTF_INPUT)
+#define PARAM_3AA_DDMA_INPUT           INC_NUM(PARAM_3AA_VDMA1_INPUT)
+#define PARAM_3AA_OTF_OUTPUT           INC_NUM(PARAM_3AA_DDMA_INPUT)
+#define PARAM_3AA_VDMA4_OUTPUT         INC_NUM(PARAM_3AA_OTF_OUTPUT)
+#define PARAM_3AA_VDMA2_OUTPUT         INC_NUM(PARAM_3AA_VDMA4_OUTPUT)
+#define PARAM_3AA_DDMA_OUTPUT          INC_NUM(PARAM_3AA_VDMA2_OUTPUT)
+#define PARAM_ISP_CONTROL              INC_NUM(PARAM_3AA_DDMA_OUTPUT)
+#define PARAM_ISP_OTF_INPUT            INC_NUM(PARAM_ISP_CONTROL)
+#define PARAM_ISP_VDMA1_INPUT          INC_NUM(PARAM_ISP_OTF_INPUT)
+#define PARAM_ISP_VDMA3_INPUT          INC_NUM(PARAM_ISP_VDMA1_INPUT)
+#define PARAM_ISP_OTF_OUTPUT           INC_NUM(PARAM_ISP_VDMA3_INPUT)
+#define PARAM_ISP_VDMA4_OUTPUT         INC_NUM(PARAM_ISP_OTF_OUTPUT)
+#define PARAM_ISP_VDMA5_OUTPUT         INC_NUM(PARAM_ISP_VDMA4_OUTPUT)
+#define PARAM_DRC_CONTROL              INC_NUM(PARAM_ISP_VDMA5_OUTPUT)
+#define PARAM_DRC_OTF_INPUT            INC_NUM(PARAM_DRC_CONTROL)
+#define PARAM_DRC_DMA_INPUT            INC_NUM(PARAM_DRC_OTF_INPUT)
+#define PARAM_DRC_OTF_OUTPUT           INC_NUM(PARAM_DRC_DMA_INPUT)
+#define PARAM_SCALERC_CONTROL          INC_NUM(PARAM_DRC_OTF_OUTPUT)
+#define PARAM_SCALERC_OTF_INPUT                INC_NUM(PARAM_SCALERC_CONTROL)
+#define PARAM_SCALERC_IMAGE_EFFECT     INC_NUM(PARAM_SCALERC_OTF_INPUT)
+#define PARAM_SCALERC_INPUT_CROP       INC_NUM(PARAM_SCALERC_IMAGE_EFFECT)
+/* 32~63 */
+#define PARAM_SCALERC_OUTPUT_CROP      INC_NUM(PARAM_SCALERC_INPUT_CROP)
+#define PARAM_SCALERC_OTF_OUTPUT       INC_NUM(PARAM_SCALERC_OUTPUT_CROP)
+#define PARAM_SCALERC_DMA_OUTPUT       INC_NUM(PARAM_SCALERC_OTF_OUTPUT)
+#define PARAM_ODC_CONTROL              INC_NUM(PARAM_SCALERC_DMA_OUTPUT)
+#define PARAM_ODC_OTF_INPUT            INC_NUM(PARAM_ODC_CONTROL)
+#define PARAM_ODC_OTF_OUTPUT           INC_NUM(PARAM_ODC_OTF_INPUT)
+#define PARAM_DIS_CONTROL              INC_NUM(PARAM_ODC_OTF_OUTPUT)
+#define PARAM_DIS_OTF_INPUT            INC_NUM(PARAM_DIS_CONTROL)
+#define PARAM_DIS_OTF_OUTPUT           INC_NUM(PARAM_DIS_OTF_INPUT)
+#define PARAM_TDNR_CONTROL             INC_NUM(PARAM_DIS_OTF_OUTPUT)
+#define PARAM_TDNR_OTF_INPUT           INC_NUM(PARAM_TDNR_CONTROL)
+#define PARAM_TDNR_1ST_FRAME           INC_NUM(PARAM_TDNR_OTF_INPUT)
+#define PARAM_TDNR_OTF_OUTPUT          INC_NUM(PARAM_TDNR_1ST_FRAME)
+#define PARAM_TDNR_DMA_OUTPUT          INC_NUM(PARAM_TDNR_OTF_OUTPUT)
+#define PARAM_SCALERP_CONTROL          INC_NUM(PARAM_TDNR_DMA_OUTPUT)
+#define PARAM_SCALERP_OTF_INPUT                INC_NUM(PARAM_SCALERP_CONTROL)
+#define PARAM_SCALERP_IMAGE_EFFECT     INC_NUM(PARAM_SCALERP_OTF_INPUT)
+#define PARAM_SCALERP_INPUT_CROP       INC_NUM(PARAM_SCALERP_IMAGE_EFFECT)
+#define PARAM_SCALERP_OUTPUT_CROP      INC_NUM(PARAM_SCALERP_INPUT_CROP)
+#define PARAM_SCALERP_ROTATION         INC_NUM(PARAM_SCALERP_OUTPUT_CROP)
+#define PARAM_SCALERP_FLIP             INC_NUM(PARAM_SCALERP_ROTATION)
+#define PARAM_SCALERP_OTF_OUTPUT       INC_NUM(PARAM_SCALERP_FLIP)
+#define PARAM_SCALERP_DMA_OUTPUT       INC_NUM(PARAM_SCALERP_OTF_OUTPUT)
+#define PARAM_FD_CONTROL               INC_NUM(PARAM_SCALERP_DMA_OUTPUT)
+#define PARAM_FD_OTF_INPUT             INC_NUM(PARAM_FD_CONTROL)
+#define PARAM_FD_DMA_INPUT             INC_NUM(PARAM_FD_OTF_INPUT)
+#define PARAM_FD_CONFIG                        INC_NUM(PARAM_FD_DMA_INPUT)
+#define PARAM_END                      INC_NUM(PARAM_FD_CONFIG)
+
+#define PARAM_STRNUM_GLOBAL            (PARAM_GLOBAL_SHOTMODE)
+#define PARAM_RANGE_GLOBAL             1
+#define PARAM_STRNUM_SENSOR            (PARAM_SENSOR_CONTROL)
+#define PARAM_RANGE_SENSOR             5
+#define PARAM_STRNUM_BUFFER            (PARAM_BUFFER_CONTROL)
+#define PARAM_RANGE_BUFFER             3
+#define PARAM_STRNUM_3AA               (PARAM_3AA_CONTROL)
+#define PARAM_RANGE_3AA                        8
+#define PARAM_STRNUM_ISP               (PARAM_ISP_CONTROL)
+#define PARAM_RANGE_ISP                        7
+#define PARAM_STRNUM_DRC               (PARAM_DRC_CONTROL)
+#define PARAM_RANGE_DRC                        4
+#define PARAM_STRNUM_SCALERC           (PARAM_SCALERC_CONTROL)
+#define PARAM_RANGE_SCALERC            7
+#define PARAM_STRNUM_ODC               (PARAM_ODC_CONTROL)
+#define PARAM_RANGE_ODC                        3
+#define PARAM_STRNUM_DIS               (PARAM_DIS_CONTROL)
+#define PARAM_RANGE_DIS                        3
+#define PARAM_STRNUM_TDNR              (PARAM_TDNR_CONTROL)
+#define PARAM_RANGE_TDNR               5
+#define PARAM_STRNUM_SCALERP           (PARAM_SCALERP_CONTROL)
+#define PARAM_RANGE_SCALERP            9
+#define PARAM_STRNUM_LHFD              (PARAM_FD_CONTROL)
+#define PARAM_RANGE_LHFD               4
+
+#define PARAM_LOW_MASK         (0xFFFFFFFF)
+#define PARAM_HIGH_MASK                (0x07FFFFFF)
+
+/* Enumerations
+*
+*/
+
+/* ----------------------  Input  ----------------------------------- */
+enum control_command {
+       CONTROL_COMMAND_STOP    = 0,
+       CONTROL_COMMAND_START   = 1,
+       CONTROL_COMMAND_TEST    = 2
+};
+
+enum bypass_command {
+       CONTROL_BYPASS_DISABLE          = 0,
+       CONTROL_BYPASS_ENABLE           = 1
+};
+
+enum control_error {
+       CONTROL_ERROR_NO                = 0
+};
+
+enum otf_input_command {
+       OTF_INPUT_COMMAND_DISABLE       = 0,
+       OTF_INPUT_COMMAND_ENABLE        = 1
+};
+
+enum otf_input_format {
+       OTF_INPUT_FORMAT_BAYER          = 0, /* 1 Channel */
+       OTF_INPUT_FORMAT_YUV444         = 1, /* 3 Channel */
+       OTF_INPUT_FORMAT_YUV422         = 2, /* 3 Channel */
+       OTF_INPUT_FORMAT_YUV420         = 3, /* 3 Channel */
+       OTF_INPUT_FORMAT_STRGEN_COLORBAR_BAYER = 10,
+       OTF_INPUT_FORMAT_BAYER_DMA      = 11,
+};
+
+enum otf_input_bitwidth {
+       OTF_INPUT_BIT_WIDTH_14BIT       = 14,
+       OTF_INPUT_BIT_WIDTH_12BIT       = 12,
+       OTF_INPUT_BIT_WIDTH_11BIT       = 11,
+       OTF_INPUT_BIT_WIDTH_10BIT       = 10,
+       OTF_INPUT_BIT_WIDTH_9BIT        = 9,
+       OTF_INPUT_BIT_WIDTH_8BIT        = 8
+};
+
+enum otf_input_order {
+       OTF_INPUT_ORDER_BAYER_GR_BG     = 0,
+       OTF_INPUT_ORDER_BAYER_RG_GB     = 1,
+       OTF_INPUT_ORDER_BAYER_BG_GR     = 2,
+       OTF_INPUT_ORDER_BAYER_GB_RG     = 3
+};
+
+enum otf_input_path {
+       OTF_INPUT_SERIAL_PATH = 0,
+       OTF_INPUT_PARAL_PATH = 1
+};
+
+enum otf_intput_error {
+       OTF_INPUT_ERROR_NO              = 0 /* Input setting is done */
+};
+
+enum dma_input_command {
+       DMA_INPUT_COMMAND_DISABLE       = 0,
+       DMA_INPUT_COMMAND_ENABLE        = 1,
+       DMA_INPUT_COMMAND_BUF_MNGR      = 2,
+       DMA_INPUT_COMMAND_RUN_SINGLE    = 3,
+};
+
+enum dma_inut_format {
+       DMA_INPUT_FORMAT_BAYER          = 0,
+       DMA_INPUT_FORMAT_YUV444         = 1,
+       DMA_INPUT_FORMAT_YUV422         = 2,
+       DMA_INPUT_FORMAT_YUV420         = 3,
+       DMA_INPUT_FORMAT_RGB            = 4,
+       DMA_INPUT_FORMAT_BAYER_PACKED12 = 5,
+};
+
+enum dma_input_bitwidth {
+       DMA_INPUT_BIT_WIDTH_14BIT       = 14,
+       DMA_INPUT_BIT_WIDTH_12BIT       = 12,
+       DMA_INPUT_BIT_WIDTH_11BIT       = 11,
+       DMA_INPUT_BIT_WIDTH_10BIT       = 10,
+       DMA_INPUT_BIT_WIDTH_9BIT        = 9,
+       DMA_INPUT_BIT_WIDTH_8BIT        = 8
+};
+
+enum dma_input_plane {
+       DMA_INPUT_PLANE_3       = 3,
+       DMA_INPUT_PLANE_2       = 2,
+       DMA_INPUT_PLANE_1       = 1
+};
+
+enum dma_input_order {
+       /* (for DMA_INPUT_PLANE_3) */
+       DMA_INPUT_ORDER_NO      = 0,
+       /* (only valid at DMA_INPUT_PLANE_2) */
+       DMA_INPUT_ORDER_CbCr    = 1,
+       /* (only valid at DMA_INPUT_PLANE_2) */
+       DMA_INPUT_ORDER_CrCb    = 2,
+       /* (only valid at DMA_INPUT_PLANE_1 & DMA_INPUT_FORMAT_YUV444) */
+       DMA_INPUT_ORDER_YCbCr   = 3,
+       /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
+       DMA_INPUT_ORDER_YYCbCr  = 4,
+       /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
+       DMA_INPUT_ORDER_YCbYCr  = 5,
+       /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
+       DMA_INPUT_ORDER_YCrYCb  = 6,
+       /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
+       DMA_INPUT_ORDER_CbYCrY  = 7,
+       /* (only valid at DMA_INPUT_FORMAT_YUV422 & DMA_INPUT_PLANE_1) */
+       DMA_INPUT_ORDER_CrYCbY  = 8,
+       /* (only valid at DMA_INPUT_FORMAT_BAYER) */
+       DMA_INPUT_ORDER_GR_BG   = 9
+};
+
+enum dma_input_MemoryWidthBits {
+       DMA_INPUT_MEMORY_WIDTH_16BIT    = 16,
+       DMA_INPUT_MEMORY_WIDTH_12BIT    = 12,
+};
+
+enum dma_input_error {
+       DMA_INPUT_ERROR_NO      = 0 /*  DMA input setting is done */
+};
+
+/* ----------------------  Output  ----------------------------------- */
+enum otf_output_crop {
+       OTF_OUTPUT_CROP_DISABLE         = 0,
+       OTF_OUTPUT_CROP_ENABLE          = 1
+};
+
+enum otf_output_command {
+       OTF_OUTPUT_COMMAND_DISABLE      = 0,
+       OTF_OUTPUT_COMMAND_ENABLE       = 1
+};
+
+enum orf_output_format {
+       OTF_OUTPUT_FORMAT_YUV444                = 1,
+       OTF_OUTPUT_FORMAT_YUV422                = 2,
+       OTF_OUTPUT_FORMAT_YUV420                = 3,
+       OTF_OUTPUT_FORMAT_RGB                   = 4,
+       OTF_OUTPUT_FORMAT_YUV444_TRUNCATED      = 5,
+       OTF_OUTPUT_FORMAT_YUV422_TRUNCATED      = 6
+};
+
+enum otf_output_bitwidth {
+       OTF_OUTPUT_BIT_WIDTH_14BIT      = 14,
+       OTF_OUTPUT_BIT_WIDTH_12BIT      = 12,
+       OTF_OUTPUT_BIT_WIDTH_11BIT      = 11,
+       OTF_OUTPUT_BIT_WIDTH_10BIT      = 10,
+       OTF_OUTPUT_BIT_WIDTH_9BIT       = 9,
+       OTF_OUTPUT_BIT_WIDTH_8BIT       = 8
+};
+
+enum otf_output_order {
+       OTF_OUTPUT_ORDER_BAYER_GR_BG    = 0,
+};
+
+enum otf_output_error {
+       OTF_OUTPUT_ERROR_NO = 0 /* Output Setting is done */
+};
+
+enum dma_output_command {
+       DMA_OUTPUT_COMMAND_DISABLE      = 0,
+       DMA_OUTPUT_COMMAND_ENABLE       = 1,
+       DMA_OUTPUT_COMMAND_BUF_MNGR     = 2,
+       DMA_OUTPUT_UPDATE_MASK_BITS     = 3
+};
+
+enum dma_output_format {
+       DMA_OUTPUT_FORMAT_BAYER         = 0,
+       DMA_OUTPUT_FORMAT_YUV444        = 1,
+       DMA_OUTPUT_FORMAT_YUV422        = 2,
+       DMA_OUTPUT_FORMAT_YUV420        = 3,
+       DMA_OUTPUT_FORMAT_RGB           = 4,
+       DMA_OUTPUT_FORMAT_BAYER_PACKED12= 5,
+};
+
+enum dma_output_bitwidth {
+       DMA_OUTPUT_BIT_WIDTH_14BIT      = 14,
+       DMA_OUTPUT_BIT_WIDTH_12BIT      = 12,
+       DMA_OUTPUT_BIT_WIDTH_11BIT      = 11,
+       DMA_OUTPUT_BIT_WIDTH_10BIT      = 10,
+       DMA_OUTPUT_BIT_WIDTH_9BIT       = 9,
+       DMA_OUTPUT_BIT_WIDTH_8BIT       = 8
+};
+
+enum dma_output_plane {
+       DMA_OUTPUT_PLANE_3              = 3,
+       DMA_OUTPUT_PLANE_2              = 2,
+       DMA_OUTPUT_PLANE_1              = 1
+};
+
+enum dma_output_order {
+       DMA_OUTPUT_ORDER_NO             = 0,
+       /* (for DMA_OUTPUT_PLANE_3) */
+       DMA_OUTPUT_ORDER_CbCr           = 1,
+       /* (only valid at DMA_INPUT_PLANE_2) */
+       DMA_OUTPUT_ORDER_CrCb           = 2,
+       /* (only valid at DMA_OUTPUT_PLANE_2) */
+       DMA_OUTPUT_ORDER_YYCbCr         = 3,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_YCbYCr         = 4,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_YCrYCb         = 5,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_CbYCrY         = 6,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_CrYCbY         = 7,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV422 & DMA_OUTPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_YCbCr          = 8,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_CrYCb          = 9,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_CrCbY          = 10,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_CbYCr          = 11,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_YCrCb          = 12,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_CbCrY          = 13,
+       /* (only valid at DMA_OUTPUT_FORMAT_YUV444 & DMA_OUPUT_PLANE_1) */
+       DMA_OUTPUT_ORDER_BGR            = 14,
+       /* (only valid at DMA_OUTPUT_FORMAT_RGB) */
+       DMA_OUTPUT_ORDER_GB_BG          = 15
+       /* (only valid at DMA_OUTPUT_FORMAT_BAYER) */
+};
+
+enum dma_output_notify_dma_done {
+       DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE      = 0,
+       DMA_OUTPUT_NOTIFY_DMA_DONE_ENBABLE      = 1,
+};
+
+enum dma_output_error {
+       DMA_OUTPUT_ERROR_NO             = 0 /* DMA output setting is done */
+};
+
+/* ----------------------  Global  ----------------------------------- */
+enum global_shotmode_error {
+       GLOBAL_SHOTMODE_ERROR_NO        = 0 /* shot-mode setting is done */
+};
+
+/* -------------------------  AA  ------------------------------------ */
+enum isp_lock_command {
+       ISP_AA_COMMAND_START    = 0,
+       ISP_AA_COMMAND_STOP     = 1
+};
+
+enum isp_lock_target {
+       ISP_AA_TARGET_AF        = 1,
+       ISP_AA_TARGET_AE        = 2,
+       ISP_AA_TARGET_AWB       = 4
+};
+
+enum isp_af_mode {
+       ISP_AF_MANUAL = 0,
+       ISP_AF_SINGLE,
+       ISP_AF_CONTINUOUS,
+       ISP_AF_REGION,
+       ISP_AF_SLEEP,
+       ISP_AF_INIT,
+       ISP_AF_SET_CENTER_WINDOW,
+       ISP_AF_SET_TOUCH_WINDOW,
+       ISP_AF_SET_FACE_WINDOW
+};
+
+enum isp_af_scene {
+       ISP_AF_SCENE_NORMAL             = 0,
+       ISP_AF_SCENE_MACRO              = 1
+};
+
+enum isp_af_touch {
+       ISP_AF_TOUCH_DISABLE = 0,
+       ISP_AF_TOUCH_ENABLE
+};
+
+enum isp_af_face {
+       ISP_AF_FACE_DISABLE = 0,
+       ISP_AF_FACE_ENABLE
+};
+
+enum isp_af_reponse {
+       ISP_AF_RESPONSE_PREVIEW = 0,
+       ISP_AF_RESPONSE_MOVIE
+};
+
+enum isp_af_sleep {
+       ISP_AF_SLEEP_OFF                = 0,
+       ISP_AF_SLEEP_ON                 = 1
+};
+
+enum isp_af_continuous {
+       ISP_AF_CONTINUOUS_DISABLE       = 0,
+       ISP_AF_CONTINUOUS_ENABLE        = 1
+};
+
+enum isp_af_error {
+       ISP_AF_ERROR_NO                 = 0, /* AF mode change is done */
+       ISP_AF_EROOR_NO_LOCK_DONE       = 1  /* AF lock is done */
+};
+
+/* -------------------------  Flash  ------------------------------------- */
+enum isp_flash_command {
+       ISP_FLASH_COMMAND_DISABLE       = 0,
+       ISP_FLASH_COMMAND_MANUALON      = 1, /* (forced flash) */
+       ISP_FLASH_COMMAND_AUTO          = 2,
+       ISP_FLASH_COMMAND_TORCH         = 3,   /* 3 sec */
+       ISP_FLASH_COMMAND_FLASH_ON      = 4,
+       ISP_FLASH_COMMAND_CAPTURE       = 5,
+       ISP_FLASH_COMMAND_TRIGGER       = 6,
+       ISP_FLASH_COMMAND_CALIBRATION   = 7,
+       ISP_FLASH_COMMAND_START         = 8,
+       ISP_FLASH_COMMAND_CANCLE        = 9
+};
+
+enum isp_flash_redeye {
+       ISP_FLASH_REDEYE_DISABLE        = 0,
+       ISP_FLASH_REDEYE_ENABLE         = 1
+};
+
+enum isp_flash_error {
+       ISP_FLASH_ERROR_NO              = 0 /* Flash setting is done */
+};
+
+/* --------------------------  AWB  ------------------------------------ */
+enum isp_awb_command {
+       ISP_AWB_COMMAND_AUTO            = 0,
+       ISP_AWB_COMMAND_ILLUMINATION    = 1,
+       ISP_AWB_COMMAND_MANUAL  = 2
+};
+
+enum isp_awb_illumination {
+       ISP_AWB_ILLUMINATION_DAYLIGHT           = 0,
+       ISP_AWB_ILLUMINATION_CLOUDY             = 1,
+       ISP_AWB_ILLUMINATION_TUNGSTEN           = 2,
+       ISP_AWB_ILLUMINATION_FLUORESCENT        = 3
+};
+
+enum isp_awb_error {
+       ISP_AWB_ERROR_NO                = 0 /* AWB setting is done */
+};
+
+/* --------------------------  Effect  ----------------------------------- */
+enum isp_imageeffect_command {
+       ISP_IMAGE_EFFECT_DISABLE                = 0,
+       ISP_IMAGE_EFFECT_MONOCHROME             = 1,
+       ISP_IMAGE_EFFECT_NEGATIVE_MONO          = 2,
+       ISP_IMAGE_EFFECT_NEGATIVE_COLOR         = 3,
+       ISP_IMAGE_EFFECT_SEPIA                  = 4,
+       ISP_IMAGE_EFFECT_AQUA                   = 5,
+       ISP_IMAGE_EFFECT_EMBOSS                 = 6,
+       ISP_IMAGE_EFFECT_EMBOSS_MONO            = 7,
+       ISP_IMAGE_EFFECT_SKETCH                 = 8,
+       ISP_IMAGE_EFFECT_RED_YELLOW_POINT       = 9,
+       ISP_IMAGE_EFFECT_GREEN_POINT            = 10,
+       ISP_IMAGE_EFFECT_BLUE_POINT             = 11,
+       ISP_IMAGE_EFFECT_MAGENTA_POINT          = 12,
+       ISP_IMAGE_EFFECT_WARM_VINTAGE           = 13,
+       ISP_IMAGE_EFFECT_COLD_VINTAGE           = 14,
+       ISP_IMAGE_EFFECT_POSTERIZE              = 15,
+       ISP_IMAGE_EFFECT_SOLARIZE               = 16,
+       ISP_IMAGE_EFFECT_WASHED                 = 17,
+       ISP_IMAGE_EFFECT_CCM                    = 18,
+};
+
+enum isp_imageeffect_error {
+       ISP_IMAGE_EFFECT_ERROR_NO       = 0 /* Image effect setting is done */
+};
+
+/* ---------------------------  ISO  ------------------------------------ */
+enum isp_iso_command {
+       ISP_ISO_COMMAND_AUTO            = 0,
+       ISP_ISO_COMMAND_MANUAL          = 1
+};
+
+enum iso_error {
+       ISP_ISO_ERROR_NO                = 0 /* ISO setting is done */
+};
+
+/* --------------------------  Adjust  ----------------------------------- */
+enum iso_adjust_command {
+       ISP_ADJUST_COMMAND_AUTO                 = 0,
+       ISP_ADJUST_COMMAND_MANUAL_CONTRAST      = (1 << 0),
+       ISP_ADJUST_COMMAND_MANUAL_SATURATION    = (1 << 1),
+       ISP_ADJUST_COMMAND_MANUAL_SHARPNESS     = (1 << 2),
+       ISP_ADJUST_COMMAND_MANUAL_EXPOSURE      = (1 << 3),
+       ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS    = (1 << 4),
+       ISP_ADJUST_COMMAND_MANUAL_HUE           = (1 << 5),
+       ISP_ADJUST_COMMAND_MANUAL_HOTPIXEL      = (1 << 6),
+       ISP_ADJUST_COMMAND_MANUAL_NOISEREDUCTION = (1 << 7),
+       ISP_ADJUST_COMMAND_MANUAL_SHADING       = (1 << 8),
+       ISP_ADJUST_COMMAND_MANUAL_GAMMA         = (1 << 9),
+       ISP_ADJUST_COMMAND_MANUAL_EDGEENHANCEMENT = (1 << 10),
+       ISP_ADJUST_COMMAND_MANUAL_SCENE         = (1 << 11),
+       ISP_ADJUST_COMMAND_MANUAL_FRAMETIME     = (1 << 12),
+       ISP_ADJUST_COMMAND_MANUAL_ALL           = 0x1FFF
+};
+
+enum isp_adjust_scene_index {
+       ISP_ADJUST_SCENE_NORMAL                 = 0,
+       ISP_ADJUST_SCENE_NIGHT_PREVIEW          = 1,
+       ISP_ADJUST_SCENE_NIGHT_CAPTURE          = 2
+};
+
+
+enum isp_adjust_error {
+       ISP_ADJUST_ERROR_NO             = 0 /* Adjust setting is done */
+};
+
+/* -------------------------  Metering  ---------------------------------- */
+enum isp_metering_command {
+       ISP_METERING_COMMAND_AVERAGE            = 0,
+       ISP_METERING_COMMAND_SPOT               = 1,
+       ISP_METERING_COMMAND_MATRIX             = 2,
+       ISP_METERING_COMMAND_CENTER             = 3,
+       ISP_METERING_COMMAND_EXPOSURE_MODE      = (1 << 8)
+};
+
+enum isp_exposure_mode {
+       ISP_EXPOSUREMODE_OFF            = 1,
+       ISP_EXPOSUREMODE_AUTO           = 2
+};
+
+enum isp_metering_error {
+       ISP_METERING_ERROR_NO   = 0 /* Metering setting is done */
+};
+
+/* --------------------------  AFC  ----------------------------------- */
+enum isp_afc_command {
+       ISP_AFC_COMMAND_DISABLE         = 0,
+       ISP_AFC_COMMAND_AUTO            = 1,
+       ISP_AFC_COMMAND_MANUAL          = 2
+};
+
+enum isp_afc_manual {
+       ISP_AFC_MANUAL_50HZ             = 50,
+       ISP_AFC_MANUAL_60HZ             = 60
+};
+
+enum isp_afc_error {
+       ISP_AFC_ERROR_NO        = 0 /* AFC setting is done */
+};
+
+enum isp_scene_command {
+       ISP_SCENE_NONE          = 0,
+       ISP_SCENE_PORTRAIT      = 1,
+       ISP_SCENE_LANDSCAPE     = 2,
+       ISP_SCENE_SPORTS        = 3,
+       ISP_SCENE_PARTYINDOOR   = 4,
+       ISP_SCENE_BEACHSNOW     = 5,
+       ISP_SCENE_SUNSET        = 6,
+       ISP_SCENE_DAWN          = 7,
+       ISP_SCENE_FALL          = 8,
+       ISP_SCENE_NIGHT         = 9,
+       ISP_SCENE_AGAINSTLIGHTWLIGHT    = 10,
+       ISP_SCENE_AGAINSTLIGHTWOLIGHT   = 11,
+       ISP_SCENE_FIRE                  = 12,
+       ISP_SCENE_TEXT                  = 13,
+       ISP_SCENE_CANDLE                = 14
+};
+
+enum ISP_BDSCommandEnum {
+       ISP_BDS_COMMAND_DISABLE         = 0,
+       ISP_BDS_COMMAND_ENABLE          = 1
+};
+
+/* --------------------------  Scaler  --------------------------------- */
+enum scaler_imageeffect_command {
+       SCALER_IMAGE_EFFECT_COMMNAD_DISABLE     = 0,
+       SCALER_IMAGE_EFFECT_COMMNAD_SEPIA_CB    = 1,
+       SCALER_IMAGE_EFFECT_COMMAND_SEPIA_CR    = 2,
+       SCALER_IMAGE_EFFECT_COMMAND_NEGATIVE    = 3,
+       SCALER_IMAGE_EFFECT_COMMAND_ARTFREEZE   = 4,
+       SCALER_IMAGE_EFFECT_COMMAND_EMBOSSING   = 5,
+       SCALER_IMAGE_EFFECT_COMMAND_SILHOUETTE  = 6
+};
+
+enum scaler_imageeffect_error {
+       SCALER_IMAGE_EFFECT_ERROR_NO            = 0
+};
+
+enum scaler_crop_command {
+       SCALER_CROP_COMMAND_DISABLE             = 0,
+       SCALER_CROP_COMMAND_ENABLE              = 1
+};
+
+enum scaler_crop_error {
+       SCALER_CROP_ERROR_NO                    = 0 /* crop setting is done */
+};
+
+enum scaler_scaling_command {
+       SCALER_SCALING_COMMNAD_DISABLE          = 0,
+       SCALER_SCALING_COMMAND_UP               = 1,
+       SCALER_SCALING_COMMAND_DOWN             = 2
+};
+
+enum scaler_scaling_error {
+       SCALER_SCALING_ERROR_NO                 = 0
+};
+
+enum scaler_rotation_command {
+       SCALER_ROTATION_COMMAND_DISABLE         = 0,
+       SCALER_ROTATION_COMMAND_CLOCKWISE90     = 1
+};
+
+enum scaler_rotation_error {
+       SCALER_ROTATION_ERROR_NO                = 0
+};
+
+enum scaler_flip_command {
+       SCALER_FLIP_COMMAND_NORMAL              = 0,
+       SCALER_FLIP_COMMAND_X_MIRROR            = 1,
+       SCALER_FLIP_COMMAND_Y_MIRROR            = 2,
+       SCALER_FLIP_COMMAND_XY_MIRROR           = 3 /* (180 rotation) */
+};
+
+enum scaler_flip_error {
+       SCALER_FLIP_ERROR_NO                    = 0 /* flip setting is done */
+};
+
+enum scaler_dma_out_sel {
+       SCALER_DMA_OUT_IMAGE_EFFECT             = 0,
+       SCALER_DMA_OUT_SCALED                   = 1,
+       SCALER_DMA_OUT_UNSCALED                 = 2
+};
+
+enum scaler_output_yuv_range {
+       SCALER_OUTPUT_YUV_RANGE_FULL = 0,
+       SCALER_OUTPUT_YUV_RANGE_NARROW = 1,
+};
+
+/* --------------------------  3DNR  ----------------------------------- */
+enum tdnr_1st_frame_command {
+       TDNR_1ST_FRAME_COMMAND_NOPROCESSING     = 0,
+       TDNR_1ST_FRAME_COMMAND_2DNR             = 1
+};
+
+enum tdnr_1st_frame_error {
+       TDNR_1ST_FRAME_ERROR_NO                 = 0
+               /*1st frame setting is done*/
+};
+
+/* ----------------------------  FD  ------------------------------------- */
+enum fd_config_command {
+       FD_CONFIG_COMMAND_MAXIMUM_NUMBER        = 0x1,
+       FD_CONFIG_COMMAND_ROLL_ANGLE            = 0x2,
+       FD_CONFIG_COMMAND_YAW_ANGLE             = 0x4,
+       FD_CONFIG_COMMAND_SMILE_MODE            = 0x8,
+       FD_CONFIG_COMMAND_BLINK_MODE            = 0x10,
+       FD_CONFIG_COMMAND_EYES_DETECT           = 0x20,
+       FD_CONFIG_COMMAND_MOUTH_DETECT          = 0x40,
+       FD_CONFIG_COMMAND_ORIENTATION           = 0x80,
+       FD_CONFIG_COMMAND_ORIENTATION_VALUE     = 0x100
+};
+
+enum fd_config_roll_angle {
+       FD_CONFIG_ROLL_ANGLE_BASIC              = 0,
+       FD_CONFIG_ROLL_ANGLE_PRECISE_BASIC      = 1,
+       FD_CONFIG_ROLL_ANGLE_SIDES              = 2,
+       FD_CONFIG_ROLL_ANGLE_PRECISE_SIDES      = 3,
+       FD_CONFIG_ROLL_ANGLE_FULL               = 4,
+       FD_CONFIG_ROLL_ANGLE_PRECISE_FULL       = 5,
+};
+
+enum fd_config_yaw_angle {
+       FD_CONFIG_YAW_ANGLE_0                   = 0,
+       FD_CONFIG_YAW_ANGLE_45                  = 1,
+       FD_CONFIG_YAW_ANGLE_90                  = 2,
+       FD_CONFIG_YAW_ANGLE_45_90               = 3,
+};
+
+enum fd_config_smile_mode {
+       FD_CONFIG_SMILE_MODE_DISABLE            = 0,
+       FD_CONFIG_SMILE_MODE_ENABLE             = 1
+};
+
+enum fd_config_blink_mode {
+       FD_CONFIG_BLINK_MODE_DISABLE            = 0,
+       FD_CONFIG_BLINK_MODE_ENABLE             = 1
+};
+
+enum fd_config_eye_result {
+       FD_CONFIG_EYES_DETECT_DISABLE           = 0,
+       FD_CONFIG_EYES_DETECT_ENABLE            = 1
+};
+
+enum fd_config_mouth_result {
+       FD_CONFIG_MOUTH_DETECT_DISABLE          = 0,
+       FD_CONFIG_MOUTH_DETECT_ENABLE           = 1
+};
+
+enum fd_config_orientation {
+       FD_CONFIG_ORIENTATION_DISABLE           = 0,
+       FD_CONFIG_ORIENTATION_ENABLE            = 1
+};
+
+struct param_control {
+       u32     cmd;
+       u32     bypass;
+       u32     buffer_address;
+       u32     buffer_number;
+       /* 0: continuous, 1: single */
+       u32     run_mode;
+       u32     reserved[PARAMETER_MAX_MEMBER-6];
+       u32     err;
+};
+
+struct param_otf_input {
+       u32     cmd;
+       u32     width; /* with margin */
+       u32     height; /* with margine */
+       u32     format;
+       u32     bitwidth;
+       u32     order;
+       u32     sensor_binning_ratio_x; /* ex(x1: 1000, x0.5: 2000) */
+       u32     sensor_binning_ratio_y; /* ex(x1: 1000, x0.5: 2000) */
+       u32     bns_binning_enable;
+       u32     bns_binning_ratio_x; /* ex(x1: 1000, x0.5: 2000) */
+       u32     bns_binning_ratio_y; /* ex(x1: 1000, x0.5: 2000) */
+       u32     bns_margin_left;
+       u32     bns_margin_top;
+       u32     bns_output_width; /* with margin */
+       u32     bns_output_height; /* with margin */
+       u32     bayer_crop_enable;
+       u32     bayer_crop_offset_x;
+       u32     bayer_crop_offset_y;
+       u32     bayer_crop_width; /* without margin */
+       u32     bayer_crop_height; /* without margin */
+       u32     bds_out_enable;
+       u32     bds_out_width; /* without margin */
+       u32     bds_out_height; /* without margin */
+       u32     frametime_min;
+       u32     frametime_max;
+       u32     scaler_path_sel; /* parallel or serial for SCC*/
+       u32     reserved[PARAMETER_MAX_MEMBER-27];
+       u32     err;
+};
+
+struct param_dma_input {
+       u32     cmd;
+       u32     width; /* with margin */
+       u32     height; /* with margin */
+       u32     format;
+       u32     bitwidth;
+       u32     plane;
+       u32     order;
+       u32     buffer_number;
+       u32     buffer_address;
+       u32     sensor_binning_ratio_x; /* ex(x1: 1000, x0.5: 2000) */
+       u32     sensor_binning_ratio_y; /* ex(x1: 1000, x0.5: 2000) */
+       u32     dma_crop_enable; /* should be 0 */
+       u32     dma_crop_offset_x; /* not supported yet */
+       u32     dma_crop_offset_y; /* not supported yet */
+       u32     dma_crop_width; /* not supported yet */
+       u32     dma_crop_height; /* not supported yet */
+       u32     bayer_crop_enable;
+       u32     bayer_crop_offset_x;
+       u32     bayer_crop_offset_y;
+       u32     bayer_crop_width; /* without margine */
+       u32     bayer_crop_height; /* without margine */
+       u32     bds_out_enable;
+       u32     bds_out_width; /* without margine */
+       u32     bds_out_height; /* without margine */
+       u32     user_min_frame_time;
+       u32     user_max_frame_time;
+       u32     reserved[PARAMETER_MAX_MEMBER-27];
+       u32     err;
+};
+
+struct param_otf_output {
+       u32     cmd;
+       u32     width;
+       u32     height;
+       u32     format;
+       u32     bitwidth;
+       u32     order;
+       u32     crop_offset_x;
+       u32     crop_offset_y;
+       u32     reserved[PARAMETER_MAX_MEMBER-9];
+       u32     err;
+};
+
+struct param_dma_output {
+       u32     cmd;
+       u32     width;
+       u32     height;
+       u32     format;
+       u32     bitwidth;
+       u32     plane;
+       u32     order;
+       u32     buffer_number;
+       u32     buffer_address;
+       u32     notify_dma_done;
+       u32     dma_out_mask;
+       u32     reserved[PARAMETER_MAX_MEMBER-12];
+       u32     err;
+};
+
+struct param_global_shotmode {
+       u32     cmd;
+       u32     skip_frames;
+       u32     reserved[PARAMETER_MAX_MEMBER-3];
+       u32     err;
+};
+
+struct param_sensor_config {
+       u32     framerate;
+       u32     width;
+       u32     height;
+       u32     mode;
+       u32     binning_ratio_x;
+       u32     binning_ratio_y;
+       u32     min_target_fps;
+       u32     max_target_fps;
+       u32     scene_mode;
+       u32     reserved[PARAMETER_MAX_MEMBER-10];
+       u32     err;
+};
+
+struct param_isp_aa {
+       u32     cmd;
+       u32     target;
+       u32     mode;
+       u32     scene;
+       u32     af_touch;
+       u32     af_face;
+       u32     af_response;
+       u32     sleep;
+       u32     touch_x;
+       u32     touch_y;
+       u32     manual_af_setting;
+       /*0: Legacy, 1: Camera 2.0*/
+       u32     cam_api_2p0;
+       /* For android.control.afRegions in Camera 2.0,
+       Resolution based on YUV output size*/
+       u32     af_region_left;
+       /* For android.control.afRegions in Camera 2.0,
+       Resolution based on YUV output size*/
+       u32     af_region_top;
+       /* For android.control.afRegions in Camera 2.0,
+       Resolution based on YUV output size*/
+       u32     af_region_right;
+       /* For android.control.afRegions in Camera 2.0,
+       Resolution based on YUV output size*/
+       u32     af_region_bottom;
+       u32     reserved[PARAMETER_MAX_MEMBER-17];
+       u32     err;
+};
+
+struct param_isp_flash {
+       u32     cmd;
+       u32     redeye;
+       u32     flashintensity;
+       u32     reserved[PARAMETER_MAX_MEMBER-4];
+       u32     err;
+};
+
+struct param_isp_awb {
+       u32     cmd;
+       u32     illumination;
+       u32     reserved[PARAMETER_MAX_MEMBER-3];
+       u32     err;
+};
+
+struct param_isp_imageeffect {
+       u32     cmd;
+       u32     reserved[PARAMETER_MAX_MEMBER-2];
+       u32     err;
+};
+
+struct param_isp_iso {
+       u32     cmd;
+       u32     value;
+       u32     reserved[PARAMETER_MAX_MEMBER-3];
+       u32     err;
+};
+
+struct param_isp_adjust {
+       u32     cmd;
+       s32     contrast;
+       s32     saturation;
+       s32     sharpness;
+       s32     exposure;
+       s32     brightness;
+       s32     hue;
+       /* 0 or 1 */
+       u32     hot_pixel_enable;
+       /* -127 ~ 127 */
+       s32     noise_reduction_strength;
+       /* 0 or 1 */
+       u32     shading_correction_enable;
+       /* 0 or 1 */
+       u32     user_gamma_enable;
+       /* -127 ~ 127 */
+       s32     edge_enhancement_strength;
+       /* ISP_AdjustSceneIndexEnum */
+       u32     user_scene_mode;
+       u32     min_frame_time;
+       u32     max_frame_time;
+       u32     reserved[PARAMETER_MAX_MEMBER-16];
+       u32     err;
+};
+
+struct param_isp_metering {
+       u32     cmd;
+       u32     win_pos_x;
+       u32     win_pos_y;
+       u32     win_width;
+       u32     win_height;
+       u32     exposure_mode;
+       /* 0: Legacy, 1: Camera 2.0 */
+       u32     cam_api_2p0;
+       u32     reserved[PARAMETER_MAX_MEMBER-8];
+       u32     err;
+};
+
+struct param_isp_afc {
+       u32     cmd;
+       u32     manual;
+       u32     reserved[PARAMETER_MAX_MEMBER-3];
+       u32     err;
+};
+
+struct param_scaler_imageeffect {
+       u32     cmd;
+       u32     arbitrary_cb;
+       u32     arbitrary_cr;
+       u32     yuv_range;
+       u32     reserved[PARAMETER_MAX_MEMBER-5];
+       u32     err;
+};
+
+struct param_scaler_input_crop {
+       u32  cmd;
+       u32  pos_x;
+       u32  pos_y;
+       u32  crop_width;
+       u32  crop_height;
+       u32  in_width;
+       u32  in_height;
+       u32  out_width;
+       u32  out_height;
+       u32  reserved[PARAMETER_MAX_MEMBER-10];
+       u32  err;
+};
+
+struct param_scaler_output_crop {
+       u32  cmd;
+       u32  pos_x;
+       u32  pos_y;
+       u32  crop_width;
+       u32  crop_height;
+       u32  format;
+       u32  reserved[PARAMETER_MAX_MEMBER-7];
+       u32  err;
+};
+
+struct param_scaler_rotation {
+       u32     cmd;
+       u32     reserved[PARAMETER_MAX_MEMBER-2];
+       u32     err;
+};
+
+struct param_scaler_flip {
+       u32     cmd;
+       u32     reserved[PARAMETER_MAX_MEMBER-2];
+       u32     err;
+};
+
+struct param_3dnr_1stframe {
+       u32     cmd;
+       u32     reserved[PARAMETER_MAX_MEMBER-2];
+       u32     err;
+};
+
+struct param_fd_config {
+       u32     cmd;
+       u32     max_number;
+       u32     roll_angle;
+       u32     yaw_angle;
+       s32     smile_mode;
+       s32     blink_mode;
+       u32     eye_detect;
+       u32     mouth_detect;
+       u32     orientation;
+       u32     orientation_value;
+       u32     reserved[PARAMETER_MAX_MEMBER-11];
+       u32     err;
+};
+
+struct global_param {
+       struct param_global_shotmode    shotmode; /* 0 */
+};
+
+/* To be added */
+struct sensor_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;
+       struct param_otf_output         otf_output;
+       struct param_sensor_config      config;
+       struct param_dma_output         dma_output;
+};
+
+struct buffer_param {
+       struct param_control    control;
+       struct param_otf_input  otf_input;
+       struct param_otf_output otf_output;
+};
+
+struct taa_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;      /* otf_input */
+       struct param_dma_input          vdma1_input;    /* dma1_input */
+       struct param_dma_input          ddma_input;     /* not use */
+       struct param_otf_output         otf_output;     /* not use */
+       struct param_dma_output         vdma4_output;   /* Before BDS */
+       struct param_dma_output         vdma2_output;   /* After BDS */
+       struct param_dma_output         ddma_output;    /* not use */
+};
+
+struct isp_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;      /* not use */
+       struct param_dma_input          vdma1_input;    /* dma1_input */
+       struct param_dma_input          vdma3_input;    /* not use */
+       struct param_otf_output         otf_output;     /* otf_out */
+       struct param_dma_output         vdma4_output;   /* not use */
+       struct param_dma_output         vdma5_output;   /* not use */
+};
+
+struct drc_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;
+       struct param_dma_input          dma_input;
+       struct param_otf_output         otf_output;
+};
+
+struct scalerc_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;
+       struct param_scaler_imageeffect effect;
+       struct param_scaler_input_crop  input_crop;
+       struct param_scaler_output_crop  output_crop;
+       struct param_otf_output         otf_output;
+       struct param_dma_output         dma_output;
+};
+
+struct odc_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;
+       struct param_otf_output         otf_output;
+};
+
+struct dis_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;
+       struct param_otf_output         otf_output;
+};
+
+struct tdnr_param {
+       struct param_control            control;
+       struct param_otf_input          otf_input;
+       struct param_3dnr_1stframe      frame;
+       struct param_otf_output         otf_output;
+       struct param_dma_output         dma_output;
+};
+
+struct scalerp_param {
+       struct param_control                    control;
+       struct param_otf_input                  otf_input;
+       struct param_scaler_imageeffect         effect;
+       struct param_scaler_input_crop  input_crop;
+       struct param_scaler_output_crop  output_crop;
+       struct param_scaler_rotation            rotation;
+       struct param_scaler_flip                flip;
+       struct param_otf_output                 otf_output;
+       struct param_dma_output                 dma_output;
+};
+
+struct fd_param {
+       struct param_control                    control;
+       struct param_otf_input                  otf_input;
+       struct param_dma_input                  dma_input;
+       struct param_fd_config                  config;
+};
+
+struct is_param_region {
+       struct global_param             global;
+       struct sensor_param             sensor;
+       struct buffer_param             buf;
+       struct taa_param                taa;
+       struct isp_param                isp;
+       struct drc_param                drc;
+       struct scalerc_param            scalerc;
+       struct odc_param                odc;
+       struct dis_param                dis;
+       struct tdnr_param               tdnr;
+       struct scalerp_param            scalerp;
+       struct fd_param                 fd;
+};
+
+#define        NUMBER_OF_GAMMA_CURVE_POINTS    32
+
+struct is_sensor_tune {
+       u32 exposure;
+       u32 analog_gain;
+       u32 frame_rate;
+       u32 actuator_pos;
+};
+
+struct is_tune_gammacurve {
+       u32 num_pts_x[NUMBER_OF_GAMMA_CURVE_POINTS];
+       u32 num_pts_y_r[NUMBER_OF_GAMMA_CURVE_POINTS];
+       u32 num_pts_y_g[NUMBER_OF_GAMMA_CURVE_POINTS];
+       u32 num_pts_y_b[NUMBER_OF_GAMMA_CURVE_POINTS];
+};
+
+struct is_isp_tune {
+       /* Brightness level : range 0~100, default : 7 */
+       u32 brightness_level;
+       /* Contrast level : range -127~127, default : 0 */
+       s32 contrast_level;
+       /* Saturation level : range -127~127, default : 0 */
+       s32 saturation_level;
+       s32 gamma_level;
+       struct is_tune_gammacurve gamma_curve[4];
+       /* Hue : range -127~127, default : 0 */
+       s32 hue;
+       /* Sharpness blur : range -127~127, default : 0 */
+       s32 sharpness_blur;
+       /* Despeckle : range -127~127, default : 0 */
+       s32 despeckle;
+       /* Edge color supression : range -127~127, default : 0 */
+       s32 edge_color_supression;
+       /* Noise reduction : range -127~127, default : 0 */
+       s32 noise_reduction;
+       /* (32*4 + 9)*4 = 548 bytes */
+};
+
+struct is_tune_region {
+       struct is_sensor_tune sensor_tune;
+       struct is_isp_tune isp_tune;
+};
+
+struct rational_t {
+       u32 num;
+       u32 den;
+};
+
+struct srational_t {
+       s32 num;
+       s32 den;
+};
+
+#define FLASH_FIRED_SHIFT      0
+#define FLASH_NOT_FIRED                0
+#define FLASH_FIRED            1
+
+#define FLASH_STROBE_SHIFT                             1
+#define FLASH_STROBE_NO_DETECTION                      0
+#define FLASH_STROBE_RESERVED                          1
+#define FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED         2
+#define FLASH_STROBE_RETURN_LIGHT_DETECTED             3
+
+#define FLASH_MODE_SHIFT                       3
+#define FLASH_MODE_UNKNOWN                     0
+#define FLASH_MODE_COMPULSORY_FLASH_FIRING     1
+#define FLASH_MODE_COMPULSORY_FLASH_SUPPRESSION        2
+#define FLASH_MODE_AUTO_MODE                   3
+
+#define FLASH_FUNCTION_SHIFT           5
+#define FLASH_FUNCTION_PRESENT         0
+#define FLASH_FUNCTION_NONE            1
+
+#define FLASH_RED_EYE_SHIFT            6
+#define FLASH_RED_EYE_DISABLED         0
+#define FLASH_RED_EYE_SUPPORTED                1
+
+enum apex_aperture_value {
+       F1_0            = 0,
+       F1_4            = 1,
+       F2_0            = 2,
+       F2_8            = 3,
+       F4_0            = 4,
+       F5_6            = 5,
+       F8_9            = 6,
+       F11_0           = 7,
+       F16_0           = 8,
+       F22_0           = 9,
+       F32_0           = 10,
+};
+
+struct exif_attribute {
+       struct rational_t exposure_time;
+       struct srational_t shutter_speed;
+       u32 iso_speed_rating;
+       u32 flash;
+       struct srational_t brightness;
+};
+
+struct is_frame_header {
+       u32 valid;
+       u32 bad_mark;
+       u32 captured;
+       u32 frame_number;
+       struct exif_attribute   exif;
+};
+
+struct is_fd_rect {
+       u32 offset_x;
+       u32 offset_y;
+       u32 width;
+       u32 height;
+};
+
+struct is_face_marker {
+       u32     frame_number;
+       struct is_fd_rect face;
+       struct is_fd_rect left_eye;
+       struct is_fd_rect right_eye;
+       struct is_fd_rect mouth;
+       u32     roll_angle;
+       u32 yaw_angle;
+       u32     confidence;
+       u32     is_tracked;
+       u32     tracked_face_id;
+       u32     smile_level;
+       u32     blink_level;
+};
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433) || defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS4415)
+struct is_debug_region {
+       u32     frame_count;
+       u32     reserved[PARAMETER_MAX_MEMBER-1];
+};
+#endif
+
+#define MAX_FRAME_COUNT                8
+#define MAX_FRAME_COUNT_PREVIEW        4
+#define MAX_FRAME_COUNT_CAPTURE        1
+#define MAX_FACE_COUNT         16
+
+#define MAX_SHARED_COUNT       500
+
+struct is_region {
+       struct is_param_region  parameter;
+       struct is_tune_region   tune;
+       struct is_frame_header  header[MAX_FRAME_COUNT];
+       struct is_face_marker   face[MAX_FACE_COUNT];
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433) || defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS4415)
+       struct is_debug_region  debug;
+#endif
+       u32                     shared[MAX_SHARED_COUNT];
+};
+
+struct is_time_measure_us {
+       u32  min_time_us;
+       u32  max_time_us;
+       u32  avrg_time_us;
+       u32  current_time_us;
+};
+
+struct is_debug_frame_descriptor {
+       u32     sensor_frame_time;
+       u32     sensor_exposure_time;
+       u32     sensor_analog_gain;
+       u32     req_lei;
+};
+
+#define MAX_FRAMEDESCRIPTOR_CONTEXT_NUM        (30 * 20)       /* 600 frame */
+#define MAX_VERSION_DISPLAY_BUF                (32)
+
+struct is_share_region {
+       u32     frame_time;
+       u32     exposure_time;
+       u32     analog_gain;
+
+       u32     r_gain;
+       u32     g_gain;
+       u32     b_gain;
+
+       u32     af_position;
+       u32     af_status;
+       u32 af_scene_type;
+
+       u32     frame_descp_onoff_control;
+       u32     frame_descp_update_done;
+       u32     frame_descp_idx;
+       u32     frame_descp_max_idx;
+
+       struct is_debug_frame_descriptor
+               dbg_frame_descp_ctx[MAX_FRAMEDESCRIPTOR_CONTEXT_NUM];
+
+       u32 chip_id;
+       u32 chip_rev_no;
+       u8      ispfw_version_no[MAX_VERSION_DISPLAY_BUF];
+       u8      ispfw_version_date[MAX_VERSION_DISPLAY_BUF];
+       u8      sirc_sdk_version_no[MAX_VERSION_DISPLAY_BUF];
+       u8      sirc_sdk_revsion_no[MAX_VERSION_DISPLAY_BUF];
+       u8      sirc_sdk_version_date[MAX_VERSION_DISPLAY_BUF];
+
+       /*measure timing*/
+       struct is_time_measure_us       isp_sdk_Time;
+};
+
+struct is_debug_control {
+       u32 write_point;        /* 0~500KB boundary*/
+       u32 assert_flag;        /* 0:Not Inovked, 1:Invoked*/
+       u32 pabort_flag;        /* 0:Not Inovked, 1:Invoked*/
+       u32 dabort_flag;        /* 0:Not Inovked, 1:Invoked*/
+       u32 pd_Ready_flag;      /* 0:Normal, 1:EnterIdle(Ready to power down)*/
+       u32 isp_frameErr;       /* Frame Error Count.*/
+       u32 drc_frame_err;      /* Frame Error Count.*/
+       u32 scc_frame_err;      /* Frame Error Count.*/
+       u32 odc_frame_err;      /* Frame Error Count.*/
+       u32 dis_frame_err;      /* Frame Error Count.*/
+       u32 tdnr_frame_err;     /* Frame Error Count.*/
+       u32 scp_frame_err;      /* Frame Error Count.*/
+       u32 fd_frame_err;       /* Frame Error Count.*/
+       u32 isp_frame_drop;     /* Frame Drop Count.*/
+       u32 drc_frame_drop;     /* Frame Drop Count.*/
+       u32 dis_frame_drop;     /* Frame Drop Count.*/
+       u32 fd_frame_drop;
+};
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-regs.h b/drivers/media/platform/exynos/fimc-is/fimc-is-regs.h
new file mode 100644 (file)
index 0000000..c15485a
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_REGS_H
+#define FIMC_IS_REGS_H
+
+#include <mach/map.h>
+
+/* MCUCTL register */
+#define MCUCTL                         0x0
+/* MCU Controller Register */
+#define MCUCTLR                                (MCUCTL+0x00)
+#define MCUCTLR_AXI_ISPX_AWCACHE(x)    ((x) << 16)
+#define MCUCTLR_AXI_ISPX_ARCACHE(x)    ((x) << 12)
+#define MCUCTLR_MSWRST                 (1 << 0)
+/* Boot Base OFfset Address Register */
+#define BBOAR                          (MCUCTL+0x04)
+#define BBOAR_BBOA(x)                  ((x) << 0)
+/* Interrupt Generation Register 0 from Host CPU to VIC */
+#define INTGR0                         (MCUCTL+0x08)
+#define INTGR0_INTGC9                  (1 << 25)
+#define INTGR0_INTGC8                  (1 << 24)
+#define INTGR0_INTGC7                  (1 << 23)
+#define INTGR0_INTGC6                  (1 << 22)
+#define INTGR0_INTGC5                  (1 << 21)
+#define INTGR0_INTGC4                  (1 << 20)
+#define INTGR0_INTGC3                  (1 << 19)
+#define INTGR0_INTGC2                  (1 << 18)
+#define INTGR0_INTGC1                  (1 << 17)
+#define INTGR0_INTGC0                  (1 << 16)
+#define INTGR0_INTGD5                  (1 << 5)
+#define INTGR0_INTGD4                  (1 << 4)
+#define INTGR0_INTGD3                  (1 << 3)
+#define INTGR0_INTGD2                  (1 << 2)
+#define INTGR0_INTGD1                  (1 << 1)
+#define INTGR0_INTGD0                  (1 << 0)
+/* Interrupt Clear Register 0 from Host CPU to VIC */
+#define INTCR0                         (MCUCTL+0x0c)
+#define INTCR0_INTCC9                  (1 << 25)
+#define INTCR0_INTCC8                  (1 << 24)
+#define INTCR0_INTCC7                  (1 << 23)
+#define INTCR0_INTCC6                  (1 << 22)
+#define INTCR0_INTCC5                  (1 << 21)
+#define INTCR0_INTCC4                  (1 << 20)
+#define INTCR0_INTCC3                  (1 << 19)
+#define INTCR0_INTCC2                  (1 << 18)
+#define INTCR0_INTCC1                  (1 << 17)
+#define INTCR0_INTCC0                  (1 << 16)
+#define INTCR0_INTCD5                  (1 << 5)
+#define INTCR0_INTCD4                  (1 << 4)
+#define INTCR0_INTCD3                  (1 << 3)
+#define INTCR0_INTCD2                  (1 << 2)
+#define INTCR0_INTCD1                  (1 << 1)
+#define INTCR0_INTCD0                  (1 << 0)
+/* Interrupt Mask Register 0 from Host CPU to VIC */
+#define INTMR0                         (MCUCTL+0x10)
+#define INTMR0_INTMC9                  (1 << 25)
+#define INTMR0_INTMC8                  (1 << 24)
+#define INTMR0_INTMC7                  (1 << 23)
+#define INTMR0_INTMC6                  (1 << 22)
+#define INTMR0_INTMC5                  (1 << 21)
+#define INTMR0_INTMC4                  (1 << 20)
+#define INTMR0_INTMC3                  (1 << 19)
+#define INTMR0_INTMC2                  (1 << 18)
+#define INTMR0_INTMC1                  (1 << 17)
+#define INTMR0_INTMC0                  (1 << 16)
+#define INTMR0_INTMD5                  (1 << 5)
+#define INTMR0_INTMD4                  (1 << 4)
+#define INTMR0_INTMD3                  (1 << 3)
+#define INTMR0_INTMD2                  (1 << 2)
+#define INTMR0_INTMD1                  (1 << 1)
+#define INTMR0_INTMD0                  (1 << 0)
+/* Interrupt Status Register 0 from Host CPU to VIC */
+#define INTSR0                         (MCUCTL+0x14)
+#define INTSR0_GET_INTSD0(x)           (((x) >> 0) & 0x1)
+#define INTSR0_GET_INTSD1(x)           (((x) >> 1) & 0x1)
+#define INTSR0_GET_INTSD2(x)           (((x) >> 2) & 0x1)
+#define INTSR0_GET_INTSD3(x)           (((x) >> 3) & 0x1)
+#define INTSR0_GET_INTSD4(x)           (((x) >> 4) & 0x1)
+#define INTSR0_GET_INTSC0(x)           (((x) >> 16) & 0x1)
+#define INTSR0_GET_INTSC1(x)           (((x) >> 17) & 0x1)
+#define INTSR0_GET_INTSC2(x)           (((x) >> 18) & 0x1)
+#define INTSR0_GET_INTSC3(x)           (((x) >> 19) & 0x1)
+#define INTSR0_GET_INTSC4(x)           (((x) >> 20) & 0x1)
+#define INTSR0_GET_INTSC5(x)           (((x) >> 21) & 0x1)
+#define INTSR0_GET_INTSC6(x)           (((x) >> 22) & 0x1)
+#define INTSR0_GET_INTSC7(x)           (((x) >> 23) & 0x1)
+#define INTSR0_GET_INTSC8(x)           (((x) >> 24) & 0x1)
+#define INTSR0_GET_INTSC9(x)           (((x) >> 25) & 0x1)
+/* Interrupt Mask Status Register 0 from Host CPU to VIC */
+#define INTMSR0                                (MCUCTL+0x18)
+#define INTMSR0_GET_INTMSD0(x)         (((x) >> 0) & 0x1)
+#define INTMSR0_GET_INTMSD1(x)         (((x) >> 1) & 0x1)
+#define INTMSR0_GET_INTMSD2(x)         (((x) >> 2) & 0x1)
+#define INTMSR0_GET_INTMSD3(x)         (((x) >> 3) & 0x1)
+#define INTMSR0_GET_INTMSD4(x)         (((x) >> 4) & 0x1)
+#define INTMSR0_GET_INTMSC0(x)         (((x) >> 16) & 0x1)
+#define INTMSR0_GET_INTMSC1(x)         (((x) >> 17) & 0x1)
+#define INTMSR0_GET_INTMSC2(x)         (((x) >> 18) & 0x1)
+#define INTMSR0_GET_INTMSC3(x)         (((x) >> 19) & 0x1)
+#define INTMSR0_GET_INTMSC4(x)         (((x) >> 20) & 0x1)
+#define INTMSR0_GET_INTMSC5(x)         (((x) >> 21) & 0x1)
+#define INTMSR0_GET_INTMSC6(x)         (((x) >> 22) & 0x1)
+#define INTMSR0_GET_INTMSC7(x)         (((x) >> 23) & 0x1)
+#define INTMSR0_GET_INTMSC8(x)         (((x) >> 24) & 0x1)
+#define INTMSR0_GET_INTMSC9(x)         (((x) >> 25) & 0x1)
+/* Interrupt Generation Register 1 from ISP CPU to Host IC */
+#define INTGR1                         (MCUCTL+0x1c)
+#define INTGR1_INTGC9                  (1 << 9)
+#define INTGR1_INTGC8                  (1 << 8)
+#define INTGR1_INTGC7                  (1 << 7)
+#define INTGR1_INTGC6                  (1 << 6)
+#define INTGR1_INTGC5                  (1 << 5)
+#define INTGR1_INTGC4                  (1 << 4)
+#define INTGR1_INTGC3                  (1 << 3)
+#define INTGR1_INTGC2                  (1 << 2)
+#define INTGR1_INTGC1                  (1 << 1)
+#define INTGR1_INTGC0                  (1 << 0)
+/* Interrupt Clear Register 1 from ISP CPU to Host IC */
+#define INTCR1                         (MCUCTL+0x20)
+#define INTCR1_INTCC9                  (1 << 9)
+#define INTCR1_INTCC8                  (1 << 8)
+#define INTCR1_INTCC7                  (1 << 7)
+#define INTCR1_INTCC6                  (1 << 6)
+#define INTCR1_INTCC5                  (1 << 5)
+#define INTCR1_INTCC4                  (1 << 4)
+#define INTCR1_INTCC3                  (1 << 3)
+#define INTCR1_INTCC2                  (1 << 2)
+#define INTCR1_INTCC1                  (1 << 1)
+#define INTCR1_INTCC0                  (1 << 0)
+/* Interrupt Mask Register 1 from ISP CPU to Host IC */
+#define INTMR1                         (MCUCTL+0x24)
+#define INTMR1_INTMC9                  (1 << 9)
+#define INTMR1_INTMC8                  (1 << 8)
+#define INTMR1_INTMC7                  (1 << 7)
+#define INTMR1_INTMC6                  (1 << 6)
+#define INTMR1_INTMC5                  (1 << 5)
+#define INTMR1_INTMC4                  (1 << 4)
+#define INTMR1_INTMC3                  (1 << 3)
+#define INTMR1_INTMC2                  (1 << 2)
+#define INTMR1_INTMC1                  (1 << 1)
+#define INTMR1_INTMC0                  (1 << 0)
+/* Interrupt Status Register 1 from ISP CPU to Host IC */
+#define INTSR1                         (MCUCTL+0x28)
+/* Interrupt Mask Status Register 1 from ISP CPU to Host IC */
+#define INTMSR1                                (MCUCTL+0x2c)
+/* Interrupt Clear Register 2 from ISP BLK's interrupts to Host IC */
+#define INTCR2                         (MCUCTL+0x30)
+#define INTCR2_INTCC21                 (1 << 21)
+#define INTCR2_INTCC20                 (1 << 20)
+#define INTCR2_INTCC19                 (1 << 19)
+#define INTCR2_INTCC18                 (1 << 18)
+#define INTCR2_INTCC17                 (1 << 17)
+#define INTCR2_INTCC16                 (1 << 16)
+/* Interrupt Mask Register 2 from ISP BLK's interrupts to Host IC */
+#define INTMR2                         (MCUCTL+0x34)
+#define INTMR2_INTMCIS25               (1 << 25)
+#define INTMR2_INTMCIS24               (1 << 24)
+#define INTMR2_INTMCIS23               (1 << 23)
+#define INTMR2_INTMCIS22               (1 << 22)
+#define INTMR2_INTMCIS21               (1 << 21)
+#define INTMR2_INTMCIS20               (1 << 20)
+#define INTMR2_INTMCIS19               (1 << 19)
+#define INTMR2_INTMCIS18               (1 << 18)
+#define INTMR2_INTMCIS17               (1 << 17)
+#define INTMR2_INTMCIS16               (1 << 16)
+#define INTMR2_INTMCIS15               (1 << 15)
+#define INTMR2_INTMCIS14               (1 << 14)
+#define INTMR2_INTMCIS13               (1 << 13)
+#define INTMR2_INTMCIS12               (1 << 12)
+#define INTMR2_INTMCIS11               (1 << 11)
+#define INTMR2_INTMCIS10               (1 << 10)
+#define INTMR2_INTMCIS9                        (1 << 9)
+#define INTMR2_INTMCIS8                        (1 << 8)
+#define INTMR2_INTMCIS7                        (1 << 7)
+#define INTMR2_INTMCIS6                        (1 << 6)
+#define INTMR2_INTMCIS5                        (1 << 5)
+#define INTMR2_INTMCIS4                        (1 << 4)
+#define INTMR2_INTMCIS3                        (1 << 3)
+#define INTMR2_INTMCIS2                        (1 << 2)
+#define INTMR2_INTMCIS1                        (1 << 1)
+#define INTMR2_INTMCIS0                        (1 << 0)
+/* Interrupt Status Register 2 from ISP BLK's interrupts to Host IC */
+#define INTSR2                         (MCUCTL+0x38)
+/* Interrupt Mask Status Register 2 from ISP BLK's interrupts to Host IC */
+#define INTMSR2                                (MCUCTL+0x3c)
+/* General Purpose Output Control Register (0~17) */
+#define GPOCTLR                                (MCUCTL+0x40)
+#define GPOCTLR_GPOG17(x)              ((x) << 17)
+#define GPOCTLR_GPOG16(x)              ((x) << 16)
+#define GPOCTLR_GPOG15(x)              ((x) << 15)
+#define GPOCTLR_GPOG14(x)              ((x) << 14)
+#define GPOCTLR_GPOG13(x)              ((x) << 13)
+#define GPOCTLR_GPOG12(x)              ((x) << 12)
+#define GPOCTLR_GPOG11(x)              ((x) << 11)
+#define GPOCTLR_GPOG10(x)              ((x) << 10)
+#define GPOCTLR_GPOG9(x)               ((x) << 9)
+#define GPOCTLR_GPOG8(x)               ((x) << 8)
+#define GPOCTLR_GPOG7(x)               ((x) << 7)
+#define GPOCTLR_GPOG6(x)               ((x) << 6)
+#define GPOCTLR_GPOG5(x)               ((x) << 5)
+#define GPOCTLR_GPOG4(x)               ((x) << 4)
+#define GPOCTLR_GPOG3(x)               ((x) << 3)
+#define GPOCTLR_GPOG2(x)               ((x) << 2)
+#define GPOCTLR_GPOG1(x)               ((x) << 1)
+#define GPOCTLR_GPOG0(x)               ((x) << 0)
+/* General Purpose Pad Output Enable Register (0~17) */
+#define GPOENCTLR                      (MCUCTL+0x44)
+#define GPOENCTLR_GPOEN17(x)           ((x) << 17)
+#define GPOENCTLR_GPOEN16(x)           ((x) << 16)
+#define GPOENCTLR_GPOEN15(x)           ((x) << 15)
+#define GPOENCTLR_GPOEN14(x)           ((x) << 14)
+#define GPOENCTLR_GPOEN13(x)           ((x) << 13)
+#define GPOENCTLR_GPOEN12(x)           ((x) << 12)
+#define GPOENCTLR_GPOEN11(x)           ((x) << 11)
+#define GPOENCTLR_GPOEN10(x)           ((x) << 10)
+#define GPOENCTLR_GPOEN9(x)            ((x) << 9)
+#define GPOENCTLR_GPOEN8(x)            ((x) << 8)
+#define GPOENCTLR_GPOEN7(x)            ((x) << 7)
+#define GPOENCTLR_GPOEN6(x)            ((x) << 6)
+#define GPOENCTLR_GPOEN5(x)            ((x) << 5)
+#define GPOENCTLR_GPOEN4(x)            ((x) << 4)
+#define GPOENCTLR_GPOEN3(x)            ((x) << 3)
+#define GPOENCTLR_GPOEN2(x)            ((x) << 2)
+#define GPOENCTLR_GPOEN1(x)            ((x) << 1)
+#define GPOENCTLR_GPOEN0(x)            ((x) << 0)
+/* General Purpose Input Control Register (0~17) */
+#define GPICTLR                                (MCUCTL+0x48)
+/* IS Shared Register 0 between ISP CPU and HOST CPU */
+#define ISSR0                  (MCUCTL+0x80)
+/* Command Host -> IS */
+/* IS Shared Register 1 between ISP CPU and HOST CPU */
+/* Sensor ID for Command */
+#define ISSR1                  (MCUCTL+0x84)
+/* IS Shared Register 2 between ISP CPU and HOST CPU */
+/* Parameter 1 */
+#define ISSR2                  (MCUCTL+0x88)
+/* IS Shared Register 3 between ISP CPU and HOST CPU */
+/* Parameter 2 */
+#define ISSR3                  (MCUCTL+0x8c)
+/* IS Shared Register 4 between ISP CPU and HOST CPU */
+/* Parameter 3 */
+#define ISSR4                  (MCUCTL+0x90)
+/* IS Shared Register 5 between ISP CPU and HOST CPU */
+/* Parameter 4 */
+#define ISSR5                  (MCUCTL+0x94)
+#define ISSR6                  (MCUCTL+0x98)
+#define ISSR7                  (MCUCTL+0x9c)
+#define ISSR8                  (MCUCTL+0xa0)
+#define ISSR9                  (MCUCTL+0xa4)
+/* IS Shared Register 10 between ISP CPU and HOST CPU */
+/* Command IS -> Host */
+#define ISSR10                 (MCUCTL+0xa8)
+/* IS Shared Register 11 between ISP CPU and HOST CPU */
+/* Sensor ID for Command */
+#define ISSR11                 (MCUCTL+0xac)
+/* IS Shared Register 12 between ISP CPU and HOST CPU */
+/* Parameter 1 */
+#define ISSR12                 (MCUCTL+0xb0)
+/* IS Shared Register 13 between ISP CPU and HOST CPU */
+/* Parameter 2 */
+#define ISSR13                 (MCUCTL+0xb4)
+/* IS Shared Register 14 between ISP CPU and HOST CPU */
+/* Parameter 3 */
+#define ISSR14                 (MCUCTL+0xb8)
+/* IS Shared Register 15 between ISP CPU and HOST CPU */
+/* Parameter 4 */
+#define ISSR15                 (MCUCTL+0xbc)
+#define ISSR16                 (MCUCTL+0xc0)
+#define ISSR17                 (MCUCTL+0xc4)
+#define ISSR18                 (MCUCTL+0xc8)
+#define ISSR19                 (MCUCTL+0xcc)
+/* IS Shared Register 20 between ISP CPU and HOST CPU */
+/* ISP_FRAME_DONE : SENSOR ID */
+#define ISSR20                 (MCUCTL+0xd0)
+/* IS Shared Register 21 between ISP CPU and HOST CPU */
+/* ISP_FRAME_DONE : PARAMETER 1 */
+#define ISSR21                 (MCUCTL+0xd4)
+#define ISSR22                 (MCUCTL+0xd8)
+#define ISSR23                 (MCUCTL+0xdc)
+/* IS Shared Register 24 between ISP CPU and HOST CPU */
+/* SCALERC_FRAME_DONE : SENSOR ID */
+#define ISSR24                 (MCUCTL+0xe0)
+/* IS Shared Register 25 between ISP CPU and HOST CPU */
+/* SCALERC_FRAME_DONE : PARAMETER 1 */
+#define ISSR25                 (MCUCTL+0xe4)
+#define ISSR26                 (MCUCTL+0xe8)
+#define ISSR27                 (MCUCTL+0xec)
+/* IS Shared Register 28 between ISP CPU and HOST CPU */
+/* 3DNR_FRAME_DONE : SENSOR ID */
+#define ISSR28                 (MCUCTL+0xf0)
+/* IS Shared Register 29 between ISP CPU and HOST CPU */
+/* 3DNR_FRAME_DONE : PARAMETER 1 */
+#define ISSR29                 (MCUCTL+0xf4)
+#define ISSR30                 (MCUCTL+0xf8)
+#define ISSR31                 (MCUCTL+0xfc)
+/* IS Shared Register 32 between ISP CPU and HOST CPU */
+/* SCALERP_FRAME_DONE : SENSOR ID */
+#define ISSR32                 (MCUCTL+0x100)
+/* IS Shared Register 33 between ISP CPU and HOST CPU */
+/* SCALERP_FRAME_DONE : PARAMETER 1 */
+#define ISSR33                 (MCUCTL+0x104)
+#define ISSR34                 (MCUCTL+0x108)
+#define ISSR35                 (MCUCTL+0x10c)
+#define ISSR36                 (MCUCTL+0x110)
+#define ISSR37                 (MCUCTL+0x114)
+#define ISSR38                 (MCUCTL+0x118)
+#define ISSR39                 (MCUCTL+0x11c)
+#define ISSR40                 (MCUCTL+0x120)
+#define ISSR41                 (MCUCTL+0x124)
+#define ISSR42                 (MCUCTL+0x128)
+#define ISSR43                 (MCUCTL+0x12c)
+#define ISSR44                 (MCUCTL+0x130)
+#define ISSR45                 (MCUCTL+0x134)
+#define ISSR46                 (MCUCTL+0x138)
+#define ISSR47                 (MCUCTL+0x13c)
+#define ISSR48                 (MCUCTL+0x140)
+#define ISSR49                 (MCUCTL+0x144)
+#define ISSR50                 (MCUCTL+0x148)
+#define ISSR51                 (MCUCTL+0x14c)
+#define ISSR52                 (MCUCTL+0x150)
+#define ISSR53                 (MCUCTL+0x154)
+#define ISSR54                 (MCUCTL+0x158)
+#define ISSR55                 (MCUCTL+0x15c)
+#define ISSR56                 (MCUCTL+0x160)
+#define ISSR57                 (MCUCTL+0x164)
+#define ISSR58                 (MCUCTL+0x168)
+#define ISSR59                 (MCUCTL+0x16c)
+#define ISSR60                 (MCUCTL+0x170)
+#define ISSR61                 (MCUCTL+0x174)
+#define ISSR62                 (MCUCTL+0x178)
+#define ISSR63                 (MCUCTL+0x17c)
+
+/* PMU for FIMC-IS*/
+#if defined(CONFIG_SOC_EXYNOS4415)
+#define PMUREG_CMU_RESET_ISP0_SYS_PWR          (S5P_VA_PMU  + 0x1594)
+#define PMUREG_ISP0_CONFIGURATION              (S5P_VA_PMU  + 0x40A0)
+#define PMUREG_ISP0_STATUS                     (S5P_VA_PMU  + 0x40A4)
+#define PMUREG_ISP0_OPTION                     (S5P_VA_PMU  + 0x40A8)
+
+#define PMUREG_CMU_RESET_ISP1_SYS_PWR          (S5P_VA_PMU  + 0x159C)
+#define PMUREG_ISP1_CONFIGURATION              (S5P_VA_PMU  + 0x40E0)
+#define PMUREG_ISP1_STATUS                     (S5P_VA_PMU  + 0x40E4)
+#define PMUREG_ISP1_OPTION                     (S5P_VA_PMU  + 0x40E8)
+
+#define PMUREG_CENTRAL_SEQ_OPTION              (S5P_VA_PMU  + 0x0208)
+#define PMUREG_ISP_ARM_SYS_PWR_REG             (S5P_VA_PMU  + 0x1050)
+#define PMUREG_ISP_ARM_CONFIGURATION           (S5P_VA_PMU  + 0x2280)
+#define PMUREG_ISP_ARM_STATUS                  (S5P_VA_PMU  + 0x2284)
+#define PMUREG_ISP_ARM_OPTION                  (S5P_VA_PMU  + 0x2288)
+
+#define PMUREG_ISP_LOW_POWER_OFF               (S5P_VA_PMU  + 0x0004)
+
+#define PMUREG_ISP0_STATUS                     (S5P_VA_PMU  + 0x40A4)
+#define PMUREG_ISP1_STATUS                     (S5P_VA_PMU  + 0x40E4)
+
+#define MIPICSI0_REG_BASE                      (S5P_VA_MIPICSI0)   /* phy : 0x120C_0000 */
+#define MIPICSI1_REG_BASE                      (S5P_VA_MIPICSI1)   /* phy : 0x120D_0000 */
+#define MIPICSI2_REG_BASE                      0
+
+#define FIMCLITE0_REG_BASE                     (S5P_VA_FIMCLITE0)  /* phy : 0x120A0000 */
+#define FIMCLITE1_REG_BASE                     (S5P_VA_FIMCLITE1)  /* phy : 0x120B0000 */
+#define FIMCLITE2_REG_BASE                     (S5P_VA_FIMCLITE2)  /* phy : 0x122A0000 */
+
+#define PA_FIMC_IS_GIC_C                       (0x121E0000)
+#define PA_FIMC_IS_GIC_D                       (0x121F0000)
+#else
+#define MIPICSI0_REG_BASE                       (S5P_VA_MIPICSI0)
+#define MIPICSI1_REG_BASE                       (S5P_VA_MIPICSI1)
+#define MIPICSI2_REG_BASE                      (S5P_VA_MIPICSI2)
+
+#define FIMCLITE0_REG_BASE                      (S5P_VA_FIMCLITE0)
+#define FIMCLITE1_REG_BASE                      (S5P_VA_FIMCLITE1)
+#define FIMCLITE2_REG_BASE                      (S5P_VA_FIMCLITE2)
+
+#if defined(CONFIG_SOC_EXYNOS3470)
+#define PMUREG_ISP_ARM_CONFIGURATION            (S5P_VA_PMU  + 0x2280)
+#define PMUREG_ISP_ARM_STATUS                   (S5P_VA_PMU  + 0x2284)
+#define PMUREG_ISP_ARM_OPTION                   (S5P_VA_PMU  + 0x2288)
+#define PMUREG_ISP_LOW_POWER_OFF                (S5P_VA_PMU  + 0x0004)
+#define PMUREG_ISP_CONFIGURATION                (S5P_VA_PMU  + 0x3CA0)
+#define PMUREG_ISP_STATUS                       (S5P_VA_PMU  + 0x3CA4)
+#define PMUREG_ISP_ARM_SYS_PWR_REG              (S5P_VA_PMU  + 0x1050)
+#elif defined(CONFIG_SOC_EXYNOS5422)
+#define PMUREG_ISP_ARM_CONFIGURATION            (S5P_VA_PMU  + 0x2480)
+#define PMUREG_ISP_ARM_STATUS                   (S5P_VA_PMU  + 0x2484)
+#define PMUREG_ISP_ARM_OPTION                   (S5P_VA_PMU  + 0x2488)
+#define PMUREG_ISP_LOW_POWER_OFF                (S5P_VA_PMU  + 0x0004)
+#define PMUREG_ISP_CONFIGURATION                (S5P_VA_PMU  + 0x4020)
+#define PMUREG_ISP_STATUS                       (S5P_VA_PMU  + 0x4024)
+#define PMUREG_CMU_RESET_ISP_SYS_PWR_REG               (S5P_VA_PMU  + 0x1584)
+#define PMUREG_CMU_SYSCLK_ISP_SYS_PWR_REG       (S5P_VA_PMU  + 0x14C4)
+#define PMUREG_ISP_ARM_SYS_PWR_REG              (S5P_VA_PMU  + 0x1090)
+#define PMUREG_CAM_CONFIGURATION                (S5P_VA_PMU  + 0x5100)
+#define PMUREG_CAM_STATUS                                              (S5P_VA_PMU  + 0x5104)
+#else
+#define PMUREG_ISP_ARM_CONFIGURATION           (S5P_VA_PMU  + 0x2580)
+#define PMUREG_ISP_ARM_STATUS                  (S5P_VA_PMU  + 0x2584)
+#define PMUREG_ISP_ARM_OPTION                  (S5P_VA_PMU  + 0x2588)
+#define PMUREG_ISP_LOW_POWER_OFF               (S5P_VA_PMU  + 0x0004)
+#define PMUREG_ISP_CONFIGURATION               (S5P_VA_PMU  + 0x4140)
+#define PMUREG_ISP_STATUS                      (S5P_VA_PMU  + 0x4144)
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+#define PMUREG_CAM0_STATUS                     (S5P_VA_PMU  + 0x4024)
+#define PMUREG_CAM1_STATUS                     (S5P_VA_PMU  + 0x40A4)
+#endif
+
+#define SYSREG_GSCBLK_CFG1                     (S3C_VA_SYS + 0x0224)
+#define SYSREG_ISPBLK_CFG                      (S3C_VA_SYS + 0x022C)
+
+/* GIC for FIMC-IS*/
+#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+#define PA_FIMC_IS_GIC_C                       (0x141E0000)
+#define PA_FIMC_IS_GIC_D                       (0x141F0000)
+#elif defined(CONFIG_SOC_EXYNOS3470)
+#define PA_FIMC_IS_GIC_C                       (0x121E0000)
+#define PA_FIMC_IS_GIC_D                       (0x121F0000)
+#else
+#define PA_FIMC_IS_GIC_C                       (0x131E0000)
+#define PA_FIMC_IS_GIC_D                       (0x131F0000)
+#endif
+#endif
+
+/* PWM for FIMC-IS*/
+#define FIMC_IS_PWM_TCNTB0                     (0xC)
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-resourcemgr.c b/drivers/media/platform/exynos/fimc-is/fimc-is-resourcemgr.c
new file mode 100644 (file)
index 0000000..ad2518f
--- /dev/null
@@ -0,0 +1,225 @@
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-core.h"
+#include "fimc-is-dvfs.h"
+#include "fimc-is-clk-gate.h"
+#include "fimc-is-hw.h"
+
+struct pm_qos_request exynos_isp_qos_cpu_min;
+struct pm_qos_request exynos_isp_qos_cpu_max;
+struct pm_qos_request exynos_isp_qos_int;
+struct pm_qos_request exynos_isp_qos_mem;
+struct pm_qos_request exynos_isp_qos_cam;
+struct pm_qos_request exynos_isp_qos_disp;
+#if defined(CONFIG_SOC_EXYNOS5422) || defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5433)
+struct pm_qos_request max_cpu_qos;
+#endif
+
+extern struct fimc_is_sysfs_debug sysfs_debug;
+
+int fimc_is_resource_probe(struct fimc_is_resourcemgr *resourcemgr,
+       void *private_data)
+{
+       int ret = 0;
+
+       BUG_ON(!resourcemgr);
+       BUG_ON(!private_data);
+
+       resourcemgr->private_data = private_data;
+
+       atomic_set(&resourcemgr->rsccount, 0);
+       atomic_set(&resourcemgr->resource_sensor0.rsccount, 0);
+       atomic_set(&resourcemgr->resource_sensor1.rsccount, 0);
+       atomic_set(&resourcemgr->resource_ischain.rsccount, 0);
+
+#ifdef ENABLE_DVFS
+       /* dvfs controller init */
+       ret = fimc_is_dvfs_init(resourcemgr);
+       if (ret)
+               err("%s: fimc_is_dvfs_init failed!\n", __func__);
+#endif
+
+       info("%s\n", __func__);
+       return ret;
+}
+
+int fimc_is_resource_get(struct fimc_is_resourcemgr *resourcemgr, u32 rsc_type)
+{
+       int ret = 0;
+       u32 rsccount;
+       struct fimc_is_resource *resource;
+       struct fimc_is_core *core;
+
+       BUG_ON(!resourcemgr);
+       BUG_ON(!resourcemgr->private_data);
+       BUG_ON(rsc_type >= RESOURCE_TYPE_MAX);
+
+       resource = GET_RESOURCE(resourcemgr, rsc_type);
+       core = (struct fimc_is_core *)resourcemgr->private_data;
+       rsccount = atomic_read(&core->rsccount);
+
+       if (rsccount >= 5) {
+               err("[RSC] Invalid rsccount(%d)", rsccount);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       if (rsccount == 0) {
+#ifdef ENABLE_DVFS
+               /* dvfs controller init */
+               ret = fimc_is_dvfs_init(resourcemgr);
+               if (ret) {
+                       err("%s: fimc_is_dvfs_init failed!\n", __func__);
+                       goto p_err;
+               }
+#endif
+       }
+
+       if (atomic_read(&resource->rsccount) == 0) {
+               switch (rsc_type) {
+               case RESOURCE_TYPE_SENSOR0:
+                       break;
+               case RESOURCE_TYPE_SENSOR1:
+                       break;
+               case RESOURCE_TYPE_ISCHAIN:
+                       core->debug_cnt = 0;
+
+                       ret = fimc_is_interface_open(&core->interface);
+                       if (ret) {
+                               err("fimc_is_interface_open is fail(%d)", ret);
+                               goto p_err;
+                       }
+
+                       ret = fimc_is_ischain_power(&core->ischain[0], 1);
+                       if (ret) {
+                               err("fimc_is_ischain_power is fail (%d)", ret);
+                               goto p_err;
+                       }
+
+                       /* W/A for a lower version MCUCTL */
+                       fimc_is_interface_reset(&core->interface);
+
+#ifdef ENABLE_CLOCK_GATE
+                       if (sysfs_debug.en_clk_gate &&
+                                       sysfs_debug.clk_gate_mode == CLOCK_GATE_MODE_HOST)
+                               fimc_is_clk_gate_init(core);
+#endif
+                       break;
+               default:
+                       err("[RSC] resource type(%d) is invalid", rsc_type);
+                       BUG();
+                       break;
+               }
+       }
+
+       atomic_inc(&resource->rsccount);
+       atomic_inc(&core->rsccount);
+
+p_err:
+       info("[RSC] rsctype : %d, rsccount : %d\n", rsc_type, rsccount);
+       return ret;
+}
+
+int fimc_is_resource_put(struct fimc_is_resourcemgr *resourcemgr, u32 rsc_type)
+{
+       int ret = 0;
+       u32 rsccount;
+       struct fimc_is_resource *resource;
+       struct fimc_is_core *core;
+
+       BUG_ON(!resourcemgr);
+       BUG_ON(!resourcemgr->private_data);
+       BUG_ON(rsc_type >= RESOURCE_TYPE_MAX);
+
+       resource = GET_RESOURCE(resourcemgr, rsc_type);
+       core = (struct fimc_is_core *)resourcemgr->private_data;
+       rsccount = atomic_read(&core->rsccount);
+
+       if (rsccount == 0) {
+               err("[RSC] Invalid rsccount(%d)\n", rsccount);
+               ret = -EMFILE;
+               goto p_err;
+       }
+
+       if (atomic_read(&resource->rsccount) == 1) {
+               switch (rsc_type) {
+               case RESOURCE_TYPE_SENSOR0:
+                       break;
+               case RESOURCE_TYPE_SENSOR1:
+                       break;
+               case RESOURCE_TYPE_ISCHAIN:
+                       ret = fimc_is_itf_power_down(&core->interface);
+                       if (ret)
+                               err("power down cmd is fail(%d)", ret);
+
+                       ret = fimc_is_ischain_power(&core->ischain[0], 0);
+                       if (ret)
+                               err("fimc_is_ischain_power is fail(%d)", ret);
+
+                       ret = fimc_is_interface_close(&core->interface);
+                       if (ret)
+                               err("fimc_is_interface_close is fail(%d)", ret);
+#ifndef RESERVED_MEM
+                       /* 5. Dealloc memroy */
+                       ret = fimc_is_ishcain_deinitmem(&core->ischain[0]);
+                       if (ret)
+                               err("fimc_is_ishcain_deinitmem is fail(%d)", ret);
+#endif
+                       break;
+
+               default:
+                       err("[RSC] resource type(%d) is invalid", rsc_type);
+                       BUG();
+                       break;
+               }
+       }
+
+       /* global update */
+       if (atomic_read(&core->rsccount) == 1) {
+               ret = fimc_is_runtime_suspend_post(NULL);
+               if (ret)
+                       err("fimc_is_runtime_suspend_post is fail(%d)", ret);
+       }
+
+       atomic_dec(&resource->rsccount);
+       atomic_dec(&core->rsccount);
+
+p_err:
+       info("[RSC] rsctype : %d, rsccount : %d\n", rsc_type, rsccount);
+       return ret;
+}
+
+int fimc_is_logsync(struct fimc_is_interface *itf, u32 sync_id, u32 msg_test_id)
+{
+       int ret = 0;
+
+       /* print kernel sync log */
+       log_sync(sync_id);
+
+#ifdef ENABLE_FW_SYNC_LOG
+       ret = fimc_is_hw_msg_test(itf, sync_id, msg_test_id);
+       if (ret)
+               err("fimc_is_hw_msg_test(%d)", ret);
+#endif
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-resourcemgr.h b/drivers/media/platform/exynos/fimc-is/fimc-is-resourcemgr.h
new file mode 100644 (file)
index 0000000..51c9e98
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_RESOURCE_MGR_H
+#define FIMC_IS_RESOURCE_MGR_H
+
+#include "fimc-is-groupmgr.h"
+#include "fimc-is-interface.h"
+
+#define RESOURCE_TYPE_SENSOR0  0
+#define RESOURCE_TYPE_SENSOR1  1
+#define RESOURCE_TYPE_ISCHAIN  2
+#define RESOURCE_TYPE_MAX      3
+
+struct fimc_is_dvfs_ctrl {
+       struct mutex lock;
+       int cur_cpu_min_qos;
+       int cur_cpu_max_qos;
+       int cur_int_qos;
+       int cur_mif_qos;
+       int cur_cam_qos;
+       int cur_i2c_qos;
+       int cur_disp_qos;
+
+       struct fimc_is_dvfs_scenario_ctrl *static_ctrl;
+       struct fimc_is_dvfs_scenario_ctrl *dynamic_ctrl;
+};
+
+struct fimc_is_clk_gate_ctrl {
+       spinlock_t lock;
+       unsigned long msk_state;
+       int msk_cnt[GROUP_ID_MAX];
+       u32 msk_lock_by_ischain[FIMC_IS_MAX_NODES];
+       struct exynos_fimc_is_clk_gate_info *gate_info;
+       u32 msk_clk_on_off_state; /* on/off(1/0) state per ip */
+       /*
+        * For check that there's too long clock-on period.
+        * This var will increase when clock on,
+        * And will decrease when clock off.
+        */
+       unsigned long chk_on_off_cnt[GROUP_ID_MAX];
+};
+
+struct fimc_is_resource {
+        struct platform_device                  *pdev;
+        void __iomem                            *regs;
+        atomic_t                                rsccount;
+        u32                                     private_data;
+};
+
+struct fimc_is_resourcemgr {
+       atomic_t                                rsccount;
+       atomic_t                                rsccount_module; /* sensor module */
+       struct fimc_is_resource                 resource_sensor0;
+       struct fimc_is_resource                 resource_sensor1;
+       struct fimc_is_resource                 resource_ischain;
+
+       struct fimc_is_dvfs_ctrl                dvfs_ctrl;
+       struct fimc_is_clk_gate_ctrl            clk_gate_ctrl;
+
+       void                                    *private_data;
+};
+
+int fimc_is_resource_probe(struct fimc_is_resourcemgr *resourcemgr,
+       void *private_data);
+int fimc_is_resource_get(struct fimc_is_resourcemgr *resourcemgr, u32 rsc_type);
+int fimc_is_resource_put(struct fimc_is_resourcemgr *resourcemgr, u32 rsc_type);
+int fimc_is_logsync(struct fimc_is_interface *itf, u32 sync_id, u32 msg_test_id);
+
+
+#define GET_RESOURCE(resourcemgr, type) \
+       ((type == RESOURCE_TYPE_SENSOR0) ? &resourcemgr->resource_sensor0 : \
+       ((type == RESOURCE_TYPE_SENSOR1) ? &resourcemgr->resource_sensor1 : \
+       &resourcemgr->resource_ischain))
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-sec-define.c b/drivers/media/platform/exynos/fimc-is/fimc-is-sec-define.c
new file mode 100644 (file)
index 0000000..4e52cf0
--- /dev/null
@@ -0,0 +1,2626 @@
+#include "fimc-is-sec-define.h"
+#include <mach/pinctrl-samsung.h>
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR) || defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+#include <linux/i2c.h>
+#endif
+
+bool crc32_fw_check = true;
+bool crc32_check = true;
+bool crc32_check_factory = true;
+bool crc32_header_check = true;
+bool crc32_check_front = true;
+bool crc32_header_check_front = true;
+bool crc32_check_factory_front = true;
+bool fw_version_crc_check = true;
+bool is_latest_cam_module = false;
+bool is_final_cam_module = false;
+#if defined(CONFIG_SOC_EXYNOS5433)
+bool is_right_prj_name = true;
+#endif
+#ifdef CONFIG_COMPANION_USE
+bool crc32_c1_fw_check = true;
+bool crc32_c1_check = true;
+bool crc32_c1_check_factory = true;
+bool companion_lsc_isvalid = false;
+bool companion_coef_isvalid = false;
+#endif
+u8 cal_map_version[4] = {0,};
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+#define FIMC_IS_MAX_CAL_SIZE   (8 * 1024)
+#else
+#define FIMC_IS_MAX_CAL_SIZE   (64 * 1024)
+#endif
+#define FIMC_IS_MAX_CAL_SIZE_FRONT     (8 * 1024)
+
+#define FIMC_IS_DEFAULT_CAL_SIZE       (20 * 1024)
+#define FIMC_IS_DUMP_CAL_SIZE  (172 * 1024)
+#define FIMC_IS_LATEST_FROM_VERSION_B  'B'
+#define FIMC_IS_LATEST_FROM_VERSION_C  'C'
+#define FIMC_IS_LATEST_FROM_VERSION_D  'D'
+#define FIMC_IS_LATEST_FROM_VERSION_M  'M'
+
+
+//static bool is_caldata_read = false;
+//static bool is_c1_caldata_read = false;
+static bool force_caldata_dump = false;
+static int cam_id = CAMERA_SINGLE_REAR;
+bool is_dumped_fw_loading_needed = false;
+bool is_dumped_c1_fw_loading_needed = false;
+char fw_core_version;
+//struct class *camera_class;
+//struct device *camera_front_dev; /*sys/class/camera/front*/
+//struct device *camera_rear_dev; /*sys/class/camera/rear*/
+static struct fimc_is_from_info sysfs_finfo;
+static struct fimc_is_from_info sysfs_pinfo;
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+static struct fimc_is_from_info sysfs_finfo_front;
+static struct fimc_is_from_info sysfs_pinfo_front;
+static char cal_buf_front[FIMC_IS_MAX_CAL_SIZE_FRONT];
+#endif
+
+static char cal_buf[FIMC_IS_MAX_CAL_SIZE];
+char loaded_fw[12] = {0, };
+char loaded_companion_fw[30] = {0, };
+
+int fimc_is_sec_set_force_caldata_dump(bool fcd)
+{
+       force_caldata_dump = fcd;
+       if (fcd)
+               pr_info("forced caldata dump enabled!!\n");
+       return 0;
+}
+
+int fimc_is_sec_get_sysfs_finfo(struct fimc_is_from_info **finfo)
+{
+       *finfo = &sysfs_finfo;
+       return 0;
+}
+
+int fimc_is_sec_get_sysfs_pinfo(struct fimc_is_from_info **pinfo)
+{
+       *pinfo = &sysfs_pinfo;
+       return 0;
+}
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+int fimc_is_sec_get_sysfs_finfo_front(struct fimc_is_from_info **finfo)
+{
+       *finfo = &sysfs_finfo_front;
+       return 0;
+}
+
+int fimc_is_sec_get_sysfs_pinfo_front(struct fimc_is_from_info **pinfo)
+{
+       *pinfo = &sysfs_pinfo_front;
+       return 0;
+}
+
+int fimc_is_sec_get_front_cal_buf(char **buf)
+{
+       *buf = &cal_buf_front[0];
+       return 0;
+}
+#endif
+
+int fimc_is_sec_get_cal_buf(char **buf)
+{
+       *buf = &cal_buf[0];
+       return 0;
+}
+
+int fimc_is_sec_get_loaded_fw(char **buf)
+{
+       *buf = &loaded_fw[0];
+       return 0;
+}
+
+int fimc_is_sec_get_loaded_c1_fw(char **buf)
+{
+       *buf = &loaded_companion_fw[0];
+       return 0;
+}
+
+int fimc_is_sec_set_camid(int id)
+{
+       cam_id = id;
+       return 0;
+}
+
+int fimc_is_sec_get_camid(void)
+{
+       return cam_id;
+}
+
+int fimc_is_sec_get_camid_from_hal(char *fw_name, char *setf_name)
+{
+#if 0
+       char buf[1];
+       loff_t pos = 0;
+       int pixelSize;
+
+       read_data_from_file("/data/CameraID.txt", buf, 1, &pos);
+       if (buf[0] == '0')
+               cam_id = CAMERA_SINGLE_REAR;
+       else if (buf[0] == '1')
+               cam_id = CAMERA_SINGLE_FRONT;
+       else if (buf[0] == '2')
+               cam_id = CAMERA_DUAL_REAR;
+       else if (buf[0] == '3')
+               cam_id = CAMERA_DUAL_FRONT;
+
+       if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_3L2)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_3L2), "%s", FIMC_IS_FW_3L2);
+               snprintf(setf_name, sizeof(FIMC_IS_3L2_SETF), "%s", FIMC_IS_3L2_SETF);
+       } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_IMX135)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW), "%s", FIMC_IS_FW);
+               snprintf(setf_name, sizeof(FIMC_IS_IMX135_SETF), "%s", FIMC_IS_IMX135_SETF);
+       } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_IMX134)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_IMX134), "%s", FIMC_IS_FW_IMX134);
+               snprintf(setf_name, sizeof(FIMC_IS_IMX134_SETF), "%s", FIMC_IS_IMX134_SETF);
+       } else {
+               pixelSize = fimc_is_sec_get_pixel_size(sysfs_finfo.header_ver);
+               if (pixelSize == 13) {
+                       snprintf(fw_name, sizeof(FIMC_IS_FW), "%s", FIMC_IS_FW);
+                       snprintf(setf_name, sizeof(FIMC_IS_IMX135_SETF), "%s", FIMC_IS_IMX135_SETF);
+               } else if (pixelSize == 8) {
+                       snprintf(fw_name, sizeof(FIMC_IS_FW_IMX134), "%s", FIMC_IS_FW_IMX134);
+                       snprintf(setf_name, sizeof(FIMC_IS_IMX134_SETF), "%s", FIMC_IS_IMX134_SETF);
+               } else {
+                       snprintf(fw_name, sizeof(FIMC_IS_FW), "%s", FIMC_IS_FW);
+                       snprintf(setf_name, sizeof(FIMC_IS_IMX135_SETF), "%s", FIMC_IS_IMX135_SETF);
+               }
+       }
+
+       if (cam_id == CAMERA_SINGLE_FRONT ||
+               cam_id == CAMERA_DUAL_FRONT) {
+               snprintf(setf_name, sizeof(FIMC_IS_6B2_SETF), "%s", FIMC_IS_6B2_SETF);
+       }
+#else
+       pr_err("%s: waring, you're calling the disabled func!\n\n", __func__);
+#endif
+       return 0;
+}
+
+int fimc_is_sec_fw_revision(char *fw_ver)
+{
+       int revision = 0;
+       revision = revision + ((int)fw_ver[FW_PUB_YEAR] - 58) * 10000;
+       revision = revision + ((int)fw_ver[FW_PUB_MON] - 64) * 100;
+       revision = revision + ((int)fw_ver[FW_PUB_NUM] - 48) * 10;
+       revision = revision + (int)fw_ver[FW_PUB_NUM + 1] - 48;
+
+       return revision;
+}
+
+bool fimc_is_sec_fw_module_compare(char *fw_ver1, char *fw_ver2)
+{
+       if (fw_ver1[FW_CORE_VER] != fw_ver2[FW_CORE_VER]
+               || fw_ver1[FW_PIXEL_SIZE] != fw_ver2[FW_PIXEL_SIZE]
+               || fw_ver1[FW_PIXEL_SIZE + 1] != fw_ver2[FW_PIXEL_SIZE + 1]
+               || fw_ver1[FW_ISP_COMPANY] != fw_ver2[FW_ISP_COMPANY]
+               || fw_ver1[FW_SENSOR_MAKER] != fw_ver2[FW_SENSOR_MAKER]) {
+               return false;
+       }
+
+       return true;
+}
+
+bool fimc_is_sec_check_cal_crc32(char *buf, int id)
+{
+       u32 *buf32 = NULL;
+       u32 checksum;
+       u32 check_base;
+       u32 check_length;
+       u32 checksum_base;
+       bool crc32_temp, crc32_header_temp;
+       struct fimc_is_from_info *finfo = NULL;
+
+       buf32 = (u32 *)buf;
+
+       printk(KERN_INFO "+++ %s\n", __func__);
+
+
+       crc32_temp = true;
+#ifdef CONFIG_COMPANION_USE
+       crc32_c1_check = true;
+#endif
+
+       /* Header data */
+       check_base = 0;
+       checksum = 0;
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               finfo = &sysfs_finfo_front;
+               checksum_base = ((check_base & 0xffffff00) + 0xfc) / 4;
+       } else
+#endif
+       {
+               finfo = &sysfs_finfo;
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+               checksum_base = ((check_base & 0xffffff00) + 0xfc) / 4;
+#else
+               checksum_base = ((check_base & 0xfffff000) + 0xffc) / 4;
+#endif
+       }
+
+       checksum = getCRC((u16 *)&buf32[check_base], HEADER_CRC32_LEN, NULL, NULL);
+       if (checksum_base < 0x80000 && checksum_base > 0 && checksum != buf32[checksum_base]) {
+               err("Camera: CRC32 error at the header (0x%08X != 0x%08X)",
+                                       checksum, buf32[checksum_base]);
+               crc32_temp = false;
+               crc32_header_temp = false;
+       } else if (checksum_base > 0x80000 || checksum_base < 0) {
+               err("Camera: Header checksum address has error(0x%08X)", checksum_base * 4);
+       } else {
+               crc32_header_temp = true;
+       }
+
+       /* OEM */
+       check_base = finfo->oem_start_addr / 4;
+       checksum = 0;
+       check_length = (finfo->oem_end_addr - finfo->oem_start_addr + 1) / 2;
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               checksum_base = ((finfo->oem_end_addr & 0xffffff00) + 0xfc) / 4;
+       } else
+#endif
+       {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+               checksum_base = ((finfo->oem_end_addr & 0xffffff00) + 0xfc) / 4;
+#else
+               checksum_base = ((finfo->oem_end_addr & 0xfffff000) + 0xffc) / 4;
+#endif
+       }
+
+       checksum = getCRC((u16 *)&buf32[check_base],
+                                       check_length, NULL, NULL);
+       if (checksum_base < 0x80000 && checksum_base > 0 && checksum != buf32[checksum_base]) {
+               err("Camera: CRC32 error at the OEM (0x%08X != 0x%08X)",
+                                       checksum, buf32[checksum_base]);
+               crc32_temp = false;
+       } else if (checksum_base > 0x80000 || checksum_base < 0) {
+               err("Camera: OEM checksum address has error(0x%08X)", checksum_base * 4);
+       }
+
+       /* AWB */
+       check_base = finfo->awb_start_addr / 4;
+       checksum = 0;
+       check_length = (finfo->awb_end_addr - finfo->awb_start_addr + 1) / 2;
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               checksum_base = ((finfo->awb_end_addr & 0xffffff00) + 0xfc) / 4;
+       } else
+#endif
+       {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+               checksum_base = ((finfo->awb_end_addr & 0xffffff00) + 0xfc) / 4;
+#else
+               checksum_base = ((finfo->awb_end_addr & 0xfffff000) + 0xffc) / 4;
+#endif
+       }
+
+       checksum = getCRC((u16 *)&buf32[check_base],
+                                       check_length, NULL, NULL);
+       if (checksum_base < 0x80000 && checksum_base > 0 && checksum != buf32[checksum_base]) {
+               err("Camera: CRC32 error at the AWB (0x%08X != 0x%08X)",
+                                       checksum, buf32[checksum_base]);
+               crc32_temp = false;
+       } else if (checksum_base > 0x80000 || checksum_base < 0) {
+               err("Camera: AWB checksum address has error(0x%08X)", checksum_base * 4);
+       }
+
+       /* Shading */
+       check_base = finfo->shading_start_addr / 4;
+       checksum = 0;
+       check_length = (finfo->shading_end_addr - finfo->shading_start_addr + 1) / 2;
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               checksum_base = 0x1ffc / 4;
+       } else
+#endif
+       {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+               checksum_base = 0x1ffc / 4;
+#else
+               checksum_base = ((finfo->shading_end_addr & 0xfffff000) + 0xffc) / 4;
+#endif
+       }
+
+       checksum = getCRC((u16 *)&buf32[check_base],
+                                       check_length, NULL, NULL);
+       if (checksum_base < 0x80000 && checksum_base > 0 && checksum != buf32[checksum_base]) {
+               err("Camera: CRC32 error at the Shading (0x%08X != 0x%08X)",
+                               checksum, buf32[checksum_base]);
+               crc32_temp = false;
+       } else if (checksum_base > 0x80000 || checksum_base < 0) {
+               err("Camera: Shading checksum address has error(0x%08X)", checksum_base * 4);
+       }
+
+#ifdef CONFIG_COMPANION_USE
+       /* pdaf cal */
+       check_base = finfo->pdaf_cal_start_addr / 4;
+       checksum = 0;
+       check_length = (finfo->pdaf_cal_end_addr - finfo->pdaf_cal_start_addr + 1) / 2;
+       checksum_base = ((0x8FFF & 0xfffff000) + 0xffc) / 4;
+
+       checksum = getCRC((u16 *)&buf32[check_base],
+                                       check_length, NULL, NULL);
+       if (checksum_base < 0x80000 && checksum_base > 0 && checksum != buf32[checksum_base]) {
+               err("Camera: CRC32 error at the pdaf cal (0x%08X != 0x%08X)",
+                               checksum, buf32[checksum_base]);
+               crc32_temp = false;
+       } else if (checksum_base > 0x80000 || checksum_base < 0) {
+               err("Camera: pdaf cal checksum address has error(0x%08X)", checksum_base * 4);
+       }
+
+       /* concord cal */
+       check_base = finfo->concord_cal_start_addr / 4;
+       checksum = 0;
+       check_length = (finfo->concord_cal_end_addr - finfo->concord_cal_start_addr + 1) / 2;
+       checksum_base = ((finfo->concord_cal_end_addr & 0xfffff000) + 0xffc) / 4;
+
+       checksum = getCRC((u16 *)&buf32[check_base],
+                                       check_length, NULL, NULL);
+       if (checksum_base < 0x80000 && checksum_base > 0 && checksum != buf32[checksum_base]) {
+               err("Camera: CRC32 error at the concord cal (0x%08X != 0x%08X)",
+                               checksum, buf32[checksum_base]);
+               crc32_c1_check = false;
+       } else if (checksum_base > 0x80000 || checksum_base < 0) {
+               err("Camera: concord cal checksum address has error(0x%08X)", checksum_base * 4);
+       }
+#endif
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               crc32_check_front = crc32_temp;
+               crc32_header_check_front = crc32_header_temp;
+               return crc32_check_front;
+       } else
+#endif
+       {
+               crc32_check = crc32_temp;
+               crc32_header_check = crc32_header_temp;
+#ifdef CONFIG_COMPANION_USE
+               return crc32_check && crc32_c1_check;
+#else
+               return crc32_check;
+#endif
+       }
+}
+
+bool fimc_is_sec_check_fw_crc32(char *buf)
+{
+       u32 *buf32 = NULL;
+       u32 checksum;
+
+       buf32 = (u32 *)buf;
+
+       pr_info("Camera: Start checking CRC32 FW\n\n");
+
+       crc32_fw_check = true;
+
+       checksum = 0;
+
+       checksum = getCRC((u16 *)&buf32[0],
+                                               (sysfs_finfo.setfile_end_addr - sysfs_finfo.bin_start_addr + 1)/2, NULL, NULL);
+       if (checksum != buf32[(0x3FFFFC - 0x80000)/4]) {
+               err("Camera: CRC32 error at the binary section (0x%08X != 0x%08X)",
+                                       checksum, buf32[(0x3FFFFC - 0x80000)/4]);
+               crc32_fw_check = false;
+       }
+
+       pr_info("Camera: End checking CRC32 FW\n\n");
+
+       return crc32_fw_check;
+}
+
+#ifdef CONFIG_COMPANION_USE
+bool fimc_is_sec_check_companion_fw_crc32(char *buf)
+{
+       u32 *buf32 = NULL;
+       u32 checksum;
+
+       buf32 = (u32 *)buf;
+
+       pr_info("Camera: Start checking CRC32 Companion FW\n\n");
+
+       crc32_c1_fw_check = true;
+
+       checksum = 0;
+
+       checksum = getCRC((u16 *)&buf32[0], (sysfs_finfo.concord_mode_setfile_end_addr - sysfs_finfo.concord_bin_start_addr + 1)/2, NULL, NULL);
+       if (checksum != buf32[(0x6AFFC - 0x2B000)/4]) {
+               err("Camera: CRC32 error at the binary section (0x%08X != 0x%08X)",
+                                       checksum, buf32[(0x6AFFC - 0x2B000)/4]);
+               crc32_c1_fw_check = false;
+       }
+
+       pr_info("Camera: End checking CRC32 Companion FW\n\n");
+
+       return crc32_c1_fw_check;
+}
+#endif
+
+ssize_t write_data_to_file(char *name, char *buf, size_t count, loff_t *pos)
+{
+       struct file *fp;
+       mm_segment_t old_fs;
+       ssize_t tx;
+       int fd, old_mask;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       old_mask = sys_umask(0);
+
+       fd = sys_open(name, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0664);
+       if (fd < 0) {
+               err("open file error!!\n");
+               sys_umask(old_mask);
+               set_fs(old_fs);
+               return -EINVAL;
+       }
+
+       fp = fget(fd);
+       if (fp) {
+               tx = vfs_write(fp, buf, count, pos);
+               vfs_fsync(fp, 0);
+               fput(fp);
+       }
+
+       sys_close(fd);
+       sys_umask(old_mask);
+       set_fs(old_fs);
+
+       return count;
+}
+
+ssize_t read_data_from_file(char *name, char *buf, size_t count, loff_t *pos)
+{
+       struct file *fp;
+       mm_segment_t old_fs;
+       ssize_t tx;
+       int fd;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       fd = sys_open(name, O_RDONLY, 0664);
+       if (fd < 0) {
+               if (-ENOENT == fd)
+                       pr_info("%s: file(%s) not exist!\n", __func__, name);
+               else
+                       pr_info("%s: error %d, failed to open %s\n", __func__, fd, name);
+
+               set_fs(old_fs);
+               return -EINVAL;
+       }
+       fp = fget(fd);
+       if (fp) {
+               tx = vfs_read(fp, buf, count, pos);
+               fput(fp);
+       }
+       sys_close(fd);
+       set_fs(old_fs);
+
+       return count;
+}
+
+void fimc_is_sec_make_crc32_table(u32 *table, u32 id)
+{
+       u32 i, j, k;
+
+       for (i = 0; i < 256; ++i) {
+               k = i;
+               for (j = 0; j < 8; ++j) {
+                       if (k & 1)
+                               k = (k >> 1) ^ id;
+                       else
+                               k >>= 1;
+               }
+               table[i] = k;
+       }
+}
+
+#if 0 /* unused */
+static void fimc_is_read_sensor_version(void)
+{
+       int ret;
+       char buf[0x50];
+
+       memset(buf, 0x0, 0x50);
+
+       printk(KERN_INFO "+++ %s\n", __func__);
+
+       ret = fimc_is_spi_read(buf, 0x0, 0x50);
+
+       printk(KERN_INFO "--- %s\n", __func__);
+
+       if (ret) {
+               err("fimc_is_spi_read - can't read sensor version\n");
+       }
+
+       err("Manufacturer ID(0x40): 0x%02x\n", buf[0x40]);
+       err("Pixel Number(0x41): 0x%02x\n", buf[0x41]);
+}
+
+static void fimc_is_read_sensor_version2(void)
+{
+       char *buf;
+       char *cal_data;
+       u32 cur;
+       u32 count = SETFILE_SIZE/READ_SIZE;
+       u32 extra = SETFILE_SIZE%READ_SIZE;
+
+       printk(KERN_ERR "%s\n\n\n\n", __func__);
+
+
+       buf = (char *)kmalloc(READ_SIZE, GFP_KERNEL);
+       cal_data = (char *)kmalloc(SETFILE_SIZE, GFP_KERNEL);
+
+       memset(buf, 0x0, READ_SIZE);
+       memset(cal_data, 0x0, SETFILE_SIZE);
+
+
+       for (cur = 0; cur < SETFILE_SIZE; cur += READ_SIZE) {
+               fimc_is_spi_read(buf, cur, READ_SIZE);
+               memcpy(cal_data+cur, buf, READ_SIZE);
+               memset(buf, 0x0, READ_SIZE);
+       }
+
+       if (extra != 0) {
+               fimc_is_spi_read(buf, cur, extra);
+               memcpy(cal_data+cur, buf, extra);
+               memset(buf, 0x0, extra);
+       }
+
+       pr_info("Manufacturer ID(0x40): 0x%02x\n", cal_data[0x40]);
+       pr_info("Pixel Number(0x41): 0x%02x\n", cal_data[0x41]);
+
+
+       pr_info("Manufacturer ID(0x4FE7): 0x%02x\n", cal_data[0x4FE7]);
+       pr_info("Pixel Number(0x4FE8): 0x%02x\n", cal_data[0x4FE8]);
+       pr_info("Manufacturer ID(0x4FE9): 0x%02x\n", cal_data[0x4FE9]);
+       pr_info("Pixel Number(0x4FEA): 0x%02x\n", cal_data[0x4FEA]);
+
+       kfree(buf);
+       kfree(cal_data);
+
+}
+
+static int fimc_is_get_cal_data(void)
+{
+       int err = 0;
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long ret = 0;
+       u8 mem0 = 0, mem1 = 0;
+       u32 CRC = 0;
+       u32 DataCRC = 0;
+       u32 IntOriginalCRC = 0;
+       u32 crc_index = 0;
+       int retryCnt = 2;
+       u32 header_crc32 =      0x1000;
+       u32 oem_crc32 =         0x2000;
+       u32 awb_crc32 =         0x3000;
+       u32 shading_crc32 = 0x6000;
+       u32 shading_header = 0x22C0;
+
+       char *cal_data;
+
+       crc32_check = true;
+       printk(KERN_INFO "%s\n\n\n\n", __func__);
+       printk(KERN_INFO "+++ %s\n", __func__);
+
+       fimc_is_spi_read(cal_map_version, 0x60, 0x4);
+       printk(KERN_INFO "cal_map_version = %.4s\n", cal_map_version);
+
+       if (cal_map_version[3] == '5') {
+               shading_crc32 = 0x6000;
+               shading_header = 0x22C0;
+       } else if (cal_map_version[3] == '6') {
+               shading_crc32 = 0x4000;
+               shading_header = 0x920;
+       } else {
+               shading_crc32 = 0x5000;
+               shading_header = 0x22C0;
+       }
+
+       /* Make CRC Table */
+       fimc_is_sec_make_crc32_table((u32 *)&crc_table, 0xEDB88320);
+
+
+       retry:
+               cal_data = (char *)kmalloc(SETFILE_SIZE, GFP_KERNEL);
+
+               memset(cal_data, 0x0, SETFILE_SIZE);
+
+               mem0 = 0, mem1 = 0;
+               CRC = 0;
+               DataCRC = 0;
+               IntOriginalCRC = 0;
+               crc_index = 0;
+
+               fimc_is_spi_read(cal_data, 0, SETFILE_SIZE);
+
+               CRC = ~CRC;
+               for (crc_index = 0; crc_index < (0x80)/2; crc_index++) {
+                       /*low byte*/
+                       mem0 = (unsigned char)(cal_data[crc_index*2] & 0x00ff);
+                       /*high byte*/
+                       mem1 = (unsigned char)((cal_data[crc_index*2+1]) & 0x00ff);
+                       CRC = crc_table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8);
+                       CRC = crc_table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8);
+               }
+               CRC = ~CRC;
+
+
+               DataCRC = (CRC&0x000000ff)<<24;
+               DataCRC += (CRC&0x0000ff00)<<8;
+               DataCRC += (CRC&0x00ff0000)>>8;
+               DataCRC += (CRC&0xff000000)>>24;
+               printk(KERN_INFO "made HEADER CSC value by S/W = 0x%x\n", DataCRC);
+
+               IntOriginalCRC = (cal_data[header_crc32-4]&0x00ff)<<24;
+               IntOriginalCRC += (cal_data[header_crc32-3]&0x00ff)<<16;
+               IntOriginalCRC += (cal_data[header_crc32-2]&0x00ff)<<8;
+               IntOriginalCRC += (cal_data[header_crc32-1]&0x00ff);
+               printk(KERN_INFO "Original HEADER CRC Int = 0x%x\n", IntOriginalCRC);
+
+               if (IntOriginalCRC != DataCRC)
+                       crc32_check = false;
+
+               CRC = 0;
+               CRC = ~CRC;
+               for (crc_index = 0; crc_index < (0xC0)/2; crc_index++) {
+                       /*low byte*/
+                       mem0 = (unsigned char)(cal_data[0x1000 + crc_index*2] & 0x00ff);
+                       /*high byte*/
+                       mem1 = (unsigned char)((cal_data[0x1000 + crc_index*2+1]) & 0x00ff);
+                       CRC = crc_table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8);
+                       CRC = crc_table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8);
+               }
+               CRC = ~CRC;
+
+
+               DataCRC = (CRC&0x000000ff)<<24;
+               DataCRC += (CRC&0x0000ff00)<<8;
+               DataCRC += (CRC&0x00ff0000)>>8;
+               DataCRC += (CRC&0xff000000)>>24;
+               printk(KERN_INFO "made OEM CSC value by S/W = 0x%x\n", DataCRC);
+
+               IntOriginalCRC = (cal_data[oem_crc32-4]&0x00ff)<<24;
+               IntOriginalCRC += (cal_data[oem_crc32-3]&0x00ff)<<16;
+               IntOriginalCRC += (cal_data[oem_crc32-2]&0x00ff)<<8;
+               IntOriginalCRC += (cal_data[oem_crc32-1]&0x00ff);
+               printk(KERN_INFO "Original OEM CRC Int = 0x%x\n", IntOriginalCRC);
+
+               if (IntOriginalCRC != DataCRC)
+                       crc32_check = false;
+
+
+               CRC = 0;
+               CRC = ~CRC;
+               for (crc_index = 0; crc_index < (0x20)/2; crc_index++) {
+                       /*low byte*/
+                       mem0 = (unsigned char)(cal_data[0x2000 + crc_index*2] & 0x00ff);
+                       /*high byte*/
+                       mem1 = (unsigned char)((cal_data[0x2000 + crc_index*2+1]) & 0x00ff);
+                       CRC = crc_table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8);
+                       CRC = crc_table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8);
+               }
+               CRC = ~CRC;
+
+
+               DataCRC = (CRC&0x000000ff)<<24;
+               DataCRC += (CRC&0x0000ff00)<<8;
+               DataCRC += (CRC&0x00ff0000)>>8;
+               DataCRC += (CRC&0xff000000)>>24;
+               printk(KERN_INFO "made AWB CSC value by S/W = 0x%x\n", DataCRC);
+
+               IntOriginalCRC = (cal_data[awb_crc32-4]&0x00ff)<<24;
+               IntOriginalCRC += (cal_data[awb_crc32-3]&0x00ff)<<16;
+               IntOriginalCRC += (cal_data[awb_crc32-2]&0x00ff)<<8;
+               IntOriginalCRC += (cal_data[awb_crc32-1]&0x00ff);
+               printk(KERN_INFO "Original AWB CRC Int = 0x%x\n", IntOriginalCRC);
+
+               if (IntOriginalCRC != DataCRC)
+                       crc32_check = false;
+
+
+               CRC = 0;
+               CRC = ~CRC;
+               for (crc_index = 0; crc_index < (shading_header)/2; crc_index++) {
+
+                       /*low byte*/
+                       mem0 = (unsigned char)(cal_data[0x3000 + crc_index*2] & 0x00ff);
+                       /*high byte*/
+                       mem1 = (unsigned char)((cal_data[0x3000 + crc_index*2+1]) & 0x00ff);
+                       CRC = crc_table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8);
+                       CRC = crc_table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8);
+               }
+               CRC = ~CRC;
+
+
+               DataCRC = (CRC&0x000000ff)<<24;
+               DataCRC += (CRC&0x0000ff00)<<8;
+               DataCRC += (CRC&0x00ff0000)>>8;
+               DataCRC += (CRC&0xff000000)>>24;
+               printk(KERN_INFO "made SHADING CSC value by S/W = 0x%x\n", DataCRC);
+
+               IntOriginalCRC = (cal_data[shading_crc32-4]&0x00ff)<<24;
+               IntOriginalCRC += (cal_data[shading_crc32-3]&0x00ff)<<16;
+               IntOriginalCRC += (cal_data[shading_crc32-2]&0x00ff)<<8;
+               IntOriginalCRC += (cal_data[shading_crc32-1]&0x00ff);
+               printk(KERN_INFO "Original SHADING CRC Int = 0x%x\n", IntOriginalCRC);
+
+               if (IntOriginalCRC != DataCRC)
+                       crc32_check = false;
+
+
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               if (crc32_check == true) {
+                       printk(KERN_INFO "make cal_data.bin~~~~ \n");
+                       fp = filp_open(FIMC_IS_CAL_SDCARD, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+                       if (IS_ERR(fp) || fp == NULL) {
+                               printk(KERN_INFO "failed to open %s, err %ld\n",
+                                       FIMC_IS_CAL_SDCARD, PTR_ERR(fp));
+                               err = -EINVAL;
+                               goto out;
+                       }
+
+                       ret = vfs_write(fp, (char __user *)cal_data,
+                               SETFILE_SIZE, &fp->f_pos);
+
+               } else {
+                       if (retryCnt > 0) {
+                               set_fs(old_fs);
+                               retryCnt--;
+                               goto retry;
+                       }
+               }
+
+/*
+               {
+                       fp = filp_open(FIMC_IS_CAL_SDCARD, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+                       if (IS_ERR(fp) || fp == NULL) {
+                               printk(KERN_INFO "failed to open %s, err %ld\n",
+                                       FIMC_IS_CAL_SDCARD, PTR_ERR(fp));
+                               err = -EINVAL;
+                               goto out;
+                       }
+
+                       ret = vfs_write(fp, (char __user *)cal_data,
+                               SETFILE_SIZE, &fp->f_pos);
+
+               }
+*/
+
+               if (fp != NULL)
+                       filp_close(fp, current->files);
+
+       out:
+               set_fs(old_fs);
+               kfree(cal_data);
+               return err;
+
+}
+
+#endif
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR) || defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+int fimc_is_i2c_read(struct i2c_client *client, void *buf, u32 addr, size_t size)
+{
+       const u32 addr_size = 2, max_retry = 5;
+       u8 addr_buf[addr_size];
+       int retries = max_retry;
+       int ret = 0;
+
+       if (!client) {
+               pr_info("%s: client is null\n", __func__);
+               return -ENODEV;
+       }
+
+       /* pr_info("%s %s: fimc_is_i2c_read\n",
+               dev_driver_string(&client->dev), dev_name(&client->dev));*/
+
+       /* Send addr */
+       addr_buf[0] = ((u16)addr) >> 8;
+       addr_buf[1] = (u8)addr;
+
+       for (retries = max_retry; retries > 0; retries--) {
+               ret = i2c_master_send(client, addr_buf, addr_size);
+               if (likely(addr_size == ret))
+                       break;
+
+               pr_info("%s: i2c_master_send failed(%d), try %d\n", __func__, ret, retries);
+               usleep_range(1000, 1000);
+       }
+
+       if (unlikely(ret <= 0)) {
+               pr_err("%s: error %d, fail to write 0x%04X\n", __func__, ret, addr);
+               return ret ? ret : -ETIMEDOUT;
+       }
+
+       /* Receive data */
+       for (retries = max_retry; retries > 0; retries--) {
+               ret = i2c_master_recv(client, buf, size);
+               if (likely(ret == size))
+                       break;
+
+               pr_info("%s: i2c_master_recv failed(%d), try %d\n", __func__,  ret, retries);
+               usleep_range(1000, 1000);
+       }
+
+       if (unlikely(ret <= 0)) {
+               pr_err("%s: error %d, fail to read 0x%04X\n", __func__, ret, addr);
+               return ret ? ret : -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+int fimc_is_i2c_write(struct i2c_client *client, void *buf, u32 addr, size_t size)
+{
+       pr_info("%s: do nothing\n", __func__);
+       return 0;
+}
+
+int fimc_is_sec_read_eeprom_header(struct device *dev)
+{
+       int ret = 0;
+       struct fimc_is_core *core = dev_get_drvdata(dev);
+       u8 header_version[12] = {0, };
+       struct i2c_client *client;
+       client = core->eeprom_client0;
+
+       ret = fimc_is_i2c_read(client, header_version, 0x20, 0x0B);
+       if (unlikely(ret)) {
+               err("failed to fimc_is_i2c_read for header version (%d)\n", ret);
+               ret = -EINVAL;
+       }
+
+       memcpy(sysfs_finfo.header_ver, header_version, 11);
+       sysfs_finfo.header_ver[11] = '\0';
+
+       return ret;
+}
+
+int fimc_is_sec_readcal_eeprom(struct device *dev, int id)
+{
+       int ret = 0;
+       char *buf = NULL;
+       int retry = FIMC_IS_CAL_RETRY_CNT;
+       struct fimc_is_core *core = dev_get_drvdata(dev);
+       struct fimc_is_from_info *finfo = NULL;
+       int cal_size = 0;
+       struct i2c_client *client = NULL;
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               finfo = &sysfs_finfo_front;
+               fimc_is_sec_get_front_cal_buf(&buf);
+               cal_size = FIMC_IS_MAX_CAL_SIZE_FRONT;
+               client = core->eeprom_client1;
+       } else
+#endif
+       {
+               finfo = &sysfs_finfo;
+               fimc_is_sec_get_cal_buf(&buf);
+               cal_size = FIMC_IS_MAX_CAL_SIZE;
+               client = core->eeprom_client0;
+       }
+
+       ret = fimc_is_i2c_read(client, cal_map_version, 0x30, 0x4);
+       if (unlikely(ret)) {
+               err("failed to fimc_is_i2c_read (%d)\n", ret);
+               ret = -EINVAL;
+               goto exit;
+       }
+       printk(KERN_INFO "Camera: Cal map_version = %c%c%c%c\n", cal_map_version[0],
+                       cal_map_version[1], cal_map_version[2], cal_map_version[3]);
+
+crc_retry:
+
+       /* read cal data */
+       pr_info("Camera: I2C read cal data\n\n");
+       fimc_is_i2c_read(client, buf, 0x0, cal_size);
+
+       finfo->oem_start_addr = *((u32 *)&buf[0x0]);
+       finfo->oem_end_addr = *((u32 *)&buf[0x04]);
+       pr_info("OEM start = 0x%08x, end = 0x%08x\n",
+                       (finfo->oem_start_addr), (finfo->oem_end_addr));
+       finfo->awb_start_addr = *((u32 *)&buf[0x08]);
+       finfo->awb_end_addr = *((u32 *)&buf[0x0C]);
+       pr_info("AWB start = 0x%08x, end = 0x%08x\n",
+                       (finfo->awb_start_addr), (finfo->awb_end_addr));
+       finfo->shading_start_addr = *((u32 *)&buf[0x10]);
+       finfo->shading_end_addr = *((u32 *)&buf[0x14]);
+       if (finfo->shading_end_addr > 0x1fff) {
+               err("Shading end_addr has error!! 0x%08x", finfo->shading_end_addr);
+               finfo->setfile_end_addr = 0x1fff;
+       }
+       pr_info("Shading start = 0x%08x, end = 0x%08x\n",
+               (finfo->shading_start_addr), (finfo->shading_end_addr));
+
+       /* HEARDER Data : Module/Manufacturer Information */
+       memcpy(finfo->header_ver, &buf[0x20], 11);
+       finfo->header_ver[11] = '\0';
+       /* HEARDER Data : Cal Map Version */
+       memcpy(finfo->cal_map_ver, &buf[0x30], 4);
+
+       memcpy(finfo->project_name, &buf[0x38], 8);
+       finfo->project_name[8] = '\0';
+
+       /* OEM Data : Module/Manufacturer Information */
+       memcpy(finfo->oem_ver, &buf[0x150], 11);
+       finfo->oem_ver[11] = '\0';
+
+       /* AWB Data : Module/Manufacturer Information */
+       memcpy(finfo->awb_ver, &buf[0x220], 11);
+       finfo->awb_ver[11] = '\0';
+
+       /* SHADING Data : Module/Manufacturer Information */
+       memcpy(finfo->shading_ver, &buf[0x1CE0], 11);
+       finfo->shading_ver[11] = '\0';
+
+       /* debug info dump */
+#if defined(EEPROM_DEBUG)
+       pr_info("++++ EEPROM data info\n");
+       pr_info("1. Header info\n");
+       pr_info("Module info : %s\n", finfo->header_ver);
+       pr_info(" ID : %c\n", finfo->header_ver[0]);
+       pr_info(" Pixel num : %c%c\n", finfo->header_ver[1],
+                                                       finfo->header_ver[2]);
+       pr_info(" ISP ID : %c\n", finfo->header_ver[3]);
+       pr_info(" Sensor Maker : %c\n", finfo->header_ver[4]);
+       pr_info(" Module ver : %c\n", finfo->header_ver[6]);
+       pr_info(" Year : %c\n", finfo->header_ver[7]);
+       pr_info(" Month : %c\n", finfo->header_ver[8]);
+       pr_info(" Release num : %c%c\n", finfo->header_ver[9],
+                                                       finfo->header_ver[10]);
+       pr_info("project_name : %s\n", finfo->project_name);
+       pr_info("Cal data map ver : %s\n", finfo->cal_map_ver);
+       pr_info("2. OEM info\n");
+       pr_info("Module info : %s\n", finfo->oem_ver);
+       pr_info("3. AWB info\n");
+       pr_info("Module info : %s\n", finfo->awb_ver);
+       pr_info("4. Shading info\n");
+       pr_info("Module info : %s\n", finfo->shading_ver);
+       pr_info("---- EEPROM data info\n");
+#endif
+
+       /* CRC check */
+       if (id == SENSOR_POSITION_FRONT) {
+               ret = fimc_is_sec_check_cal_crc32(buf, SENSOR_POSITION_FRONT);
+       } else {
+               ret = fimc_is_sec_check_cal_crc32(buf, SENSOR_POSITION_REAR);
+       }
+       if (!ret && (retry > 0)) {
+               retry--;
+               goto crc_retry;
+       }
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR) || defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               if (finfo->header_ver[3] == 'L') {
+                       crc32_check_factory_front = crc32_check_front;
+               } else {
+                       crc32_check_factory_front = false;
+               }
+       } else
+#endif
+       {
+               if (finfo->header_ver[3] == 'L') {
+                       crc32_check_factory = crc32_check;
+               } else {
+                       crc32_check_factory = false;
+               }
+
+               if (finfo->project_name[6] == 'C' && finfo->header_ver[0] == 'E' && finfo->header_ver[1] == '0' &&
+                       finfo->header_ver[2] == '8') {
+                       pr_info("This camera module use IMX134+EEPROM - project_name: %c-%c\n"
+                               , finfo->project_name[6], finfo->project_name[7]);
+
+                       if (!core->use_module_check) {
+                               is_right_prj_name = true;
+                               is_latest_cam_module = true;
+                               is_final_cam_module = true;
+                       }
+               }
+       }
+
+exit:
+       return ret;
+}
+#endif
+
+#if !defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+extern int fimc_is_spi_reset_by_core(struct spi_device *spi, void *buf, u32 rx_addr, size_t size);
+extern int fimc_is_spi_read_by_core(struct spi_device *spi, void *buf, u32 rx_addr, size_t size);
+extern int fimc_is_spi_read_module_id(struct spi_device *spi, void *buf, u16 rx_addr, size_t size);
+
+int fimc_is_sec_read_from_header(struct device *dev)
+{
+       int ret = 0;
+       struct fimc_is_core *core = dev_get_drvdata(dev);
+       u8 header_version[12] = {0, };
+
+       ret = fimc_is_spi_read_by_core(core->spi0, header_version, 0x40, 0x0B);
+       if (ret < 0) {
+               printk(KERN_ERR "failed to fimc_is_spi_read for header version (%d)\n", ret);
+               ret = -EINVAL;
+       }
+
+       memcpy(sysfs_finfo.header_ver, header_version, 11);
+       sysfs_finfo.header_ver[11] = '\0';
+
+       return ret;
+}
+
+int fimc_is_sec_readcal(struct fimc_is_core *core)
+{
+       int ret = 0;
+       int retry = FIMC_IS_CAL_RETRY_CNT;
+       char spi_buf[0x50] = {0, };
+       struct file *key_fp = NULL;
+       struct file *dump_fp = NULL;
+       mm_segment_t old_fs;
+       loff_t pos = 0;
+       u16 id;
+
+       /* reset spi */
+       if (!core->spi0) {
+               pr_err("spi0 device is not available");
+               goto exit;
+       }
+
+       ret = fimc_is_spi_reset_by_core(core->spi0, spi_buf, 0x0, FIMC_IS_MAX_CAL_SIZE);
+       if (ret < 0) {
+               err("failed to fimc_is_spi_read (%d)\n", ret);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       ret = fimc_is_spi_read_module_id(core->spi0, &id, 0x0, 0x2);
+       pr_info("Camera: FROM Module ID = 0x%04x\n", id);
+
+       ret = fimc_is_spi_read_by_core(core->spi0, cal_map_version, 0x60, 0x4);
+       if (ret < 0) {
+               printk(KERN_ERR "failed to fimc_is_spi_read (%d)\n", ret);
+               ret = -EINVAL;
+               goto exit;
+       }
+       pr_info("Camera: Cal map_version = %c%c%c%c\n", cal_map_version[0],
+                       cal_map_version[1], cal_map_version[2], cal_map_version[3]);
+crc_retry:
+       /* read cal data */
+       pr_info("Camera: SPI read cal data\n\n");
+       ret = fimc_is_spi_read_by_core(core->spi0, cal_buf, 0x0, FIMC_IS_MAX_CAL_SIZE);
+       if (ret < 0) {
+               err("failed to fimc_is_spi_read (%d)\n", ret);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       sysfs_finfo.bin_start_addr = *((u32 *)&cal_buf[0]);
+       sysfs_finfo.bin_end_addr = *((u32 *)&cal_buf[4]);
+       pr_info("Binary start = 0x%08x, end = 0x%08x\n",
+                       (sysfs_finfo.bin_start_addr), (sysfs_finfo.bin_end_addr));
+       sysfs_finfo.oem_start_addr = *((u32 *)&cal_buf[8]);
+       sysfs_finfo.oem_end_addr = 0x113F;//*((u32 *)&cal_buf[12]);
+       pr_info("OEM start = 0x%08x, end = 0x%08x\n",
+                       (sysfs_finfo.oem_start_addr), (sysfs_finfo.oem_end_addr));
+       sysfs_finfo.awb_start_addr = *((u32 *)&cal_buf[16]);
+       sysfs_finfo.awb_end_addr = *((u32 *)&cal_buf[20]);
+       pr_info("AWB start = 0x%08x, end = 0x%08x\n",
+                       (sysfs_finfo.awb_start_addr), (sysfs_finfo.awb_end_addr));
+       sysfs_finfo.shading_start_addr = *((u32 *)&cal_buf[24]);
+       sysfs_finfo.shading_end_addr = *((u32 *)&cal_buf[28]);
+       pr_info("Shading start = 0x%08x, end = 0x%08x\n",
+               (sysfs_finfo.shading_start_addr), (sysfs_finfo.shading_end_addr));
+       sysfs_finfo.setfile_start_addr = *((u32 *)&cal_buf[32]);
+       sysfs_finfo.setfile_end_addr = *((u32 *)&cal_buf[36]);
+       /*if (sysfs_finfo.setfile_start_addr == 0xffffffff) {
+               sysfs_finfo.setfile_start_addr = *((u32 *)&cal_buf[40]);
+               sysfs_finfo.setfile_end_addr = *((u32 *)&cal_buf[44]);
+       }*/
+#ifdef CONFIG_COMPANION_USE
+       sysfs_finfo.concord_cal_start_addr = *((u32 *)&cal_buf[40]);
+       sysfs_finfo.concord_cal_end_addr = 0xF23F;//*((u32 *)&cal_buf[44]);
+       pr_info("concord cal start = 0x%08x, end = 0x%08x\n",
+               sysfs_finfo.concord_cal_start_addr, sysfs_finfo.concord_cal_end_addr);
+       sysfs_finfo.concord_bin_start_addr = *((u32 *)&cal_buf[48]);
+       sysfs_finfo.concord_bin_end_addr = *((u32 *)&cal_buf[52]);
+       pr_info("concord bin start = 0x%08x, end = 0x%08x\n",
+               sysfs_finfo.concord_bin_start_addr, sysfs_finfo.concord_bin_end_addr);
+       sysfs_finfo.concord_master_setfile_start_addr = *((u32 *)&cal_buf[168]);
+       sysfs_finfo.concord_master_setfile_end_addr = sysfs_finfo.concord_master_setfile_start_addr + 16064;
+       sysfs_finfo.concord_mode_setfile_start_addr = sysfs_finfo.concord_master_setfile_end_addr + 1;
+       sysfs_finfo.concord_mode_setfile_end_addr = *((u32 *)&cal_buf[172]);
+       sysfs_finfo.pdaf_cal_start_addr = 0x5000;
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V005)
+               sysfs_finfo.pdaf_cal_end_addr = 0x540F;
+       else
+               sysfs_finfo.pdaf_cal_end_addr = 0x521F;
+       pr_info("pdaf start = 0x%08x, end = 0x%08x\n",
+               sysfs_finfo.pdaf_cal_start_addr, sysfs_finfo.pdaf_cal_end_addr);
+
+       sysfs_finfo.lsc_i0_gain_addr = 0x3006;
+       pr_info("Shading lsc_i0 start = 0x%08x\n", sysfs_finfo.lsc_i0_gain_addr);
+       sysfs_finfo.lsc_j0_gain_addr = sysfs_finfo.lsc_i0_gain_addr + 0x2;
+       pr_info("Shading lsc_j0 start = 0x%08x\n", sysfs_finfo.lsc_j0_gain_addr);
+       sysfs_finfo.lsc_a_gain_addr = sysfs_finfo.lsc_j0_gain_addr + 0x2;
+       pr_info("Shading lsc_a start = 0x%08x\n", sysfs_finfo.lsc_a_gain_addr);
+       sysfs_finfo.lsc_k4_gain_addr = sysfs_finfo.lsc_a_gain_addr + 0x4;
+       pr_info("Shading lsc_k4 start = 0x%08x\n", sysfs_finfo.lsc_k4_gain_addr);
+       sysfs_finfo.lsc_scale_gain_addr = sysfs_finfo.lsc_k4_gain_addr + 0x4;
+       pr_info("Shading lsc_scale start = 0x%08x\n", sysfs_finfo.lsc_scale_gain_addr);
+
+       sysfs_finfo.lsc_gain_start_addr = sysfs_finfo.shading_start_addr + 0x14;
+       sysfs_finfo.lsc_gain_end_addr = sysfs_finfo.lsc_gain_start_addr + 6600 -1;
+       pr_info("LSC start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.lsc_gain_start_addr, sysfs_finfo.lsc_gain_end_addr);
+       sysfs_finfo.pdaf_start_addr = sysfs_finfo.concord_cal_start_addr;
+       sysfs_finfo.pdaf_end_addr = sysfs_finfo.pdaf_start_addr + 512 -1;
+       pr_info("pdaf_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.pdaf_start_addr, sysfs_finfo.pdaf_end_addr);
+       /*sysfs_finfo.coefficient_cal_start_addr = sysfs_finfo.pdaf_start_addr + 512 + 16;
+       sysfs_finfo.coefficient_cal_end_addr = sysfs_finfo.coefficient_cal_start_addr + 24576 -1;
+       pr_info("coefficient_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coefficient_cal_start_addr, sysfs_finfo.coefficient_cal_end_addr);*/
+       sysfs_finfo.coef1_start = sysfs_finfo.pdaf_start_addr + 512 + 16;
+       sysfs_finfo.coef1_end = sysfs_finfo.coef1_start + 4032 -1;
+       pr_info("coefficient1_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coef1_start, sysfs_finfo.coef1_end);
+       sysfs_finfo.coef2_start = sysfs_finfo.coef1_end + 64 + 1;
+       sysfs_finfo.coef2_end = sysfs_finfo.coef2_start + 4032 -1;
+       pr_info("coefficient2_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coef2_start, sysfs_finfo.coef2_end);
+       sysfs_finfo.coef3_start = sysfs_finfo.coef2_end + 64 + 1;
+       sysfs_finfo.coef3_end = sysfs_finfo.coef3_start + 4032 -1;
+       pr_info("coefficient3_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coef3_start, sysfs_finfo.coef3_end);
+       sysfs_finfo.coef4_start = sysfs_finfo.coef3_end + 64 + 1;
+       sysfs_finfo.coef4_end = sysfs_finfo.coef4_start + 4032 -1;
+       pr_info("coefficient4_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coef4_start, sysfs_finfo.coef4_end);
+       sysfs_finfo.coef5_start = sysfs_finfo.coef4_end + 64 + 1;
+       sysfs_finfo.coef5_end = sysfs_finfo.coef5_start + 4032 -1;
+       pr_info("coefficient5_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coef5_start, sysfs_finfo.coef5_end);
+       sysfs_finfo.coef6_start = sysfs_finfo.coef5_end + 64 + 1;
+       sysfs_finfo.coef6_end = sysfs_finfo.coef6_start + 4032 -1;
+       pr_info("coefficient6_cal_addr start = 0x%04x, end = 0x%04x\n",
+               sysfs_finfo.coef6_start, sysfs_finfo.coef6_end);
+       sysfs_finfo.wcoefficient1_addr = 0xF210;
+       pr_info("Shading wcoefficient1 start = 0x%04x\n", sysfs_finfo.wcoefficient1_addr);
+       memcpy(sysfs_finfo.concord_header_ver, &cal_buf[80], 11);
+       sysfs_finfo.concord_header_ver[11] = '\0';
+       sysfs_finfo.af_inf_addr = 0x1000;
+       sysfs_finfo.af_macro_addr = 0x1008;
+       sysfs_finfo.lsc_gain_crc_addr = 0x49DC;
+       sysfs_finfo.pdaf_crc_addr= 0x9200;
+       sysfs_finfo.coef1_crc_addr= 0xF21A;
+       sysfs_finfo.coef2_crc_addr = 0xF21E;
+       sysfs_finfo.coef3_crc_addr = 0xF222;
+       sysfs_finfo.coef4_crc_addr = 0xF226;
+       sysfs_finfo.coef5_crc_addr = 0xF22A;
+       sysfs_finfo.coef6_crc_addr = 0xF22E;
+#endif
+
+       if (sysfs_finfo.setfile_end_addr < 0x8000 || sysfs_finfo.setfile_end_addr > 0x3fffff) {
+               err("setfile end_addr has error!!  0x%08x", sysfs_finfo.setfile_end_addr);
+               sysfs_finfo.setfile_end_addr = 0x1fffff;
+       }
+
+       pr_info("Setfile start = 0x%08x, end = 0x%08x\n",
+               (sysfs_finfo.setfile_start_addr), (sysfs_finfo.setfile_end_addr));
+
+       memcpy(sysfs_finfo.header_ver, &cal_buf[64], 11);
+       sysfs_finfo.header_ver[11] = '\0';
+       memcpy(sysfs_finfo.cal_map_ver, &cal_buf[96], 4);
+       memcpy(sysfs_finfo.setfile_ver, &cal_buf[100], 6);
+       sysfs_finfo.setfile_ver[6] = '\0';
+       memcpy(sysfs_finfo.oem_ver, &cal_buf[8160], 11);
+       sysfs_finfo.oem_ver[11] = '\0';
+       memcpy(sysfs_finfo.awb_ver, &cal_buf[12256], 11);
+       sysfs_finfo.awb_ver[11] = '\0';
+       memcpy(sysfs_finfo.shading_ver, &cal_buf[16352], 11);
+       sysfs_finfo.shading_ver[11] = '\0';
+       memcpy(sysfs_finfo.project_name, &cal_buf[110], 8);
+       sysfs_finfo.project_name[8] = '\0';
+
+       fw_core_version = sysfs_finfo.header_ver[0];
+       /* debug info dump */
+//#if defined(FROM_DEBUG)
+#if 1
+       pr_err("++++ FROM data info\n");
+       pr_err("1. Header info\n");
+       pr_err("Module info : %s\n", sysfs_finfo.header_ver);
+#ifdef CONFIG_COMPANION_USE
+       pr_err("Companion version info : %s\n", sysfs_finfo.concord_header_ver);
+#endif
+       pr_err(" ID : %c\n", sysfs_finfo.header_ver[0]);
+       pr_err(" Pixel num : %c%c\n", sysfs_finfo.header_ver[1],
+                                                       sysfs_finfo.header_ver[2]);
+       pr_err(" ISP ID : %c\n", sysfs_finfo.header_ver[3]);
+       pr_err(" Sensor Maker : %c\n", sysfs_finfo.header_ver[5]);
+       pr_err(" Module ver : %c\n", sysfs_finfo.header_ver[6]);
+       pr_err(" Year : %c\n", sysfs_finfo.header_ver[7]);
+       pr_err(" Month : %c\n", sysfs_finfo.header_ver[8]);
+       pr_err(" Release num : %c%c\n", sysfs_finfo.header_ver[9],
+                                                       sysfs_finfo.header_ver[10]);
+       pr_err("Cal data map ver : %s\n", sysfs_finfo.cal_map_ver);
+       pr_err("Setfile ver : %s\n", sysfs_finfo.setfile_ver);
+       pr_err("Project name : %s\n", sysfs_finfo.project_name);
+       pr_err("2. OEM info\n");
+       pr_err("Module info : %s\n", sysfs_finfo.oem_ver);
+       pr_err("3. AWB info\n");
+       pr_err("Module info : %s\n", sysfs_finfo.awb_ver);
+       pr_err("4. Shading info\n");
+       pr_err("Module info : %s\n", sysfs_finfo.shading_ver);
+       pr_err("---- FROM data info\n");
+#endif
+
+       /* CRC check */
+#ifdef CONFIG_COMPANION_USE
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               if (!fimc_is_sec_check_cal_crc32(cal_buf, SENSOR_POSITION_REAR) && (retry > 0)) {
+                       retry--;
+                       goto crc_retry;
+               }
+       } else {
+               fw_version_crc_check = false;
+               crc32_check = false;
+               crc32_c1_check = false;
+       }
+#else
+       if (!fimc_is_sec_check_cal_crc32(cal_buf, SENSOR_POSITION_REAR) && (retry > 0)) {
+               retry--;
+               goto crc_retry;
+       }
+#endif
+
+       if (sysfs_finfo.header_ver[3] == 'L') {
+               crc32_check_factory = crc32_check;
+#ifdef CONFIG_COMPANION_USE
+               crc32_c1_check_factory = crc32_c1_check;
+#endif
+       } else {
+               crc32_check_factory = false;
+#ifdef CONFIG_COMPANION_USE
+               crc32_c1_check_factory = false;
+#endif
+       }
+
+#ifdef CONFIG_COMPANION_USE
+       if (fimc_is_comp_is_compare_ver(core) >= FROM_VERSION_V004) {
+               if (crc32_check && crc32_c1_check) {
+                       /* If FROM LSC value is not valid, loading default lsc data */
+                       if (*((u32 *)&cal_buf[sysfs_finfo.lsc_gain_start_addr]) == 0x00000000) {
+                               companion_lsc_isvalid = false;
+                       } else {
+                               companion_lsc_isvalid = true;
+                       }
+                       if (*((u32 *)&cal_buf[sysfs_finfo.coef1_start]) == 0x00000000) {
+                               companion_coef_isvalid = false;
+                       } else {
+                               companion_coef_isvalid = true;
+                       }
+               } else {
+                       companion_lsc_isvalid = false;
+                       companion_coef_isvalid = false;
+               }
+       } else {
+               companion_lsc_isvalid = true;
+               companion_coef_isvalid = true;
+       }
+#endif
+
+       if (!core->use_module_check) {
+               is_latest_cam_module = true;
+       } else {
+               if (sysfs_finfo.header_ver[10] >= FIMC_IS_LATEST_FROM_VERSION_B) {
+                       is_latest_cam_module = true;
+               } else {
+                       is_latest_cam_module = false;
+               }
+       }
+
+       if (core->use_module_check) {
+               if (sysfs_finfo.header_ver[10] == FIMC_IS_LATEST_FROM_VERSION_M) {
+                       is_final_cam_module = true;
+               } else {
+                       is_final_cam_module = false;
+               }
+       } else {
+               is_final_cam_module = true;
+       }
+
+#if defined(CONFIG_SOC_EXYNOS5433)
+       if (sysfs_finfo.project_name[6] != 'T' && sysfs_finfo.header_ver[0] == 'H' && sysfs_finfo.header_ver[1] == '1' &&
+               sysfs_finfo.header_ver[2] == '6') {
+               pr_info("FROM has abnormal project name : %c-%c\n", sysfs_finfo.project_name[6], sysfs_finfo.project_name[7]);
+               is_right_prj_name = false;
+       } else {
+               is_right_prj_name = true;
+       }
+#endif
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       key_fp = filp_open("/data/media/0/1q2w3e4r.key", O_RDONLY, 0);
+       if (IS_ERR(key_fp)) {
+               pr_info("KEY does not exist.\n");
+               key_fp = NULL;
+               goto key_err;
+       } else {
+               dump_fp = filp_open("/data/media/0/dump", O_RDONLY, 0);
+               if (IS_ERR(dump_fp)) {
+                       pr_info("dump folder does not exist.\n");
+                       dump_fp = NULL;
+                       goto key_err;
+               } else {
+                       pr_info("dump folder exist, Dump FROM cal data.\n");
+                       if (write_data_to_file("/data/media/0/dump/from_cal.bin", cal_buf, FIMC_IS_DUMP_CAL_SIZE, &pos) < 0) {
+                               pr_info("Failedl to dump cal data.\n");
+                               goto dump_err;
+                       }
+               }
+       }
+dump_err:
+       if (dump_fp)
+               filp_close(dump_fp, current->files);
+key_err:
+       if (key_fp)
+               filp_close(key_fp, current->files);
+       set_fs(old_fs);
+exit:
+       return ret;
+}
+
+int fimc_is_sec_readfw(struct fimc_is_core *core)
+{
+       int ret = 0;
+       char *buf = NULL;
+       loff_t pos = 0;
+       char fw_path[100];
+       char setfile_path[100];
+       char setf_name[50];
+       int retry = FIMC_IS_FW_RETRY_CNT;
+       int pixelSize;
+#ifdef USE_ION_ALLOC
+       struct ion_handle *handle = NULL;
+#endif
+
+       pr_info("Camera: FW, Setfile need to be dumped\n");
+#ifdef USE_ION_ALLOC
+       handle = ion_alloc(core->fimc_ion_client, (size_t)FIMC_IS_MAX_FW_SIZE, 0,
+                               EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+       if (IS_ERR_OR_NULL(handle)) {
+               err("(%s):failed to ioc_alloc\n",__func__);
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       buf = (char *)ion_map_kernel(core->fimc_ion_client, handle);
+       if (IS_ERR_OR_NULL(buf)) {
+               err("(%s)fail to ion_map_kernle\n",__func__);
+               ret = -ENOMEM;
+               goto exit;
+       }
+#else
+       buf = vmalloc(FIMC_IS_MAX_FW_SIZE);
+       if (!buf) {
+               err("vmalloc fail");
+               ret = -ENOMEM;
+               goto exit;
+       }
+#endif
+       crc_retry:
+
+       /* read fw data */
+       pr_info("Camera: Start SPI read fw data\n\n");
+       ret = fimc_is_spi_read_by_core(core->spi0, buf, 0x80000, FIMC_IS_MAX_FW_SIZE);
+       if (ret < 0) {
+               err("failed to fimc_is_spi_read (%d)\n", ret);
+               ret = -EINVAL;
+               goto exit;
+       }
+       pr_info("Camera: End SPI read fw data\n\n");
+
+       /* CRC check */
+       if (!fimc_is_sec_check_fw_crc32(buf) && (retry > 0)) {
+               retry--;
+               goto crc_retry;
+       } else if (!retry) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       snprintf(fw_path, sizeof(fw_path), "%s%s", FIMC_IS_FW_DUMP_PATH, FIMC_IS_FW);
+       if (write_data_to_file(fw_path, buf,
+                                       sysfs_finfo.bin_end_addr - sysfs_finfo.bin_start_addr + 1, &pos) < 0) {
+               ret = -EIO;
+               goto exit;
+       }
+
+       pr_info("Camera: FW Data has dumped successfully\n");
+
+       if (sysfs_finfo.header_ver[FW_SENSOR_MAKER] == FW_SENSOR_MAKER_SLSI) {
+               snprintf(setf_name, sizeof(setf_name), "%s", FIMC_IS_2P2_SETF);
+       } else if (sysfs_finfo.header_ver[FW_SENSOR_MAKER] == FW_SENSOR_MAKER_SONY) {
+               pixelSize = fimc_is_sec_get_pixel_size(sysfs_finfo.header_ver);
+               if (pixelSize == 13) {
+                       snprintf(setf_name, sizeof(setf_name), "%s", FIMC_IS_IMX135_SETF);
+               } else if (pixelSize == 8) {
+                       snprintf(setf_name, sizeof(setf_name), "%s", FIMC_IS_IMX134_SETF);
+               } else {
+                       snprintf(setf_name, sizeof(setf_name), "%s", FIMC_IS_IMX135_SETF);
+               }
+       } else {
+               snprintf(setf_name, sizeof(setf_name), "%s", FIMC_IS_2P2_SETF);
+       }
+
+       snprintf(setfile_path, sizeof(setfile_path), "%s%s", FIMC_IS_FW_DUMP_PATH, setf_name);
+       pos = 0;
+
+       if (write_data_to_file(setfile_path,
+                       buf+(sysfs_finfo.setfile_start_addr - sysfs_finfo.bin_start_addr),
+                       sysfs_finfo.setfile_end_addr - sysfs_finfo.setfile_start_addr + 1, &pos) < 0) {
+               ret = -EIO;
+               goto exit;
+       }
+
+       pr_info("Camera: Setfile has dumped successfully\n");
+       pr_info("Camera: FW, Setfile were dumped successfully\n");
+
+exit:
+#ifdef USE_ION_ALLOC
+       if (!IS_ERR_OR_NULL(buf)) {
+               ion_unmap_kernel(core->fimc_ion_client, handle);
+       }
+
+       if (!IS_ERR_OR_NULL(handle)) {
+               ion_free(core->fimc_ion_client, handle);
+       }
+#else
+       if (buf) {
+               vfree(buf);
+       }
+#endif
+       return ret;
+}
+#endif
+
+#ifdef CONFIG_COMPANION_USE
+int fimc_is_sec_read_companion_fw(struct fimc_is_core *core)
+{
+       int ret = 0;
+       char *buf = NULL;
+       loff_t pos = 0;
+       char fw_path[100];
+       char master_setfile_path[100];
+       char mode_setfile_path[100];
+       char master_setf_name[50];
+       char mode_setf_name[50];
+       int retry = FIMC_IS_FW_RETRY_CNT;
+#ifdef USE_ION_ALLOC
+       struct ion_handle *handle = NULL;
+#endif
+
+       pr_info("Camera: Companion FW, Setfile need to be dumped\n");
+#ifdef USE_ION_ALLOC
+       handle = ion_alloc(core->fimc_ion_client, (size_t)FIMC_IS_MAX_COMPANION_FW_SIZE, 0,
+                               EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+       if (IS_ERR_OR_NULL(handle)) {
+               err("(%s)failed to ioc_alloc\n",__func__);
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       buf = (char *)ion_map_kernel(core->fimc_ion_client, handle);
+       if (IS_ERR_OR_NULL(buf)) {
+               err("(%s)fail to ion_map_kernle\n",__func__);
+               ret = -ENOMEM;
+               goto exit;
+       }
+#else
+       buf = vmalloc(FIMC_IS_MAX_COMPANION_FW_SIZE);
+       if (!buf) {
+               err("vmalloc fail");
+               ret = -ENOMEM;
+               goto exit;
+       }
+#endif
+       crc_retry:
+
+       /* read companion fw data */
+       pr_info("Camera: Start SPI read companion fw data\n\n");
+       ret = fimc_is_spi_read_by_core(core->spi0, buf, 0x2B000, FIMC_IS_MAX_COMPANION_FW_SIZE);
+       if (ret < 0) {
+               err("failed to fimc_is_spi_read (%d)\n", ret);
+               ret = -EINVAL;
+               goto exit;
+       }
+       pr_info("Camera: End SPI read companion fw data\n\n");
+
+       /* CRC check */
+       if (!fimc_is_sec_check_companion_fw_crc32(buf) && (retry > 0)) {
+               retry--;
+               goto crc_retry;
+       } else if (!retry) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       if (sysfs_finfo.concord_header_ver[9] == 0) {
+               snprintf(fw_path, sizeof(fw_path), "%s%s",
+                       FIMC_IS_FW_DUMP_PATH, FIMC_IS_FW_COMPANION_EVT0);
+       } else if (sysfs_finfo.concord_header_ver[9] == 10) {
+               snprintf(fw_path, sizeof(fw_path), "%s%s",
+                       FIMC_IS_FW_DUMP_PATH, FIMC_IS_FW_COMPANION_EVT1);
+       }
+
+       if (write_data_to_file(fw_path, buf,
+                                       sysfs_finfo.concord_bin_end_addr - sysfs_finfo.concord_bin_start_addr + 1, &pos) < 0) {
+               ret = -EIO;
+               goto exit;
+       }
+
+       pr_info("Camera: Companion FW Data has dumped successfully\n");
+
+       if (sysfs_finfo.concord_header_ver[FW_SENSOR_MAKER] == FW_SENSOR_MAKER_SLSI) {
+               snprintf(master_setf_name, sizeof(master_setf_name), "%s", FIMC_IS_COMPANION_MASTER_SETF);
+               snprintf(mode_setf_name, sizeof(mode_setf_name), "%s", FIMC_IS_COMPANION_MODE_SETF);
+       } else {
+               snprintf(master_setf_name, sizeof(master_setf_name), "%s", FIMC_IS_COMPANION_MASTER_SETF);
+               snprintf(mode_setf_name, sizeof(mode_setf_name), "%s", FIMC_IS_COMPANION_MODE_SETF);
+       }
+
+       snprintf(master_setfile_path, sizeof(master_setfile_path), "%s%s", FIMC_IS_FW_DUMP_PATH, master_setf_name);
+       snprintf(mode_setfile_path, sizeof(mode_setfile_path), "%s%s", FIMC_IS_FW_DUMP_PATH, mode_setf_name);
+       pos = 0;
+
+       if (write_data_to_file(master_setfile_path,
+                       buf + sysfs_finfo.concord_master_setfile_start_addr,
+                       sysfs_finfo.concord_master_setfile_end_addr - sysfs_finfo.concord_master_setfile_start_addr + 1, &pos) < 0) {
+               ret = -EIO;
+               goto exit;
+       }
+       pos = 0;
+       if (write_data_to_file(mode_setfile_path,
+                       buf + sysfs_finfo.concord_mode_setfile_start_addr,
+                       sysfs_finfo.concord_mode_setfile_end_addr - sysfs_finfo.concord_mode_setfile_start_addr + 1, &pos) < 0) {
+               ret = -EIO;
+               goto exit;
+       }
+
+       pr_info("Camera: Companion Setfile has dumped successfully\n");
+       pr_info("Camera: Companion FW, Setfile were dumped successfully\n");
+
+exit:
+#ifdef USE_ION_ALLOC
+       if (!IS_ERR_OR_NULL(buf)) {
+               ion_unmap_kernel(core->fimc_ion_client, handle);
+       }
+
+       if (!IS_ERR_OR_NULL(handle)) {
+               ion_free(core->fimc_ion_client, handle);
+       }
+#else
+       if (buf) {
+               vfree(buf);
+       }
+#endif
+
+       return ret;
+}
+#endif
+
+#if 0
+int fimc_is_sec_gpio_enable(struct exynos_platform_fimc_is *pdata, char *name, bool on)
+{
+       struct gpio_set *gpio;
+       int ret = 0;
+       int i = 0;
+
+       for (i = 0; i < FIMC_IS_MAX_GPIO_NUM; i++) {
+                       gpio = &pdata->gpio_info->cfg[i];
+                       if (strcmp(gpio->name, name) == 0)
+                               break;
+                       else
+                               continue;
+       }
+
+       if (i == FIMC_IS_MAX_GPIO_NUM) {
+               pr_err("GPIO %s is not found!!\n", name);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       ret = gpio_request(gpio->pin, gpio->name);
+       if (ret) {
+               pr_err("Request GPIO error(%s)\n", gpio->name);
+               goto exit;
+       }
+
+       if (on) {
+               switch (gpio->act) {
+               case GPIO_PULL_NONE:
+                       s3c_gpio_cfgpin(gpio->pin, gpio->value);
+                       s3c_gpio_setpull(gpio->pin, S3C_GPIO_PULL_NONE);
+                       break;
+               case GPIO_OUTPUT:
+                       s3c_gpio_cfgpin(gpio->pin, S3C_GPIO_OUTPUT);
+                       s3c_gpio_setpull(gpio->pin, S3C_GPIO_PULL_NONE);
+                       gpio_set_value(gpio->pin, gpio->value);
+                       break;
+               case GPIO_INPUT:
+                       s3c_gpio_cfgpin(gpio->pin, S3C_GPIO_INPUT);
+                       s3c_gpio_setpull(gpio->pin, S3C_GPIO_PULL_NONE);
+                       gpio_set_value(gpio->pin, gpio->value);
+                       break;
+               case GPIO_RESET:
+                       s3c_gpio_setpull(gpio->pin, S3C_GPIO_PULL_NONE);
+                       gpio_direction_output(gpio->pin, 0);
+                       gpio_direction_output(gpio->pin, 1);
+                       break;
+               default:
+                       pr_err("unknown act for gpio\n");
+                       break;
+               }
+       } else {
+               s3c_gpio_cfgpin(gpio->pin, S3C_GPIO_INPUT);
+               s3c_gpio_setpull(gpio->pin, S3C_GPIO_PULL_DOWN);
+       }
+
+       gpio_free(gpio->pin);
+
+exit:
+       return ret;
+}
+#endif
+
+int fimc_is_sec_get_pixel_size(char *header_ver)
+{
+       int pixelsize = 0;
+
+       pixelsize += (int) (header_ver[FW_PIXEL_SIZE] - 0x30) * 10;
+       pixelsize += (int) (header_ver[FW_PIXEL_SIZE + 1] - 0x30);
+
+       return pixelsize;
+}
+
+int fimc_is_sec_core_voltage_select(struct device *dev, char *header_ver)
+{
+       struct regulator *regulator = NULL;
+       int ret = 0;
+       int minV, maxV;
+       int pixelSize = 0;
+
+       regulator = regulator_get(dev, "cam_sensor_core_1.2v");
+       if (IS_ERR_OR_NULL(regulator)) {
+               pr_err("%s : regulator_get fail\n",
+                       __func__);
+               return -EINVAL;
+       }
+       pixelSize = fimc_is_sec_get_pixel_size(header_ver);
+
+       if (header_ver[FW_SENSOR_MAKER] == FW_SENSOR_MAKER_SONY) {
+               if (pixelSize == 13) {
+                       minV = 1050000;
+                       maxV = 1050000;
+               } else if (pixelSize == 8) {
+                       minV = 1100000;
+                       maxV = 1100000;
+               } else {
+                       minV = 1050000;
+                       maxV = 1050000;
+               }
+       } else if (header_ver[FW_SENSOR_MAKER] == FW_SENSOR_MAKER_SLSI) {
+               minV = 1200000;
+               maxV = 1200000;
+       } else {
+               minV = 1050000;
+               maxV = 1050000;
+       }
+
+       ret = regulator_set_voltage(regulator, minV, maxV);
+
+       if (ret >= 0)
+               pr_info("%s : set_core_voltage %d, %d successfully\n",
+                               __func__, minV, maxV);
+       regulator_put(regulator);
+
+       return ret;
+}
+
+/**
+ * fimc_is_sec_ldo_enabled: check whether the ldo has already been enabled.
+ *
+ * @ return: true, false or error value
+ */
+static int fimc_is_sec_ldo_enabled(struct device *dev, char *name) {
+       struct regulator *regulator = NULL;
+       int enabled = 0;
+
+       regulator = regulator_get(dev, name);
+       if (IS_ERR_OR_NULL(regulator)) {
+               pr_err("%s : regulator_get(%s) fail\n", __func__, name);
+               return -EINVAL;
+       }
+
+       enabled = regulator_is_enabled(regulator);
+
+       regulator_put(regulator);
+
+       return enabled;
+}
+
+int fimc_is_sec_ldo_enable(struct device *dev, char *name, bool on)
+{
+       struct regulator *regulator = NULL;
+       int ret = 0;
+
+       regulator = regulator_get(dev, name);
+       if (IS_ERR_OR_NULL(regulator)) {
+               pr_err("%s : regulator_get(%s) fail\n", __func__, name);
+               return -EINVAL;
+       }
+
+       if (on) {
+               if (regulator_is_enabled(regulator)) {
+                       pr_warning("%s: regulator is already enabled\n", name);
+                       goto exit;
+               }
+
+               ret = regulator_enable(regulator);
+               if (ret) {
+                       pr_err("%s : regulator_enable(%s) fail\n", __func__, name);
+                       goto exit;
+               }
+       } else {
+               if (!regulator_is_enabled(regulator)) {
+                       pr_warning("%s: regulator is already disabled\n", name);
+                       goto exit;
+               }
+
+               ret = regulator_disable(regulator);
+               if (ret) {
+                       pr_err("%s : regulator_disable(%s) fail\n", __func__, name);
+                       goto exit;
+               }
+       }
+
+exit:
+       if (regulator)
+               regulator_put(regulator);
+
+       return ret;
+}
+
+int fimc_is_sec_fw_find(struct fimc_is_core *core, char *fw_name, char *setf_name)
+{
+       int pixelSize = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_device_sensor *sensor_device = &core->sensor[0];
+
+       BUG_ON(!sensor_device);
+       BUG_ON(!sensor_device->pdata);
+       BUG_ON(!sensor_device->pdata->sensor_id);
+
+       pdata = sensor_device->pdata;
+
+       if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_2P2_F) ||
+               fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_2P2_I)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_2P2), "%s", FIMC_IS_FW_2P2);
+               snprintf(setf_name, sizeof(FIMC_IS_2P2_SETF), "%s", FIMC_IS_2P2_SETF);
+       } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_2P2_12M)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_2P2_12M), "%s", FIMC_IS_FW_2P2_12M);
+               snprintf(setf_name, sizeof(FIMC_IS_2P2_12M_SETF), "%s", FIMC_IS_2P2_12M_SETF);
+       } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_2P3)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_2P3), "%s", FIMC_IS_FW_2P3);
+               snprintf(setf_name, sizeof(FIMC_IS_2P3_SETF), "%s", FIMC_IS_2P3_SETF);
+       } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_4H5)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_4H5), "%s", FIMC_IS_FW_4H5);
+               snprintf(setf_name, sizeof(FIMC_IS_4H5_SETF), "%s", FIMC_IS_4H5_SETF);
+       } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_IMX240) ||
+               fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, FW_IMX240_Q)) {
+               snprintf(fw_name, sizeof(FIMC_IS_FW_IMX240), "%s", FIMC_IS_FW_IMX240);
+               snprintf(setf_name, sizeof(FIMC_IS_IMX240_SETF), "%s", FIMC_IS_IMX240_SETF);
+       } else {
+               /* Use the PixelSize information */
+               pixelSize = fimc_is_sec_get_pixel_size(sysfs_finfo.header_ver);
+               if (pixelSize == 16) {
+                       if (pdata->sensor_id == SENSOR_NAME_S5K2P3) {
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_2P3), "%s", FIMC_IS_FW_2P3);
+                               snprintf(setf_name, sizeof(FIMC_IS_2P3_SETF), "%s", FIMC_IS_2P3_SETF);
+                       } else {
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_2P2), "%s", FIMC_IS_FW_2P2);
+                               snprintf(setf_name, sizeof(FIMC_IS_2P2_SETF), "%s", FIMC_IS_2P2_SETF);
+                       }
+               } else if (pixelSize == 13) {
+                       snprintf(fw_name, sizeof(FIMC_IS_FW), "%s", FIMC_IS_FW);
+                       snprintf(setf_name, sizeof(FIMC_IS_IMX135_SETF), "%s", FIMC_IS_IMX135_SETF);
+               } else if (pixelSize == 12) {
+                       snprintf(fw_name, sizeof(FIMC_IS_FW_2P2_12M), "%s", FIMC_IS_FW_2P2_12M);
+                       snprintf(setf_name, sizeof(FIMC_IS_2P2_12M_SETF), "%s", FIMC_IS_2P2_12M_SETF);
+               } else if (pixelSize == 8) {
+                       snprintf(fw_name, sizeof(FIMC_IS_FW_IMX134), "%s", FIMC_IS_FW_IMX134);
+                       snprintf(setf_name, sizeof(FIMC_IS_IMX134_SETF), "%s", FIMC_IS_IMX134_SETF);
+               } else {
+                       /* default firmware and setfile */
+                       if ( pdata->sensor_id == SENSOR_NAME_IMX240 ) {
+                               /* IMX240 */
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_IMX240), "%s", FIMC_IS_FW_IMX240);
+                               snprintf(setf_name, sizeof(FIMC_IS_IMX240_SETF), "%s", FIMC_IS_IMX240_SETF);
+                       } else if ( pdata->sensor_id == SENSOR_NAME_IMX134 ) {
+                               /* IMX134 */
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_IMX134), "%s", FIMC_IS_FW_IMX134);
+                               snprintf(setf_name, sizeof(FIMC_IS_IMX134_SETF), "%s", FIMC_IS_IMX134_SETF);
+                       } else if ( pdata->sensor_id == SENSOR_NAME_S5K2P2_12M ) {
+                               /* 2P2_12M */
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_2P2_12M), "%s", FIMC_IS_FW_2P2_12M);
+                               snprintf(setf_name, sizeof(FIMC_IS_2P2_12M_SETF), "%s", FIMC_IS_2P2_12M_SETF);
+                       } else if ( pdata->sensor_id == SENSOR_NAME_S5K2P2 ) {
+                               /* 2P2 */
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_2P2), "%s", FIMC_IS_FW_2P2);
+                               snprintf(setf_name, sizeof(FIMC_IS_2P2_SETF), "%s", FIMC_IS_2P2_SETF);
+                       } else if ( pdata->sensor_id == SENSOR_NAME_S5K2P3 ) {
+                               /* 2P3 */
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_2P3), "%s", FIMC_IS_FW_2P3);
+                               snprintf(setf_name, sizeof(FIMC_IS_2P3_SETF), "%s", FIMC_IS_2P3_SETF);
+                       } else if ( pdata->sensor_id == SENSOR_NAME_S5K4H5 ) {
+                               /* 4H5 */
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_4H5), "%s", FIMC_IS_FW_4H5);
+                               snprintf(setf_name, sizeof(FIMC_IS_4H5_SETF), "%s", FIMC_IS_4H5_SETF);
+                       } else {
+                               snprintf(fw_name, sizeof(FIMC_IS_FW), "%s", FIMC_IS_FW);
+                               snprintf(setf_name, sizeof(FIMC_IS_IMX135_SETF), "%s", FIMC_IS_IMX135_SETF);
+                       }
+               }
+       }
+
+       strcpy(sysfs_finfo.load_fw_name, fw_name);
+       strcpy(sysfs_finfo.load_setfile_name, setf_name);
+
+       return 0;
+}
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR) || defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+int fimc_is_sec_fw_sel_eeprom(struct device *dev,
+                char *fw_name, char *setf_name, int id, bool headerOnly)
+{
+       int ret = 0;
+       char fw_path[100];
+       char phone_fw_version[12] = {0, };
+
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long fsize, nread;
+       u8 *fw_buf = NULL;
+       bool is_ldo_enabled = false;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fimc_is_core *core = (struct fimc_is_core *)platform_get_drvdata(pdev);
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_device_sensor *sensor_device = &core->sensor[0];
+
+       BUG_ON(!sensor_device);
+       BUG_ON(!sensor_device->pdata);
+       BUG_ON(!sensor_device->pdata->sensor_id);
+
+       pdata = sensor_device->pdata;
+
+       /* Use mutex for i2c read */
+       mutex_lock(&core->spi_lock);
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+       if (id == SENSOR_POSITION_FRONT) {
+               if (!sysfs_finfo_front.is_caldata_read || force_caldata_dump) {
+                       if (force_caldata_dump)
+                               pr_info("forced caldata dump!!\n");
+
+                       if (!fimc_is_sec_ldo_enabled(dev, "VT_CAM_1.8V")) {
+                               ret = fimc_is_sec_ldo_enable(dev, "VT_CAM_1.8V", true);
+                               if (ret) {
+                                       pr_err("fimc_is_sec_fw_sel_eeprom: error, failed to cam_io(on)");
+                                       goto exit;
+                               }
+
+                               is_ldo_enabled = true;
+                       }
+
+                       pr_info("Camera: read cal data from Front EEPROM\n");
+                       if ((fimc_is_sec_readcal_eeprom(dev, SENSOR_POSITION_FRONT) != -EIO) &&
+                                       crc32_header_check_front) {
+                               sysfs_finfo_front.is_caldata_read = true;
+                       }
+               }
+               goto exit;
+       } else
+#endif
+       {
+               if (!sysfs_finfo.is_caldata_read || force_caldata_dump) {
+                       is_dumped_fw_loading_needed = false;
+                       if (force_caldata_dump)
+                               pr_info("forced caldata dump!!\n");
+
+                       if (!fimc_is_sec_ldo_enabled(dev, "CAM_IO_1.8V_AP")) {
+                               ret = fimc_is_sec_ldo_enable(dev, "CAM_IO_1.8V_AP", true);
+                               if (ret) {
+                                       pr_err("fimc_is_sec_fw_sel_eeprom: error, failed to cam_io(on)");
+                                       goto exit;
+                               }
+
+                               is_ldo_enabled = true;
+                       }
+
+                       pr_info("Camera: read cal data from Rear EEPROM\n");
+                       if (headerOnly) {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+                               fimc_is_sec_read_eeprom_header(dev);
+#endif
+                       } else {
+                               if ((fimc_is_sec_readcal_eeprom(dev, SENSOR_POSITION_REAR) != -EIO) &&
+                                               crc32_header_check) {
+                                       sysfs_finfo.is_caldata_read = true;
+                               }
+                       }
+               }
+       }
+
+       fimc_is_sec_fw_find(core, fw_name, setf_name);
+       if (headerOnly) {
+               goto exit;
+       }
+
+       snprintf(fw_path, sizeof(fw_path), "%s%s", FIMC_IS_FW_PATH, fw_name);
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       fp = filp_open(fw_path, O_RDONLY, 0);
+       if (IS_ERR(fp)) {
+               pr_err("Camera: Failed open phone firmware\n");
+               ret = -EIO;
+               fp = NULL;
+               goto read_phone_fw_exit;
+       }
+
+       fsize = fp->f_path.dentry->d_inode->i_size;
+       pr_info("start, file path %s, size %ld Bytes\n",
+               fw_path, fsize);
+       fw_buf = vmalloc(fsize);
+       if (!fw_buf) {
+               pr_err("failed to allocate memory\n");
+               ret = -ENOMEM;
+               goto read_phone_fw_exit;
+       }
+       nread = vfs_read(fp, (char __user *)fw_buf, fsize, &fp->f_pos);
+       if (nread != fsize) {
+               pr_err("failed to read firmware file, %ld Bytes\n", nread);
+               ret = -EIO;
+               goto read_phone_fw_exit;
+       }
+
+       strncpy(phone_fw_version, fw_buf + nread - 11, 11);
+       strncpy(sysfs_pinfo.header_ver, fw_buf + nread - 11, 11);
+       pr_info("Camera: phone fw version: %s\n", phone_fw_version);
+read_phone_fw_exit:
+       if (fw_buf) {
+               vfree(fw_buf);
+               fw_buf = NULL;
+       }
+
+       if (fp) {
+               filp_close(fp, current->files);
+               fp = NULL;
+       }
+
+       set_fs(old_fs);
+
+exit:
+       if (is_ldo_enabled) {
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+               if (id == SENSOR_POSITION_FRONT) {
+                       ret = fimc_is_sec_ldo_enable(dev, "VT_CAM_1.8V", false);
+               } else
+#endif
+               {
+                       ret = fimc_is_sec_ldo_enable(dev, "CAM_IO_1.8V_AP", false);
+               }
+               if (ret)
+                       pr_err("fimc_is_sec_fw_sel_eeprom: error, failed to cam_io(off)");
+       }
+
+       mutex_unlock(&core->spi_lock);
+
+       return ret;
+}
+#endif
+
+#if !defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+int fimc_is_sec_fw_sel(struct fimc_is_core *core, struct device *dev,
+       char *fw_name, char *setf_name, bool headerOnly)
+{
+       int ret = 0;
+#if 1
+       char fw_path[100];
+       char dump_fw_path[100];
+       char dump_fw_version[12] = {0, };
+       char phone_fw_version[12] = {0, };
+       int from_fw_revision = 0;
+       int dump_fw_revision = 0;
+       int phone_fw_revision = 0;
+
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long fsize, nread;
+       u8 *fw_buf = NULL;
+       bool is_dump_existed = false;
+       bool is_dump_needed = true;
+#endif
+#ifdef CONFIG_COMPANION_USE
+       struct fimc_is_spi_gpio *spi_gpio = &core->spi_gpio;
+#endif
+       bool is_ldo_enabled = false;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct fimc_is_device_sensor *sensor_device = &core->sensor[0];
+
+       BUG_ON(!sensor_device);
+       BUG_ON(!sensor_device->pdata);
+       BUG_ON(!sensor_device->pdata->sensor_id);
+
+       pdata = sensor_device->pdata;
+
+       /* Use mutex for spi read */
+       mutex_lock(&core->spi_lock);
+       if (!sysfs_finfo.is_caldata_read || force_caldata_dump) {
+               is_dumped_fw_loading_needed = false;
+               if (force_caldata_dump)
+                       pr_info("forced caldata dump!!\n");
+               if (!fimc_is_sec_ldo_enabled(dev, "CAM_IO_1.8V_AP")) {
+                       pr_info("enable %s in the %s\n", "CAM_IO_1.8V_AP", __func__);
+                       ret = fimc_is_sec_ldo_enable(dev, "CAM_IO_1.8V_AP", true);
+                       if (ret) {
+                               pr_err("fimc_is_sec_fw_sel: error, failed to cam_io(on)");
+                               goto exit;
+                       }
+
+                       is_ldo_enabled = true;
+               }
+               pr_info("read cal data from FROM\n");
+#ifdef CONFIG_COMPANION_USE
+               fimc_is_set_spi_config(spi_gpio, FIMC_IS_SPI_FUNC, false);
+#endif
+
+               if (headerOnly) {
+                       fimc_is_sec_read_from_header(dev);
+               } else {
+                       if ((fimc_is_sec_readcal(core) != -EIO) &&
+                                       crc32_header_check) {
+                               sysfs_finfo.is_caldata_read = true;
+                       }
+               }
+
+#ifdef CONFIG_COMPANION_USE
+               fimc_is_set_spi_config(spi_gpio, FIMC_IS_SPI_OUTPUT, false);
+#endif
+               /*select AF actuator*/
+               if (!crc32_header_check) {
+                       pr_info("Camera : CRC32 error for all section.\n");
+                       //ret = -EIO;
+                       //goto exit;
+               }
+
+               /*ret = fimc_is_sec_core_voltage_select(dev, sysfs_finfo.header_ver);
+               if (ret < 0) {
+                       err("failed to fimc_is_sec_core_voltage_select (%d)\n", ret);
+                       ret = -EINVAL;
+                       goto exit;
+               }*/
+
+               fimc_is_sec_fw_find(core, fw_name, setf_name);
+               if (headerOnly) {
+                       goto exit;
+               }
+
+               snprintf(fw_path, sizeof(fw_path), "%s%s", FIMC_IS_FW_PATH, fw_name);
+
+#if 1
+               snprintf(dump_fw_path, sizeof(dump_fw_path), "%s%s",
+                       FIMC_IS_FW_DUMP_PATH, fw_name);
+               pr_info("Camera: f-rom fw version: %s\n", sysfs_finfo.header_ver);
+
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+               fp = filp_open(dump_fw_path, O_RDONLY, 0);
+               if (IS_ERR(fp)) {
+                       pr_info("Camera: There is no dumped firmware\n");
+                       is_dump_existed = false;
+                       goto read_phone_fw;
+               } else {
+                       is_dump_existed = true;
+               }
+
+               fsize = fp->f_path.dentry->d_inode->i_size;
+               pr_info("start, file path %s, size %ld Bytes\n",
+                       dump_fw_path, fsize);
+               fw_buf = vmalloc(fsize);
+               if (!fw_buf) {
+                       pr_err("failed to allocate memory\n");
+                       ret = -ENOMEM;
+                       goto read_phone_fw;
+               }
+               nread = vfs_read(fp, (char __user *)fw_buf, fsize, &fp->f_pos);
+               if (nread != fsize) {
+                       pr_err("failed to read firmware file, %ld Bytes\n", nread);
+                       ret = -EIO;
+                       goto read_phone_fw;
+               }
+
+               strncpy(dump_fw_version, fw_buf+nread-11, 11);
+               pr_info("Camera: dumped fw version: %s\n", dump_fw_version);
+
+read_phone_fw:
+               if (fw_buf) {
+                       vfree(fw_buf);
+                       fw_buf = NULL;
+               }
+
+               if (fp && is_dump_existed) {
+                       filp_close(fp, current->files);
+                       fp = NULL;
+               }
+
+               set_fs(old_fs);
+
+               if (ret < 0)
+                       goto exit;
+#endif
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               fp = filp_open(fw_path, O_RDONLY, 0);
+               if (IS_ERR(fp)) {
+                       pr_err("Camera: Failed open phone firmware\n");
+                       ret = -EIO;
+                       fp = NULL;
+                       goto read_phone_fw_exit;
+               }
+
+               fsize = fp->f_path.dentry->d_inode->i_size;
+               pr_info("start, file path %s, size %ld Bytes\n",
+                       fw_path, fsize);
+               fw_buf = vmalloc(fsize);
+               if (!fw_buf) {
+                       pr_err("failed to allocate memory\n");
+                       ret = -ENOMEM;
+                       goto read_phone_fw_exit;
+               }
+               nread = vfs_read(fp, (char __user *)fw_buf, fsize, &fp->f_pos);
+               if (nread != fsize) {
+                       pr_err("failed to read firmware file, %ld Bytes\n", nread);
+                       ret = -EIO;
+                       goto read_phone_fw_exit;
+               }
+
+               strncpy(phone_fw_version, fw_buf + nread - 11, 11);
+               strncpy(sysfs_pinfo.header_ver, fw_buf + nread - 11, 11);
+               pr_info("Camera: phone fw version: %s\n", phone_fw_version);
+read_phone_fw_exit:
+               if (fw_buf) {
+                       vfree(fw_buf);
+                       fw_buf = NULL;
+               }
+
+               if (fp) {
+                       filp_close(fp, current->files);
+                       fp = NULL;
+               }
+
+               set_fs(old_fs);
+
+               if (ret < 0)
+                       goto exit;
+
+               from_fw_revision = fimc_is_sec_fw_revision(sysfs_finfo.header_ver);
+               phone_fw_revision = fimc_is_sec_fw_revision(phone_fw_version);
+               if (is_dump_existed)
+                       dump_fw_revision = fimc_is_sec_fw_revision(dump_fw_version);
+
+               if ((!fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver, phone_fw_version)) ||
+                               (from_fw_revision > phone_fw_revision)) {
+                       is_dumped_fw_loading_needed = true;
+                       if (is_dump_existed) {
+                               if (!fimc_is_sec_fw_module_compare(sysfs_finfo.header_ver,
+                                                       dump_fw_version)) {
+                                       is_dump_needed = true;
+                               } else if (from_fw_revision > dump_fw_revision) {
+                                       is_dump_needed = true;
+                               } else {
+                                       is_dump_needed = false;
+                               }
+                       } else {
+                               is_dump_needed = true;
+                       }
+               } else {
+                       is_dump_needed = false;
+                       if (is_dump_existed) {
+                               if (!fimc_is_sec_fw_module_compare(phone_fw_version,
+                                                       dump_fw_version)) {
+                                       is_dumped_fw_loading_needed = false;
+                               } else if (phone_fw_revision > dump_fw_revision) {
+                                       is_dumped_fw_loading_needed = false;
+                               } else {
+                                       is_dumped_fw_loading_needed = true;
+                               }
+                       } else {
+                               is_dumped_fw_loading_needed = false;
+                       }
+               }
+#if 0
+               if (sysfs_finfo.header_ver[0] == 'O') {
+                       /* hack: gumi module using phone fw */
+                       is_dumped_fw_loading_needed = false;
+                       is_dump_needed = false;
+               } else if (sysfs_finfo.header_ver[FW_ISP_COMPANY] != FW_ISP_COMPANY_LSI) {
+                       ret = -EINVAL;
+                       goto exit;
+               }
+
+               if (is_dump_needed) {
+                       ret = fimc_is_sec_readfw(core);
+                       if (ret < 0) {
+                               if (!crc32_fw_check) {
+                                       is_dumped_fw_loading_needed = false;
+                                       ret = 0;
+                               } else
+                                       goto exit;
+                       }
+               }
+#endif
+               if (is_dump_needed && is_dumped_fw_loading_needed) {
+                       strncpy(loaded_fw, sysfs_finfo.header_ver, 11);
+               } else if (!is_dump_needed && is_dumped_fw_loading_needed) {
+                       strncpy(loaded_fw, dump_fw_version, 11);
+               } else
+                       strncpy(loaded_fw, phone_fw_version, 11);
+
+       } else {
+               pr_info("Did not read cal data from FROM, FW version = %s\n", sysfs_finfo.header_ver);
+               strcpy(fw_name, sysfs_finfo.load_fw_name);
+               strcpy(setf_name, sysfs_finfo.load_setfile_name);
+       }
+
+exit:
+       if (is_ldo_enabled && !core->running_rear_camera) {
+               pr_info("disable %s in the %s\n", "CAM_IO_1.8V_AP", __func__);
+               ret = fimc_is_sec_ldo_enable(dev, "CAM_IO_1.8V_AP", false);
+               if (ret)
+                       pr_err("fimc_is_sec_fw_sel: error, failed to cam_io(off)");
+       }
+
+       mutex_unlock(&core->spi_lock);
+
+       if (core->use_module_check) {
+               if (sysfs_finfo.header_ver[3] != 'L') {
+                       pr_err("Not supported module. Module ver = %s", sysfs_finfo.header_ver);
+                       return  -EIO;
+               }
+       }
+
+       return ret;
+}
+#endif
+
+#ifdef CONFIG_COMPANION_USE
+void fimc_is_set_spi_config(struct fimc_is_spi_gpio *spi_gpio, int func, bool ssn) {
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_sclk,
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, func));
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_miso,
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, func));
+       pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_mois,
+                       PINCFG_PACK(PINCFG_TYPE_FUNC, func));
+       if(ssn == true) {
+               pin_config_set(FIMC_IS_SPI_PINNAME, spi_gpio->spi_ssn,
+                               PINCFG_PACK(PINCFG_TYPE_FUNC, func));
+       }
+}
+
+int fimc_is_sec_concord_fw_sel(struct fimc_is_core *core, struct device *dev,
+       char *fw_name, char *master_setf_name, char *mode_setf_name)
+{
+       int ret = 0;
+       char c1_fw_path[100];
+       char dump_c1_fw_path[100];
+       char dump_c1_fw_version[12] = {0, };
+       char phone_c1_fw_version[12] = {0, };
+       int from_c1_fw_revision = 0;
+       int dump_c1_fw_revision = 0;
+       int phone_c1_fw_revision = 0;
+
+       struct file *fp = NULL;
+       mm_segment_t old_fs;
+       long fsize, nread;
+       u8 *c1_fw_buf = NULL;
+       bool is_dump_existed = false;
+       bool is_dump_needed = true;
+       int pixelSize = 0;
+
+       if ((!sysfs_finfo.is_c1_caldata_read &&
+           (cam_id == CAMERA_SINGLE_REAR /* || cam_id == CAMERA_DUAL_FRONT*/)) ||
+           force_caldata_dump) {
+               is_dumped_c1_fw_loading_needed = false;
+               if (force_caldata_dump)
+                       pr_info("forced caldata dump!!\n");
+
+               pr_info("Load companion fw from FROM\n");
+               sysfs_finfo.is_c1_caldata_read = true;
+
+               /*ret = fimc_is_sec_core_voltage_select(dev, sysfs_finfo.header_ver);
+               if (ret < 0) {
+                       err("failed to fimc_is_sec_core_voltage_select (%d)\n", ret);
+                       ret = -EINVAL;
+                       goto exit;
+               }*/
+
+               if (fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, FW_2P2_F) ||
+                       fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, FW_2P2_I)) {
+                       if (sysfs_finfo.concord_header_ver[9] == '0') {
+                               snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                       FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_EVT0);
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_EVT0), "%s", FIMC_IS_FW_COMPANION_EVT0);
+                       } else if (sysfs_finfo.concord_header_ver[9] == '1') {
+                               snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                       FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_2P2_EVT1);
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_2P2_EVT1), "%s", FIMC_IS_FW_COMPANION_2P2_EVT1);
+                       } else {
+                               pr_info("Camera : Wrong companion module version.\n");
+                       }
+                       sysfs_finfo.sensor_id = COMPANION_SENSOR_2P2;
+                       snprintf(master_setf_name, sizeof(FIMC_IS_COMPANION_2P2_MASTER_SETF), "%s", FIMC_IS_COMPANION_2P2_MASTER_SETF);
+                       snprintf(mode_setf_name, sizeof(FIMC_IS_COMPANION_2P2_MODE_SETF), "%s", FIMC_IS_COMPANION_2P2_MODE_SETF);
+               } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, FW_IMX240) ||
+                       fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, FW_IMX240_Q_C1) ||
+                       fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, FW_IMX240_Q)) {
+                       if (sysfs_finfo.concord_header_ver[9] == '0') {
+                               snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                       FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_EVT0);
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_EVT0), "%s", FIMC_IS_FW_COMPANION_EVT0);
+                       } else if (sysfs_finfo.concord_header_ver[9] == '1') {
+                               snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                       FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_IMX240_EVT1);
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_IMX240_EVT1), "%s", FIMC_IS_FW_COMPANION_IMX240_EVT1);
+                       } else {
+                               pr_info("Camera : Wrong companion module version.\n");
+                       }
+                       sysfs_finfo.sensor_id = COMPANION_SENSOR_IMX240;
+                       snprintf(master_setf_name, sizeof(FIMC_IS_COMPANION_IMX240_MASTER_SETF), "%s", FIMC_IS_COMPANION_IMX240_MASTER_SETF);
+                       snprintf(mode_setf_name, sizeof(FIMC_IS_COMPANION_IMX240_MODE_SETF), "%s", FIMC_IS_COMPANION_IMX240_MODE_SETF);
+               } else if (fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, FW_2P2_12M)) {
+                       if (sysfs_finfo.concord_header_ver[9] == '0') {
+                               snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                       FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_EVT0);
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_EVT0), "%s", FIMC_IS_FW_COMPANION_EVT0);
+                       } else if (sysfs_finfo.concord_header_ver[9] == '1') {
+                               snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                       FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_2P2_12M_EVT1);
+                               snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_2P2_12M_EVT1), "%s", FIMC_IS_FW_COMPANION_2P2_12M_EVT1);
+                       } else {
+                               pr_info("Camera : Wrong companion module version.\n");
+                       }
+                       sysfs_finfo.sensor_id = COMPANION_SENSOR_2P2;
+                       snprintf(master_setf_name, sizeof(FIMC_IS_COMPANION_2P2_12M_MASTER_SETF), "%s", FIMC_IS_COMPANION_2P2_12M_MASTER_SETF);
+                       snprintf(mode_setf_name, sizeof(FIMC_IS_COMPANION_2P2_12M_MODE_SETF), "%s", FIMC_IS_COMPANION_2P2_12M_MODE_SETF);
+               } else {
+                       pixelSize = fimc_is_sec_get_pixel_size(sysfs_finfo.concord_header_ver);
+                       if (pixelSize == 16) {
+                               if (sysfs_finfo.concord_header_ver[9] == '0') {
+                                       snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                               FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_EVT0);
+                                       snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_EVT0), "%s", FIMC_IS_FW_COMPANION_EVT0);
+                               } else if (sysfs_finfo.concord_header_ver[9] == '1') {
+                                       snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                               FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_2P2_EVT1);
+                                       snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_2P2_EVT1), "%s", FIMC_IS_FW_COMPANION_2P2_EVT1);
+                               } else {
+                                       pr_info("Camera : Wrong companion module version.\n");
+                               }
+                               sysfs_finfo.sensor_id = COMPANION_SENSOR_2P2;
+                               snprintf(master_setf_name, sizeof(FIMC_IS_COMPANION_2P2_MASTER_SETF), "%s", FIMC_IS_COMPANION_2P2_MASTER_SETF);
+                               snprintf(mode_setf_name, sizeof(FIMC_IS_COMPANION_2P2_MODE_SETF), "%s", FIMC_IS_COMPANION_2P2_MODE_SETF);
+                       } else if (pixelSize == 12) {
+                               if (sysfs_finfo.concord_header_ver[9] == '0') {
+                                       snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                               FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_EVT0);
+                                       snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_EVT0), "%s", FIMC_IS_FW_COMPANION_EVT0);
+                               } else if (sysfs_finfo.concord_header_ver[9] == '1') {
+                                       snprintf(c1_fw_path, sizeof(c1_fw_path), "%s%s",
+                                               FIMC_IS_FW_PATH, FIMC_IS_FW_COMPANION_2P2_12M_EVT1);
+                                       snprintf(fw_name, sizeof(FIMC_IS_FW_COMPANION_2P2_12M_EVT1), "%s", FIMC_IS_FW_COMPANION_2P2_12M_EVT1);
+                               } else {
+                                       pr_info("Camera : Wrong companion module version.\n");
+                               }
+                               sysfs_finfo.sensor_id = COMPANION_SENSOR_2P2;
+                               snprintf(master_setf_name, sizeof(FIMC_IS_COMPANION_2P2_12M_MASTER_SETF), "%s", FIMC_IS_COMPANION_2P2_12M_MASTER_SETF);
+                               snprintf(mode_setf_name, sizeof(FIMC_IS_COMPANION_2P2_12M_MODE_SETF), "%s", FIMC_IS_COMPANION_2P2_12M_MODE_SETF);
+                       }
+               }
+
+               strcpy(sysfs_finfo.load_c1_fw_name, fw_name);
+               strcpy(sysfs_finfo.load_c1_mastersetf_name, master_setf_name);
+               strcpy(sysfs_finfo.load_c1_modesetf_name, mode_setf_name);
+
+               if (sysfs_finfo.concord_header_ver[9] == '0') {
+                       snprintf(dump_c1_fw_path, sizeof(dump_c1_fw_path), "%s%s",
+                               FIMC_IS_FW_DUMP_PATH, FIMC_IS_FW_COMPANION_EVT0);
+               } else if (sysfs_finfo.concord_header_ver[9] == '1') {
+                       snprintf(dump_c1_fw_path, sizeof(dump_c1_fw_path), "%s%s",
+                               FIMC_IS_FW_DUMP_PATH, sysfs_finfo.load_c1_fw_name);
+               }
+               pr_info("Camera: f-rom fw version: %s\n", sysfs_finfo.concord_header_ver);
+
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+               ret = 0;
+               fp = filp_open(dump_c1_fw_path, O_RDONLY, 0);
+               if (IS_ERR(fp)) {
+                       pr_info("Camera: There is no dumped Companion firmware\n");
+                       is_dump_existed = false;
+                       goto read_phone_fw;
+               } else {
+                       is_dump_existed = true;
+               }
+
+               fsize = fp->f_path.dentry->d_inode->i_size;
+               pr_info("start, file path %s, size %ld Bytes\n",
+                       dump_c1_fw_path, fsize);
+               c1_fw_buf = vmalloc(fsize);
+               if (!c1_fw_buf) {
+                       pr_err("failed to allocate memory\n");
+                       ret = -ENOMEM;
+                       goto read_phone_fw;
+               }
+               nread = vfs_read(fp, (char __user *)c1_fw_buf, fsize, &fp->f_pos);
+               if (nread != fsize) {
+                       pr_err("failed to read firmware file, %ld Bytes\n", nread);
+                       ret = -EIO;
+                       goto read_phone_fw;
+               }
+
+               strncpy(dump_c1_fw_version, c1_fw_buf+nread - 16, 11);
+               pr_info("Camera: dumped companion fw version: %s\n", dump_c1_fw_version);
+read_phone_fw:
+               if (c1_fw_buf) {
+                       vfree(c1_fw_buf);
+                       c1_fw_buf = NULL;
+               }
+
+               if (fp && is_dump_existed) {
+                       filp_close(fp, current->files);
+                       fp = NULL;
+               }
+
+               set_fs(old_fs);
+               if (ret < 0)
+                       goto exit;
+
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               fp = filp_open(c1_fw_path, O_RDONLY, 0);
+               if (IS_ERR(fp)) {
+                       pr_err("Camera: Failed open phone companion firmware\n");
+                       ret = -EIO;
+                       fp = NULL;
+                       goto read_phone_fw_exit;
+               }
+
+               fsize = fp->f_path.dentry->d_inode->i_size;
+               pr_info("start, file path %s, size %ld Bytes\n",
+                       c1_fw_path, fsize);
+               c1_fw_buf = vmalloc(fsize);
+               if (!c1_fw_buf) {
+                       pr_err("failed to allocate memory\n");
+                       ret = -ENOMEM;
+                       goto read_phone_fw_exit;
+               }
+               nread = vfs_read(fp, (char __user *)c1_fw_buf, fsize, &fp->f_pos);
+               if (nread != fsize) {
+                       pr_err("failed to read companion firmware file, %ld Bytes\n", nread);
+                       ret = -EIO;
+                       goto read_phone_fw_exit;
+               }
+
+               strncpy(phone_c1_fw_version, c1_fw_buf + nread - 16, 11);
+               strncpy(sysfs_pinfo.concord_header_ver, c1_fw_buf + nread - 16, 11);
+               pr_info("Camera: phone companion fw version: %s\n", phone_c1_fw_version);
+read_phone_fw_exit:
+               if (c1_fw_buf) {
+                       vfree(c1_fw_buf);
+                       c1_fw_buf = NULL;
+               }
+
+               if (fp) {
+                       filp_close(fp, current->files);
+                       fp = NULL;
+               }
+
+               set_fs(old_fs);
+
+               if (ret < 0)
+                       goto exit;
+
+               from_c1_fw_revision = fimc_is_sec_fw_revision(sysfs_finfo.concord_header_ver);
+               phone_c1_fw_revision = fimc_is_sec_fw_revision(phone_c1_fw_version);
+               if (is_dump_existed)
+                       dump_c1_fw_revision = fimc_is_sec_fw_revision(dump_c1_fw_version);
+
+               if ((!fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver, phone_c1_fw_version)) ||
+                               (from_c1_fw_revision > phone_c1_fw_revision)) {
+                       is_dumped_c1_fw_loading_needed = true;
+                       if (is_dump_existed) {
+                               if (!fimc_is_sec_fw_module_compare(sysfs_finfo.concord_header_ver,
+                                                       dump_c1_fw_version)) {
+                                       is_dump_needed = true;
+                               } else if (from_c1_fw_revision > dump_c1_fw_revision) {
+                                       is_dump_needed = true;
+                               } else {
+                                       is_dump_needed = false;
+                               }
+                       } else {
+                               is_dump_needed = true;
+                       }
+               } else {
+                       is_dump_needed = false;
+                       if (is_dump_existed) {
+                               if (!fimc_is_sec_fw_module_compare(phone_c1_fw_version,
+                                                       dump_c1_fw_version)) {
+                                       is_dumped_c1_fw_loading_needed = false;
+                               } else if (phone_c1_fw_revision > dump_c1_fw_revision) {
+                                       is_dumped_c1_fw_loading_needed = false;
+                               } else {
+                                       is_dumped_c1_fw_loading_needed = true;
+                               }
+                       } else {
+                               is_dumped_c1_fw_loading_needed = false;
+                       }
+               }
+#if 0
+               if (is_dump_needed) {
+                       ret = fimc_is_sec_read_companion_fw(core);
+                       if (ret < 0) {
+                               if (!crc32_c1_fw_check) {
+                                       is_dumped_c1_fw_loading_needed = false;
+                                       ret = 0;
+                               } else
+                                       goto exit;
+                       }
+               }
+#endif
+               if (is_dump_needed && is_dumped_c1_fw_loading_needed) {
+                       strncpy(loaded_companion_fw, sysfs_finfo.concord_header_ver, 11);
+               } else if (!is_dump_needed && is_dumped_c1_fw_loading_needed) {
+                       strncpy(loaded_companion_fw, dump_c1_fw_version, 11);
+               } else
+                       strncpy(loaded_companion_fw, phone_c1_fw_version, 11);
+       } else {
+               pr_info("Did not Load companion fw from FROM, Companion version = %s\n", sysfs_finfo.concord_header_ver);
+               strcpy(fw_name, sysfs_finfo.load_c1_fw_name);
+               strcpy(master_setf_name, sysfs_finfo.load_c1_mastersetf_name);
+               strcpy(mode_setf_name, sysfs_finfo.load_c1_modesetf_name);
+       }
+
+exit:
+       return ret;
+}
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-sec-define.h b/drivers/media/platform/exynos/fimc-is/fimc-is-sec-define.h
new file mode 100644 (file)
index 0000000..a9a170c
--- /dev/null
@@ -0,0 +1,226 @@
+#ifndef FIMC_IS_SEC_DEFINE_H
+#define FIMC_IS_SEC_DEFINE_H
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+#include <linux/syscalls.h>
+#include <linux/vmalloc.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <linux/regulator/consumer.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-device-ischain.h"
+#include "crc32.h"
+#include "fimc-is-companion.h"
+
+#define FW_CORE_VER            0
+#define FW_PIXEL_SIZE          1
+#define FW_ISP_COMPANY         3
+#define FW_SENSOR_MAKER                4
+#define FW_PUB_YEAR            5
+#define FW_PUB_MON             6
+#define FW_PUB_NUM             7
+#define FW_MODULE_COMPANY      9
+#define FW_VERSION_INFO                10
+
+#define FW_ISP_COMPANY_BROADCOMM       'B'
+#define FW_ISP_COMPANY_TN              'C'
+#define FW_ISP_COMPANY_FUJITSU         'F'
+#define FW_ISP_COMPANY_INTEL           'I'
+#define FW_ISP_COMPANY_LSI             'L'
+#define FW_ISP_COMPANY_MARVELL         'M'
+#define FW_ISP_COMPANY_QUALCOMM                'Q'
+#define FW_ISP_COMPANY_RENESAS         'R'
+#define FW_ISP_COMPANY_STE             'S'
+#define FW_ISP_COMPANY_TI              'T'
+#define FW_ISP_COMPANY_DMC             'D'
+
+#define FW_SENSOR_MAKER_SF             'F'
+#define FW_SENSOR_MAKER_SLSI           'L'
+#define FW_SENSOR_MAKER_SONY           'S'
+
+#define FW_MODULE_COMPANY_SEMCO                'S'
+#define FW_MODULE_COMPANY_GUMI         'O'
+#define FW_MODULE_COMPANY_CAMSYS       'C'
+#define FW_MODULE_COMPANY_PATRON       'P'
+#define FW_MODULE_COMPANY_MCNEX                'M'
+#define FW_MODULE_COMPANY_LITEON       'L'
+#define FW_MODULE_COMPANY_VIETNAM      'V'
+#define FW_MODULE_COMPANY_SHARP                'J'
+#define FW_MODULE_COMPANY_NAMUGA       'N'
+#define FW_MODULE_COMPANY_POWER_LOGIX  'A'
+#define FW_MODULE_COMPANY_DI           'D'
+
+#define FW_2P2_F               "F16LL"
+#define FW_2P2_I               "I16LL"
+#define FW_3L2         "C13LL"
+#define FW_IMX135      "C13LS"
+#define FW_IMX134      "D08LS"
+#define FW_IMX240      "H16LS"
+#define FW_IMX240_Q    "H16US"
+#define FW_IMX240_Q_C1 "H16UL"
+#define FW_2P2_12M     "G16LL"
+#define FW_4H5         "F08LL"
+#define FW_2P3         "J16LL"
+
+#define SDCARD_FW
+#define FIMC_IS_SETFILE_SDCARD_PATH            "/data/media/0/"
+#define FIMC_IS_FW                             "fimc_is_fw2.bin"
+#define FIMC_IS_FW_2P2                         "fimc_is_fw2_2p2.bin"
+#define FIMC_IS_FW_2P2_12M                             "fimc_is_fw2_2p2_12m.bin"
+#define FIMC_IS_FW_2P3                         "fimc_is_fw2_2p3.bin"
+#define FIMC_IS_FW_3L2                         "fimc_is_fw2_3l2.bin"
+#define FIMC_IS_FW_4H5                         "fimc_is_fw2_4h5.bin"
+#define FIMC_IS_FW_IMX134                      "fimc_is_fw2_imx134.bin"
+#define FIMC_IS_FW_IMX240              "fimc_is_fw2_imx240.bin"
+#define FIMC_IS_FW_COMPANION_EVT0                              "companion_fw_evt0.bin"
+#define FIMC_IS_FW_COMPANION_EVT1                              "companion_fw_evt1.bin"
+#define FIMC_IS_FW_COMPANION_2P2_EVT1                          "companion_fw_2p2_evt1.bin"
+#define FIMC_IS_FW_COMPANION_2P2_12M_EVT1                              "companion_fw_2p2_12m_evt1.bin"
+#define FIMC_IS_FW_COMPANION_IMX240_EVT1                               "companion_fw_imx240_evt1.bin"
+#define FIMC_IS_FW_SDCARD                      "/data/media/0/fimc_is_fw2.bin"
+#define FIMC_IS_IMX240_SETF                    "setfile_imx240.bin"
+#define FIMC_IS_IMX135_SETF                    "setfile_imx135.bin"
+#define FIMC_IS_IMX134_SETF                    "setfile_imx134.bin"
+#define FIMC_IS_4H5_SETF                       "setfile_4h5.bin"
+#define FIMC_IS_3L2_SETF                       "setfile_3l2.bin"
+#define FIMC_IS_6B2_SETF                       "setfile_6b2.bin"
+#define FIMC_IS_8B1_SETF                       "setfile_8b1.bin"
+#define FIMC_IS_6D1_SETF                       "setfile_6d1.bin"
+#define FIMC_IS_2P2_SETF                       "setfile_2p2.bin"
+#define FIMC_IS_2P2_12M_SETF                   "setfile_2p2_12m.bin"
+#define FIMC_IS_2P3_SETF                       "setfile_2p3.bin"
+#define FIMC_IS_COMPANION_MASTER_SETF                  "companion_master_setfile.bin"
+#define FIMC_IS_COMPANION_MODE_SETF                    "companion_mode_setfile.bin"
+#define FIMC_IS_COMPANION_2P2_MASTER_SETF                      "companion_2p2_master_setfile.bin"
+#define FIMC_IS_COMPANION_2P2_MODE_SETF                        "companion_2p2_mode_setfile.bin"
+#define FIMC_IS_COMPANION_IMX240_MASTER_SETF                   "companion_imx240_master_setfile.bin"
+#define FIMC_IS_COMPANION_IMX240_MODE_SETF                     "companion_imx240_mode_setfile.bin"
+#define FIMC_IS_COMPANION_2P2_12M_MASTER_SETF                  "companion_2p2_12m_master_setfile.bin"
+#define FIMC_IS_COMPANION_2P2_12M_MODE_SETF                    "companion_2p2_12m_mode_setfile.bin"
+#define FIMC_IS_FW_PATH                                "/system/vendor/firmware/"
+#define FIMC_IS_FW_DUMP_PATH           "/data/"
+
+#define FIMC_IS_FW_BASE_MASK                   ((1 << 26) - 1)
+#define FIMC_IS_VERSION_SIZE                   42
+#define FIMC_IS_SETFILE_VER_OFFSET             0x40
+#define FIMC_IS_SETFILE_VER_SIZE               52
+
+#define FIMC_IS_CAL_SDCARD                     "/data/cal_data.bin"
+#define FIMC_IS_CAL_SDCARD_FRONT                       "/data/cal_data_front.bin"
+
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+#define FIMC_IS_MAX_FW_SIZE                    (8 * 1024)
+#define HEADER_CRC32_LEN                       (80 / 2)
+#define OEM_CRC32_LEN                          (64 / 2)
+#define AWB_CRC32_LEN                          (32 / 2)
+#define SHADING_CRC32_LEN                      (6623 / 2)
+#else
+/*#define FIMC_IS_MAX_CAL_SIZE                 (20 * 1024)*/
+#define FIMC_IS_MAX_FW_SIZE                    (2048 * 1024)
+#define HEADER_CRC32_LEN (224 / 2)
+#define OEM_CRC32_LEN (192 / 2)
+#define AWB_CRC32_LEN (32 / 2)
+#define SHADING_CRC32_LEN (2336 / 2)
+#endif
+
+#define FIMC_IS_MAX_COMPANION_FW_SIZE                  (120 * 1024)
+#define FIMC_IS_CAL_START_ADDR                 (0x013D0000)
+#define FIMC_IS_CAL_START_ADDR_FRONT                   (0x013E0000)
+
+#define FIMC_IS_CAL_RETRY_CNT                  (2)
+#define FIMC_IS_FW_RETRY_CNT                   (2)
+#define FROM_VERSION_V004 '4'
+#define FROM_VERSION_V005 '5'
+
+enum {
+        CC_BIN1 = 0,
+        CC_BIN2,
+        CC_BIN3,
+        CC_BIN4,
+        CC_BIN5,
+        CC_BIN6,
+        CC_BIN_MAX,
+};
+
+int fimc_is_sec_set_force_caldata_dump(bool fcd);
+
+ssize_t write_data_to_file(char *name, char *buf, size_t count, loff_t *pos);
+ssize_t read_data_from_file(char *name, char *buf, size_t count, loff_t *pos);
+
+int fimc_is_sec_get_sysfs_finfo(struct fimc_is_from_info **finfo);
+int fimc_is_sec_get_sysfs_pinfo(struct fimc_is_from_info **pinfo);
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+int fimc_is_sec_get_sysfs_finfo_front(struct fimc_is_from_info **finfo);
+int fimc_is_sec_get_sysfs_pinfo_front(struct fimc_is_from_info **pinfo);
+int fimc_is_sec_get_front_cal_buf(char **buf);
+#endif
+
+int fimc_is_sec_get_cal_buf(char **buf);
+int fimc_is_sec_get_loaded_fw(char **buf);
+int fimc_is_sec_get_loaded_c1_fw(char **buf);
+
+int fimc_is_sec_get_camid_from_hal(char *fw_name, char *setf_name);
+int fimc_is_sec_get_camid(void);
+int fimc_is_sec_set_camid(int id);
+int fimc_is_sec_get_pixel_size(char *header_ver);
+int fimc_is_sec_fw_find(struct fimc_is_core *core, char *fw_name, char *setf_name);
+
+int fimc_is_sec_readfw(struct fimc_is_core *core);
+#if defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR) || defined(CONFIG_CAMERA_EEPROM_SUPPORT_FRONT)
+int fimc_is_sec_fw_sel_eeprom(struct device *dev, char *fw_name, char *setf_name, int id, bool headerOnly);
+#endif
+#if !defined(CONFIG_CAMERA_EEPROM_SUPPORT_REAR)
+int fimc_is_sec_readcal(struct fimc_is_core *core);
+int fimc_is_sec_fw_sel(struct fimc_is_core *core, struct device *dev, char *fw_name, char *setf_name, bool headerOnly);
+#endif
+#ifdef CONFIG_COMPANION_USE
+int fimc_is_sec_concord_fw_sel(struct fimc_is_core *core, struct device *dev,
+       char *fw_name, char *master_setf_name, char *mode_setf_name);
+#endif
+int fimc_is_sec_fw_revision(char *fw_ver);
+int fimc_is_sec_fw_revision(char *fw_ver);
+bool fimc_is_sec_fw_module_compare(char *fw_ver1, char *fw_ver2);
+
+bool fimc_is_sec_check_fw_crc32(char *buf);
+bool fimc_is_sec_check_cal_crc32(char *buf, int id);
+void fimc_is_sec_make_crc32_table(u32 *table, u32 id);
+
+int fimc_is_sec_gpio_enable(struct exynos_platform_fimc_is *pdata, char *name, bool on);
+int fimc_is_sec_core_voltage_select(struct device *dev, char *header_ver);
+int fimc_is_sec_ldo_enable(struct device *dev, char *name, bool on);
+
+int fimc_is_spi_reset_by_core(struct spi_device *spi, void *buf, u32 rx_addr, size_t size);
+int fimc_is_spi_read_by_core(struct spi_device *spi, void *buf, u32 rx_addr, size_t size);
+#ifdef CONFIG_COMPANION_USE
+void fimc_is_set_spi_config(struct fimc_is_spi_gpio *spi_gpio, int func, bool ssn);
+#endif
+#endif /* FIMC_IS_SEC_DEFINE_H */
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-spi.c b/drivers/media/platform/exynos/fimc-is/fimc-is-spi.c
new file mode 100644 (file)
index 0000000..8151b31
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * driver for FIMC-IS SPI
+ *
+ * Copyright (c) 2011, Samsung Electronics. 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#include "fimc-is-core.h"
+#include "fimc-is-regs.h"
+
+#define STREAM_TO_U16(var16, p)        {(var16) = ((u16)(*((u8 *)p+1)) + \
+                               ((u8)(*((u8 *)p) << 8))); }
+
+#ifndef __devinit
+#define __devinit
+#endif
+
+#ifndef __devexit
+#define __devexit
+#endif
+
+#ifndef __devexit_p
+#define __devexit_p(x) x
+#endif
+
+static struct spi_device *g_spi;
+
+int fimc_is_spi_reset(void *buf, u32 rx_addr, size_t size)
+{
+       unsigned char req_rst[1] = { 0x99 };
+       int ret;
+
+       struct spi_transfer t_c;
+       struct spi_transfer t_r;
+
+       struct spi_message m;
+
+       memset(&t_c, 0x00, sizeof(t_c));
+       memset(&t_r, 0x00, sizeof(t_r));
+
+       t_c.tx_buf = req_rst;
+       t_c.len = 1;
+       t_c.cs_change = 0;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t_c, &m);
+
+       ret = spi_sync(g_spi, &m);
+       if (ret) {
+               err("spi sync error - can't get device information");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int fimc_is_spi_read(void *buf, u32 rx_addr, size_t size)
+{
+       unsigned char req_data[4] = { 0x03,  };
+       int ret;
+
+       struct spi_transfer t_c;
+       struct spi_transfer t_r;
+
+       struct spi_message m;
+
+       memset(&t_c, 0x00, sizeof(t_c));
+       memset(&t_r, 0x00, sizeof(t_r));
+
+       req_data[1] = (rx_addr & 0xFF0000) >> 16;
+       req_data[2] = (rx_addr & 0xFF00) >> 8;
+       req_data[3] = (rx_addr & 0xFF);
+
+       t_c.tx_buf = req_data;
+       t_c.len = 4;
+       t_c.cs_change = 1;
+       t_c.bits_per_word = 32;
+
+       t_r.rx_buf = buf;
+       t_r.len = size;
+       t_r.cs_change = 0;
+       t_r.bits_per_word = 32;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t_c, &m);
+       spi_message_add_tail(&t_r, &m);
+
+       ret = spi_sync(g_spi, &m);
+       if (ret) {
+               err("spi sync error - can't read data");
+               return -EIO;
+       } else
+               return 0;
+}
+
+int fimc_is_spi_reset_by_core(struct spi_device *spi, void *buf, u32 rx_addr, size_t size)
+{
+       unsigned char req_rst[1] = { 0x99 };
+       int ret;
+
+       struct spi_transfer t_c;
+       struct spi_transfer t_r;
+
+       struct spi_message m;
+
+       memset(&t_c, 0x00, sizeof(t_c));
+       memset(&t_r, 0x00, sizeof(t_r));
+
+       t_c.tx_buf = req_rst;
+       t_c.len = 1;
+       t_c.cs_change = 0;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t_c, &m);
+
+       ret = spi_sync(spi, &m);
+       if (ret) {
+               err("spi sync error - can't get device information");
+               return -EIO;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(fimc_is_spi_reset_by_core);
+
+int fimc_is_spi_read_by_core(struct spi_device *spi, void *buf, u32 rx_addr, size_t size)
+{
+       unsigned char req_data[4] = { 0x03,  };
+       int ret;
+
+       struct spi_transfer t_c;
+       struct spi_transfer t_r;
+
+       struct spi_message m;
+
+       memset(&t_c, 0x00, sizeof(t_c));
+       memset(&t_r, 0x00, sizeof(t_r));
+
+       req_data[1] = (rx_addr & 0xFF0000) >> 16;
+       req_data[2] = (rx_addr & 0xFF00) >> 8;
+       req_data[3] = (rx_addr & 0xFF);
+
+       t_c.tx_buf = req_data;
+       t_c.len = 4;
+       t_c.cs_change = 1;
+       t_c.bits_per_word = 32;
+
+       t_r.rx_buf = buf;
+       t_r.len = size;
+       t_r.cs_change = 0;
+       t_r.bits_per_word = 32;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t_c, &m);
+       spi_message_add_tail(&t_r, &m);
+
+       spi->max_speed_hz = 48000000;
+       ret = spi_sync(spi, &m);
+       if (ret) {
+               err("spi sync error - can't read data");
+               return -EIO;
+       } else {
+               return 0;
+       }
+}
+EXPORT_SYMBOL(fimc_is_spi_read_by_core);
+
+int fimc_is_spi_read_module_id(struct spi_device *spi, void *buf, u16 rx_addr, size_t size)
+{
+       unsigned char req_data[4] = { 0x90,  };
+       int ret;
+
+       struct spi_transfer t_c;
+       struct spi_transfer t_r;
+
+       struct spi_message m;
+
+       memset(&t_c, 0x00, sizeof(t_c));
+       memset(&t_r, 0x00, sizeof(t_r));
+
+       req_data[1] = (rx_addr & 0xFF00) >> 8;
+       req_data[2] = (rx_addr & 0xFF);
+
+       t_c.tx_buf = req_data;
+       t_c.len = 4;
+       t_c.cs_change = 1;
+       t_c.bits_per_word = 32;
+
+       t_r.rx_buf = buf;
+       t_r.len = size;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t_c, &m);
+       spi_message_add_tail(&t_r, &m);
+
+       spi->max_speed_hz = 48000000;
+       ret = spi_sync(spi, &m);
+       if (ret) {
+               err("spi sync error - can't read data");
+               return -EIO;
+       } else {
+               return 0;
+       }
+}
+EXPORT_SYMBOL(fimc_is_spi_read_module_id);
+
+
+static int __devinit fimc_is_spi_probe(struct spi_device *spi)
+{
+       int ret = 0;
+
+       dbg_core("%s\n", __func__);
+
+       /* spi->bits_per_word = 16; */
+       if (spi_setup(spi)) {
+               pr_err("failed to setup spi for fimc_is_spi\n");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       g_spi = spi;
+
+exit:
+       return ret;
+}
+
+static int __devexit fimc_is_spi_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+static struct spi_driver fimc_is_spi_driver = {
+       .driver = {
+               .name = "fimc_is_spi",
+               .bus = &spi_bus_type,
+               .owner = THIS_MODULE,
+       },
+       .probe = fimc_is_spi_probe,
+       .remove = __devexit_p(fimc_is_spi_remove),
+};
+
+static int __init fimc_is_spi_init(void)
+{
+       int ret;
+
+       ret = spi_register_driver(&fimc_is_spi_driver);
+
+       if (ret)
+               pr_err("failed to register imc_is_spi- %x\n", ret);
+
+       return ret;
+}
+
+static void __exit fimc_is_spi_exit(void)
+{
+       spi_unregister_driver(&fimc_is_spi_driver);
+}
+
+module_init(fimc_is_spi_init);
+module_exit(fimc_is_spi_exit);
+
+MODULE_DESCRIPTION("FIMC-IS SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-subdev-ctrl.c b/drivers/media/platform/exynos/fimc-is/fimc-is-subdev-ctrl.c
new file mode 100644 (file)
index 0000000..8f0d966
--- /dev/null
@@ -0,0 +1,395 @@
+#include <linux/module.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+
+int fimc_is_subdev_open(struct fimc_is_subdev *subdev,
+       struct fimc_is_video_ctx *vctx,
+       const struct param_control *init_ctl)
+{
+       int ret = 0;
+
+       if (test_bit(FIMC_IS_SUBDEV_OPEN, &subdev->state)) {
+               warn("subdev%d already open", subdev->entry);
+               goto p_err;
+       }
+
+       mutex_init(&subdev->mutex_state);
+       subdev->vctx = vctx;
+       subdev->input.width = 0;
+       subdev->input.height = 0;
+       subdev->output.width = 0;
+       subdev->output.height = 0;
+
+       if (init_ctl) {
+               if (init_ctl->cmd != CONTROL_COMMAND_START) {
+                       if ((subdev->entry == ENTRY_DIS) ||
+                                       (subdev->entry == ENTRY_TDNR)) {
+#if defined(ENABLE_VDIS) || defined(ENABLE_TDNR)
+                               err("%d entry is not start", subdev->entry);
+#endif
+                       } else {
+                               err("%d entry is not start", subdev->entry);
+                       }
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (init_ctl->bypass == CONTROL_BYPASS_ENABLE)
+                       clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+               else if (init_ctl->bypass == CONTROL_BYPASS_DISABLE)
+                       set_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+               else {
+                       err("%d entry has invalid bypass value(%d)",
+                               subdev->entry, init_ctl->bypass);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+       } else {
+               /* isp, scc, scp do not use bypass(memory interface)*/
+               clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+       }
+
+       set_bit(FIMC_IS_SUBDEV_OPEN, &subdev->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_subdev_close(struct fimc_is_subdev *subdev)
+{
+       clear_bit(FIMC_IS_SUBDEV_OPEN, &subdev->state);
+
+       return 0;
+}
+
+int fimc_is_subdev_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue)
+{
+       return 0;
+}
+
+int fimc_is_subdev_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!queue);
+
+       framemgr = &queue->framemgr;
+
+/*
+       if (!test_bit(FIMC_IS_SUBDEV_START, &subdev->state)) {
+               mwarn("already stop", device);
+               goto p_err;
+       }
+*/
+
+       framemgr_e_barrier_irqs(framemgr, FMGR_IDX_4, flags);
+
+       if (framemgr->frame_pro_cnt > 0) {
+               framemgr_x_barrier_irqr(framemgr, FMGR_IDX_4, flags);
+               merr("being processed, can't stop", device);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_frame_complete_head(framemgr, &frame);
+       while (frame) {
+               fimc_is_frame_trans_com_to_fre(framemgr, frame);
+               fimc_is_frame_complete_head(framemgr, &frame);
+       }
+
+       fimc_is_frame_request_head(framemgr, &frame);
+       while (frame) {
+               fimc_is_frame_trans_req_to_fre(framemgr, frame);
+               fimc_is_frame_request_head(framemgr, &frame);
+       }
+
+       framemgr_x_barrier_irqr(framemgr, FMGR_IDX_4, flags);
+
+       clear_bit(FIMC_IS_SUBDEV_START, &subdev->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_subdev_s_format(struct fimc_is_subdev *subdev,
+       u32 width, u32 height)
+{
+       int ret = 0;
+
+       BUG_ON(!subdev);
+
+       subdev->output.width = width;
+       subdev->output.height = height;
+
+       return ret;
+}
+
+int fimc_is_subdev_buffer_queue(struct fimc_is_subdev *subdev,
+       u32 index)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!subdev);
+       BUG_ON(!subdev->vctx);
+       BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
+
+       vctx = subdev->vctx;
+       framemgr = GET_DST_FRAMEMGR(vctx);
+
+       /* 1. check frame validation */
+       frame = &framemgr->frame[index];
+       if (!frame) {
+               merr("frame is null\n", vctx);
+               ret = EINVAL;
+               goto p_err;
+       }
+
+       if (unlikely(!test_bit(FRAME_INI_MEM, &frame->memory))) {
+               err("frame %d is NOT init", index);
+               ret = EINVAL;
+               goto p_err;
+       }
+
+       /* 2. update frame manager */
+       framemgr_e_barrier_irqs(framemgr, index, flags);
+
+       if (frame->state == FIMC_IS_FRAME_STATE_FREE) {
+               if (frame->req_flag) {
+                       warn("%d request flag is not clear(%08X)\n",
+                               frame->index, (u32)frame->req_flag);
+                       frame->req_flag = 0;
+               }
+
+               fimc_is_frame_trans_fre_to_req(framemgr, frame);
+       } else {
+               merr("frame(%d) is invalid state(%d)\n", vctx, index, frame->state);
+               fimc_is_frame_print_all(framemgr);
+               ret = -EINVAL;
+       }
+
+       framemgr_x_barrier_irqr(framemgr, index, flags);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_subdev_buffer_finish(struct fimc_is_subdev *subdev,
+       u32 index)
+{
+       int ret = 0;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!subdev);
+       BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
+
+       framemgr = GET_SUBDEV_FRAMEMGR(subdev);
+       if (!framemgr) {
+               err("framemgr is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr_e_barrier_irq(framemgr, index);
+
+       fimc_is_frame_complete_head(framemgr, &frame);
+       if (frame) {
+               if (frame->index == index) {
+                       fimc_is_frame_trans_com_to_fre(framemgr, frame);
+               } else {
+                       err("buffer index is NOT matched(%d != %d)\n",
+                               index, frame->index);
+                       fimc_is_frame_print_all(framemgr);
+                       ret = -EINVAL;
+               }
+       } else {
+               err("frame is empty from complete");
+               fimc_is_frame_print_all(framemgr);
+               ret = -EINVAL;
+       }
+
+       framemgr_x_barrier_irq(framemgr, index);
+
+p_err:
+       return ret;
+}
+
+const struct fimc_is_queue_ops fimc_is_ischain_sub_ops = {
+       .start_streaming        = fimc_is_subdev_start,
+       .stop_streaming         = fimc_is_subdev_stop
+};
+
+void fimc_is_subdev_dis_start(struct fimc_is_device_ischain *device,
+       struct dis_param *param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+#ifdef ENABLE_VDIS
+       param->control.cmd = CONTROL_COMMAND_START;
+       param->control.bypass = CONTROL_BYPASS_DISABLE;
+       param->control.buffer_number = SIZE_DIS_INTERNAL_BUF * NUM_DIS_INTERNAL_BUF;
+       param->control.buffer_address = device->imemory.dvaddr_shared + 300 * sizeof(u32);
+       device->is_region->shared[300] = device->imemory.dvaddr_dis;
+#else
+       merr("can't start hw vdis", device);
+       BUG();
+#endif
+
+       *lindex |= LOWBIT_OF(PARAM_DIS_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_DIS_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_dis_stop(struct fimc_is_device_ischain *device,
+       struct dis_param *param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       param->control.cmd = CONTROL_COMMAND_STOP;
+       param->control.bypass = CONTROL_BYPASS_DISABLE;
+
+       *lindex |= LOWBIT_OF(PARAM_DIS_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_DIS_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_dis_bypass(struct fimc_is_device_ischain *device,
+       struct dis_param *param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       if (device->pdata->subip_info->_dis.full_bypass)
+               param->control.cmd = CONTROL_COMMAND_STOP;
+       else
+               param->control.cmd = CONTROL_COMMAND_START;
+       /*
+        * special option
+        * bypass command should be 2 for enabling software dis
+        * software dis is not active because output format of software
+        * can't support multi-plane.
+        */
+       param->control.bypass = CONTROL_BYPASS_ENABLE;
+
+       *lindex |= LOWBIT_OF(PARAM_DIS_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_DIS_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_dnr_start(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!ctl_param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       ctl_param->cmd = CONTROL_COMMAND_START;
+       ctl_param->bypass = CONTROL_BYPASS_DISABLE;
+       ctl_param->buffer_number = SIZE_DNR_INTERNAL_BUF * NUM_DNR_INTERNAL_BUF;
+       ctl_param->buffer_address = device->imemory.dvaddr_shared + 350 * sizeof(u32);
+       device->is_region->shared[350] = device->imemory.dvaddr_3dnr;
+
+       *lindex |= LOWBIT_OF(PARAM_TDNR_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_TDNR_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_dnr_stop(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!ctl_param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       ctl_param->cmd = CONTROL_COMMAND_STOP;
+       ctl_param->bypass = CONTROL_BYPASS_DISABLE;
+
+       *lindex |= LOWBIT_OF(PARAM_TDNR_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_TDNR_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_dnr_bypass(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!ctl_param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       if (device->pdata->subip_info->_dnr.full_bypass)
+               ctl_param->cmd = CONTROL_COMMAND_STOP;
+       else
+               ctl_param->cmd = CONTROL_COMMAND_START;
+
+       ctl_param->bypass = CONTROL_BYPASS_ENABLE;
+
+       *lindex |= LOWBIT_OF(PARAM_TDNR_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_TDNR_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_drc_start(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!ctl_param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       ctl_param->cmd = CONTROL_COMMAND_START;
+       ctl_param->bypass = CONTROL_BYPASS_DISABLE;
+       *lindex |= LOWBIT_OF(PARAM_DRC_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_DRC_CONTROL);
+       (*indexes)++;
+}
+
+void fimc_is_subdev_drc_bypass(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes)
+{
+       BUG_ON(!device);
+       BUG_ON(!ctl_param);
+       BUG_ON(!lindex);
+       BUG_ON(!hindex);
+       BUG_ON(!indexes);
+
+       if (device->pdata->subip_info->_drc.full_bypass)
+               ctl_param->cmd = CONTROL_COMMAND_STOP;
+       else
+               ctl_param->cmd = CONTROL_COMMAND_START;
+
+       ctl_param->bypass = CONTROL_BYPASS_ENABLE;
+
+       *lindex |= LOWBIT_OF(PARAM_DRC_CONTROL);
+       *hindex |= HIGHBIT_OF(PARAM_DRC_CONTROL);
+       (*indexes)++;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-subdev-ctrl.h b/drivers/media/platform/exynos/fimc-is/fimc-is-subdev-ctrl.h
new file mode 100644 (file)
index 0000000..94fc7c8
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_SUBDEV_H
+#define FIMC_IS_SUBDEV_H
+
+#include "fimc-is-param.h"
+#include "fimc-is-video.h"
+
+struct fimc_is_group;
+struct fimc_is_device_ischain;
+
+enum fimc_is_subdev_state {
+       FIMC_IS_SUBDEV_OPEN,
+       FIMC_IS_SUBDEV_START
+};
+
+struct fimc_is_subdev_path {
+       u32                                     width;
+       u32                                     height;
+};
+
+struct fimc_is_subdev {
+       u32                                     id;
+       u32                                     entry;
+       unsigned long                           state;
+       struct mutex                            mutex_state;
+
+       struct fimc_is_subdev_path              input;
+       struct fimc_is_subdev_path              output;
+
+       struct fimc_is_group                    *group;
+       struct fimc_is_video_ctx                *vctx;
+       struct fimc_is_subdev                   *leader;
+};
+
+#define GET_LEADER_FRAMEMGR(leader) \
+       (((leader) && (leader)->vctx) ? (&(leader)->vctx->q_src->framemgr) : NULL)
+#define GET_SUBDEV_FRAMEMGR(subdev) \
+       (((subdev) && (subdev)->vctx) ? (&(subdev)->vctx->q_dst->framemgr) : NULL)
+
+#define GET_LEADER_QUEUE(leader) \
+       (((leader) && (leader)->vctx) ? ((leader)->vctx->q_src) : NULL)
+#define GET_SUBDEV_QUEUE(subdev) \
+       (((subdev) && (subdev)->vctx) ? ((subdev)->vctx->q_dst) : NULL)
+
+/*common subdev*/
+int fimc_is_subdev_open(struct fimc_is_subdev *subdev,
+       struct fimc_is_video_ctx *vctx,
+       const struct param_control *init_ctl);
+int fimc_is_subdev_close(struct fimc_is_subdev *subdev);
+int fimc_is_subdev_start(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue);
+int fimc_is_subdev_stop(struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_queue *queue);
+int fimc_is_subdev_s_format(struct fimc_is_subdev *subdev,
+       u32 width, u32 height);
+int fimc_is_subdev_buffer_queue(struct fimc_is_subdev *subdev,
+       u32 index);
+int fimc_is_subdev_buffer_finish(struct fimc_is_subdev *subdev,
+       u32 index);
+
+void fimc_is_subdev_dis_start(struct fimc_is_device_ischain *device,
+       struct dis_param *param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_dis_stop(struct fimc_is_device_ischain *device,
+       struct dis_param *param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_dis_bypass(struct fimc_is_device_ischain *device,
+       struct dis_param *param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_dnr_start(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_dnr_stop(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_dnr_bypass(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_drc_start(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes);
+void fimc_is_subdev_drc_bypass(struct fimc_is_device_ischain *device,
+       struct param_control *ctl_param, u32 *lindex, u32 *hindex, u32 *indexes);
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-time.c b/drivers/media/platform/exynos/fimc-is/fimc-is-time.c
new file mode 100644 (file)
index 0000000..f60adf8
--- /dev/null
@@ -0,0 +1,180 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+
+#include "fimc-is-time.h"
+
+static struct timeval itime1;
+
+void TIME_STR1(void)
+{
+       do_gettimeofday(&itime1);
+}
+
+void TIME_END1(void)
+{
+       u32 time;
+       struct timeval temp;
+
+       do_gettimeofday(&temp);
+       time = (temp.tv_sec - itime1.tv_sec)*1000000 +
+               (temp.tv_usec - itime1.tv_usec);
+
+       pr_info("TIME_MEASURE : %dus\n", time);
+}
+
+uint64_t fimc_is_get_timestamp(void)
+{
+       struct timespec curtime;
+
+       do_posix_clock_monotonic_gettime(&curtime);
+
+       return (uint64_t)curtime.tv_sec*1000000000 + curtime.tv_nsec;
+}
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+
+void measure_init(struct fimc_is_time *time,
+       u32 instance,
+       u32 group_id,
+       u32 report_period)
+{
+       time->instance = instance;
+       time->group_id = group_id;
+       time->report_period = report_period;
+       time->time_count = 0;
+       time->time1_min = 0;
+       time->time1_max = 0;
+       time->time1_tot = 0;
+       time->time2_min = 0;
+       time->time2_max = 0;
+       time->time2_tot = 0;
+       time->time3_min = 0;
+       time->time3_max = 0;
+       time->time3_tot = 0;
+       time->time4_cur = 0;
+       time->time4_old = 0;
+       time->time4_tot = 0;
+}
+
+void measure_period(struct fimc_is_time *time,
+       u32 report_period)
+{
+       time->report_period = report_period;
+}
+
+void measure_time(
+       struct fimc_is_time *time,
+       struct timeval *time_queued,
+       struct timeval *time_shot,
+       struct timeval *time_shotdone,
+       struct timeval *time_dequeued)
+{
+       u32 temp1, temp2, temp3;
+
+       temp1 = (time_shot->tv_sec - time_queued->tv_sec)*1000000 +
+               (time_shot->tv_usec - time_queued->tv_usec);
+       temp2 = (time_shotdone->tv_sec - time_shot->tv_sec)*1000000 +
+               (time_shotdone->tv_usec - time_shot->tv_usec);
+       temp3 = (time_dequeued->tv_sec - time_shotdone->tv_sec)*1000000 +
+               (time_dequeued->tv_usec - time_shotdone->tv_usec);
+
+       if (!time->time_count) {
+               time->time1_min = temp1;
+               time->time1_max = temp1;
+               time->time2_min = temp2;
+               time->time2_max = temp2;
+               time->time3_min = temp3;
+               time->time3_max = temp3;
+       } else {
+               if (time->time1_min > temp1)
+                       time->time1_min = temp1;
+
+               if (time->time1_max < temp1)
+                       time->time1_max = temp1;
+
+               if (time->time2_min > temp2)
+                       time->time2_min = temp2;
+
+               if (time->time2_max < temp2)
+                       time->time2_max = temp2;
+
+               if (time->time3_min > temp3)
+                       time->time3_min = temp3;
+
+               if (time->time3_max < temp3)
+                       time->time3_max = temp3;
+       }
+
+       time->time1_tot += temp1;
+       time->time2_tot += temp2;
+       time->time3_tot += temp3;
+
+       time->time4_cur = time_queued->tv_sec*1000000 + time_queued->tv_usec;
+       time->time4_tot += (time->time4_cur - time->time4_old);
+       time->time4_old = time->time4_cur;
+
+       time->time_count++;
+
+       if (time->time_count % time->report_period)
+               return;
+
+       pr_info("I%dG%d t1(%05d,%05d,%05d), t2(%05d,%05d,%05d), t3(%05d,%05d,%05d) : %d(%dfps)",
+               time->instance, time->group_id,
+               temp1, time->time1_max, time->time1_tot / time->time_count,
+               temp2, time->time2_max, time->time2_tot / time->time_count,
+               temp3, time->time3_max, time->time3_tot / time->time_count,
+               time->time4_tot / time->report_period,
+               (1000000 * time->report_period) / time->time4_tot);
+
+       time->time_count = 0;
+       time->time1_tot = 0;
+       time->time2_tot = 0;
+       time->time3_tot = 0;
+       time->time4_tot = 0;
+}
+
+#endif
+
+#ifdef INTERFACE_TIME
+void measure_init(struct fimc_is_interface_time *time, u32 cmd)
+{
+       time->cmd = cmd;
+       time->time_max = 0;
+       time->time_min = 0;
+       time->time_tot = 0;
+       time->time_cnt = 0;
+}
+
+void measure_time(struct fimc_is_interface_time *time,
+       u32 instance,
+       u32 group,
+       struct timeval *start,
+       struct timeval *end)
+{
+       u32 temp;
+
+       temp = (end->tv_sec - start->tv_sec)*1000000 + (end->tv_usec - start->tv_usec);
+
+       if (time->time_cnt) {
+               time->time_max = temp;
+               time->time_min = temp;
+       } else {
+               if (time->time_min > temp)
+                       time->time_min = temp;
+
+               if (time->time_max < temp)
+                       time->time_max = temp;
+       }
+
+       time->time_tot += temp;
+       time->time_cnt++;
+
+       pr_info("cmd[%d][%d](%d) : curr(%d), max(%d), avg(%d)\n",
+               instance, group, time->cmd, temp, time->time_max, time->time_tot / time->time_cnt);
+}
+#endif
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-time.h b/drivers/media/platform/exynos/fimc-is/fimc-is-time.h
new file mode 100644 (file)
index 0000000..70c14a9
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_TIME_H
+#define FIMC_IS_TIME_H
+
+/* #define MEASURE_TIME */
+/* #define INTERNAL_TIME */
+/* #define EXTERNAL_TIME */
+/* #define INTERFACE_TIME */
+
+#define INSTANCE_MASK   0x3
+
+#define TM_FLITE_STR   0
+#define TM_FLITE_END   1
+#define TM_SHOT                2
+#define TM_SHOT_D      3
+#define TM_META_D      4
+#define TM_MAX_INDEX   5
+
+struct fimc_is_time {
+       u32 instance;
+       u32 group_id;
+       u32 report_period;
+       u32 time_count;
+       u32 time1_min;
+       u32 time1_max;
+       u32 time1_tot;
+       u32 time2_min;
+       u32 time2_max;
+       u32 time2_tot;
+       u32 time3_min;
+       u32 time3_max;
+       u32 time3_tot;
+       u32 time4_cur;
+       u32 time4_old;
+       u32 time4_tot;
+};
+
+void TIME_STR1(void);
+void TIME_END1(void);
+uint64_t fimc_is_get_timestamp(void);
+
+#ifdef MEASURE_TIME
+#ifdef INTERNAL_TIME
+void measure_init(struct fimc_is_time *time,
+       u32 instance,
+       u32 group_id,
+       u32 report_period);
+void measure_period(struct fimc_is_time *time,
+       u32 report_period);
+void measure_time(
+       struct fimc_is_time *time,
+       struct timeval *time_queued,
+       struct timeval *time_shot,
+       struct timeval *time_shotdone,
+       struct timeval *time_dequeued);
+#endif
+#ifdef INTERFACE_TIME
+struct fimc_is_interface_time {
+       u32                             cmd;
+       u32                             time_tot;
+       u32                             time_min;
+       u32                             time_max;
+       u32                             time_cnt;
+};
+
+void measure_init(struct fimc_is_interface_time *time, u32 cmd);
+void measure_time(struct fimc_is_interface_time *time,
+       u32 instance,
+       u32 group,
+       struct timeval *start,
+       struct timeval *end);
+#endif
+#endif
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-type.h b/drivers/media/platform/exynos/fimc-is/fimc-is-type.h
new file mode 100644 (file)
index 0000000..2f70fa8
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef FIMC_IS_TYPE_H
+#define FIMC_IS_TYPE_H
+
+#include <linux/v4l2-mediabus.h>
+
+#include <media/v4l2-device.h>
+
+enum fimc_is_device_type {
+       FIMC_IS_DEVICE_SENSOR,
+       FIMC_IS_DEVICE_ISCHAIN
+};
+
+struct fimc_is_window {
+       u32 o_width;
+       u32 o_height;
+       u32 width;
+       u32 height;
+       u32 offs_h;
+       u32 offs_v;
+       u32 otf_width;
+       u32 otf_height;
+};
+
+struct fimc_is_fmt {
+       char                            *name;
+       enum v4l2_mbus_pixelcode        mbus_code;
+       u32                             pixelformat;
+       u32                             field;
+       u32                             num_planes;
+};
+
+struct fimc_is_image {
+       u32                     framerate;
+       struct fimc_is_window   window;
+       struct fimc_is_fmt      format;
+};
+
+#define TO_WORD_OFFSET(byte_offset) ((byte_offset) >> 2)
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-3aa.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-3aa.c
new file mode 100644 (file)
index 0000000..6dc3d08
--- /dev/null
@@ -0,0 +1,960 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-mediabus.h>
+#include <media/exynos_mc.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-metadata.h"
+
+const struct v4l2_file_operations fimc_is_3aa_video_fops;
+const struct v4l2_ioctl_ops fimc_is_3aa_video_ioctl_ops;
+const struct vb2_ops fimc_is_3aa_qops;
+
+int fimc_is_3a0_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_3a0;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_3AA_NAME(0),
+               FIMC_IS_VIDEO_3A0_NUM,
+               VFL_DIR_M2M,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_3aa_video_fops,
+               &fimc_is_3aa_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_3a1_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_3a1;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_3AA_NAME(1),
+               FIMC_IS_VIDEO_3A1_NUM,
+               VFL_DIR_M2M,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_3aa_video_fops,
+               &fimc_is_3aa_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_3aa_video_open(struct file *file)
+{
+       int ret = 0;
+       u32 refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+
+       if (video->id == FIMC_IS_VIDEO_3A0_NUM)
+               core = container_of(video, struct fimc_is_core, video_3a0);
+       else
+               core = container_of(video, struct fimc_is_core, video_3a1);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_3AA_GRP, FRAMEMGR_ID_3AAP);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[3A%d:V:%d] %s\n", GET_3AA_ID(video), vctx->instance, __func__);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount > FIMC_IS_MAX_NODES || refcount < 1) {
+               err("invalid ischain refcount(%d)", refcount);
+               close_vctx(file, video, vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = &core->ischain[refcount - 1];
+       info("[3A%d:V:%d] <-> [ISP:V:%d] \n", GET_3AA_ID(video),
+               vctx->instance, device->instance);
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_3AA_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_M2M,
+               &fimc_is_3aa_qops,
+               &fimc_is_ischain_3aa_ops,
+               &fimc_is_ischain_sub_ops);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_3aa_open(device, vctx);
+       if (ret) {
+               err("fimc_is_ischain_3aa_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aa_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_device_ischain *device = NULL;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               err("video is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[3A%d:V:%d] %s\n", GET_3AA_ID(video), vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_ischain_3aa_close(device, vctx);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_3aa_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+       if (ret)
+               merr("fimc_is_video_poll is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_3aa_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_3aa_video_open,
+       .release        = fimc_is_3aa_video_close,
+       .poll           = fimc_is_3aa_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_3aa_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_3aa_video_querycap(struct file *file, void *fh,
+       struct v4l2_capability *cap)
+{
+       /* Todo : add to query capability code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       /* Todo : add to enumerate format code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       /* Todo : add to get format code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       device = vctx->device;
+       leader = &device->group_3aa.leader;
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret) {
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       if (V4L2_TYPE_IS_OUTPUT(format->type)) {
+               queue = vctx->q_src;
+               fimc_is_ischain_3aa_s_format(device,
+                       queue->framecfg.width,
+                       queue->framecfg.height);
+       } else {
+               queue = vctx->q_dst;
+               fimc_is_subdev_s_format(leader,
+                       queue->framecfg.width,
+                       queue->framecfg.height);
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aa_video_cropcap(struct file *file, void *fh,
+       struct v4l2_cropcap *cropcap)
+{
+       /* Todo : add to crop capability code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_get_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       /* Todo : add to get crop control code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_set_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *ischain;
+       struct fimc_is_group *group;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       ischain = vctx->device;
+       BUG_ON(!ischain);
+       group = &ischain->group_3aa;
+       BUG_ON(!group);
+       subdev = &group->leader;
+
+       if (V4L2_TYPE_IS_OUTPUT(crop->type))
+               fimc_is_ischain_3aa_s_format(ischain,
+                       crop->c.width, crop->c.height);
+       else
+               fimc_is_subdev_s_format(subdev,
+                       crop->c.width, crop->c.height);
+
+       return 0;
+}
+
+static int fimc_is_3aa_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_3aa("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
+               ret = fimc_is_ischain_3aa_reqbufs(device, buf->count);
+               if (ret) {
+                       merr("3a0_reqbufs is fail(%d)", vctx, ret);
+                       goto p_err;
+               }
+       }
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aa_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+
+#ifdef DBG_STREAMING
+       mdbgv_3aa("%s(%02d:%d)\n", vctx, __func__, buf->type, buf->index);
+#endif
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf(type %d) is fail(%d)", vctx, buf->type, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+
+#ifdef DBG_STREAMING
+       mdbgv_3aa("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       /* HACK : this log is commented until timeout issue fixed */
+       /* if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+       */
+       return ret;
+}
+
+static int fimc_is_3aa_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo: add enum input control code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       /* Todo: add to get input control code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_3aa("%s(input : %08X)\n", vctx, __func__, input);
+
+       device = vctx->device;
+
+       ret = fimc_is_ischain_3aa_s_input(device, input);
+       if (ret) {
+               merr("fimc_is_ischain_3aa_s_input is fail", vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_init_wrap(device, input);
+       if (ret) {
+               merr("fimc_is_device_init(%d) is fail", vctx, input);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aa_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+
+       dbg_isp("%s\n", __func__);
+
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_INTENT:
+               device->group_3aa.intent_ctl.aa.captureIntent = ctrl->value;
+               minfo("[3AA:V] s_ctrl intent(%d)\n", vctx, ctrl->value);
+               break;
+       case V4L2_CID_IS_FORCE_DONE:
+               set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_3aa.state);
+               break;
+       case V4L2_CID_IS_MAP_BUFFER:
+               {
+                       struct fimc_is_queue *queue;
+                       struct fimc_is_framemgr *framemgr;
+                       struct fimc_is_frame *frame;
+                       struct dma_buf *dmabuf;
+                       struct dma_buf_attachment *attachment;
+                       dma_addr_t dva;
+                       struct v4l2_buffer *buf = NULL;
+                       struct v4l2_plane *planes;
+                       size_t size;
+                       u32 write, plane, group_id;
+
+                       size = sizeof(struct v4l2_buffer);
+                       buf = kmalloc(size, GFP_KERNEL);
+                       if (!buf) {
+                               merr("kmalloc is fail", vctx);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       ret = copy_from_user(buf, (void __user *)ctrl->value, size);
+                       if (ret) {
+                               merr("copy_from_user is fail(%d)", vctx, ret);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       if (!V4L2_TYPE_IS_MULTIPLANAR(buf->type)) {
+                               merr("single plane is not supported", vctx);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       if (buf->index >= FRAMEMGR_MAX_REQUEST) {
+                               merr("buffer index is invalid(%d)", vctx, buf->index);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       if (buf->length > VIDEO_MAX_PLANES) {
+                               merr("planes[%d] is invalid", vctx, buf->length);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       queue = GET_QUEUE(vctx, buf->type);
+                       if (queue->vbq->memory != V4L2_MEMORY_DMABUF) {
+                               merr("memory type(%d) is not supported", vctx, queue->vbq->memory);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       size = sizeof(struct v4l2_plane) * buf->length;
+                       planes = kmalloc(size, GFP_KERNEL);
+                       if (IS_ERR(planes)) {
+                               merr("kmalloc is fail(%p)", vctx, planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       ret = copy_from_user(planes, (void __user *)buf->m.planes, size);
+                       if (ret) {
+                               merr("copy_from_user is fail(%d)", vctx, ret);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       framemgr = &queue->framemgr;
+                       frame = &framemgr->frame[buf->index];
+                       if (test_bit(FRAME_MAP_MEM, &frame->memory)) {
+                               merr("this buffer(%d) is already mapped", vctx, buf->index);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       /* only last buffer need to map */
+                       if (buf->length > 0) {
+                               plane = buf->length - 1;
+                       } else {
+                               merr("buf size is abnormal(%d)", vctx, buf->length);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+                       dmabuf = dma_buf_get(planes[plane].m.fd);
+                       if (IS_ERR(dmabuf)) {
+                               merr("dma_buf_get is fail(%p)", vctx, dmabuf);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       attachment = dma_buf_attach(dmabuf, &device->pdev->dev);
+                       if (IS_ERR(attachment)) {
+                               merr("dma_buf_attach is fail(%p)", vctx, attachment);
+                               kfree(planes);
+                               kfree(buf);
+                               dma_buf_put(dmabuf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       write = !V4L2_TYPE_IS_OUTPUT(buf->type);
+                       dva = ion_iovmm_map(attachment, 0, dmabuf->size, write, plane);
+                       if (IS_ERR_VALUE(dva)) {
+                               merr("ion_iovmm_map is fail(%X)", vctx, dva);
+                               kfree(planes);
+                               kfree(buf);
+                               dma_buf_detach(dmabuf, attachment);
+                               dma_buf_put(dmabuf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       group_id = GROUP_ID(device->group_3aa.id);
+                       ret = fimc_is_itf_map(device, group_id, dva, dmabuf->size);
+                       if (ret) {
+                               merr("fimc_is_itf_map is fail(%d)", vctx, ret);
+                               kfree(planes);
+                               kfree(buf);
+                               dma_buf_detach(dmabuf, attachment);
+                               dma_buf_put(dmabuf);
+                               goto p_err;
+                       }
+
+                       minfo("[3AA:V] buffer%d.plane%d mapping\n", vctx, buf->index, plane);
+                       set_bit(FRAME_MAP_MEM, &frame->memory);
+                       dma_buf_detach(dmabuf, attachment);
+                       dma_buf_put(dmabuf);
+                       kfree(planes);
+                       kfree(buf);
+               }
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aa_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       /* Todo: add to get control code */
+       return 0;
+}
+
+static int fimc_is_3aa_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       /* Todo: add to get extra control code */
+       return 0;
+}
+
+const struct v4l2_ioctl_ops fimc_is_3aa_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_3aa_video_querycap,
+
+       .vidioc_enum_fmt_vid_out_mplane = fimc_is_3aa_video_enum_fmt_mplane,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_3aa_video_enum_fmt_mplane,
+
+       .vidioc_g_fmt_vid_out_mplane    = fimc_is_3aa_video_get_format_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_3aa_video_get_format_mplane,
+
+       .vidioc_s_fmt_vid_out_mplane    = fimc_is_3aa_video_set_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_3aa_video_set_format_mplane,
+
+       .vidioc_querybuf                = fimc_is_3aa_video_querybuf,
+       .vidioc_reqbufs                 = fimc_is_3aa_video_reqbufs,
+
+       .vidioc_qbuf                    = fimc_is_3aa_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_3aa_video_dqbuf,
+
+       .vidioc_streamon                = fimc_is_3aa_video_streamon,
+       .vidioc_streamoff               = fimc_is_3aa_video_streamoff,
+
+       .vidioc_enum_input              = fimc_is_3aa_video_enum_input,
+       .vidioc_g_input                 = fimc_is_3aa_video_g_input,
+       .vidioc_s_input                 = fimc_is_3aa_video_s_input,
+
+       .vidioc_s_ctrl                  = fimc_is_3aa_video_s_ctrl,
+       .vidioc_g_ctrl                  = fimc_is_3aa_video_g_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_3aa_video_g_ext_ctrl,
+
+       .vidioc_cropcap                 = fimc_is_3aa_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_3aa_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_3aa_video_set_crop,
+};
+
+static int fimc_is_3aa_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       queue = GET_VCTX_QUEUE(vctx, vbq);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_buffer_prepare(struct vb2_buffer *vb)
+{
+       /* Todo : add to prepare buffer */
+       return 0;
+}
+
+static inline void fimc_is_3aa_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_3aa_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_3aa_start_streaming(struct vb2_queue *vbq,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       device = vctx->device;
+
+       if (V4L2_TYPE_IS_OUTPUT(vbq->type)) {
+               queue = GET_SRC_QUEUE(vctx);
+               subdev = &device->group_3aa.leader;
+       } else {
+               queue = GET_DST_QUEUE(vctx);
+               subdev = &device->taap;
+       }
+
+       ret = fimc_is_queue_start_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aa_stop_streaming(struct vb2_queue *vbq)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_3aa("%s\n", vctx, __func__);
+
+       device = vctx->device;
+
+       if (V4L2_TYPE_IS_OUTPUT(vbq->type)) {
+               queue = GET_SRC_QUEUE(vctx);
+               subdev = &device->group_3aa.leader;
+       } else {
+               queue = GET_DST_QUEUE(vctx);
+               subdev = &device->taap;
+       }
+
+       ret = fimc_is_queue_stop_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static void fimc_is_3aa_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       u32 index;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       index = vb->v4l2_buf.index;
+
+#ifdef DBG_STREAMING
+       mdbgv_3aa("%s(%02d:%d)\n", vctx, __func__, vb->v4l2_buf.type, index);
+#endif
+
+       video = vctx->video;
+       device = vctx->device;
+       leader = &device->group_3aa.leader;
+
+       if (V4L2_TYPE_IS_OUTPUT(vb->v4l2_buf.type)) {
+               queue = GET_SRC_QUEUE(vctx);
+               ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+               if (ret) {
+                       merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+                       return;
+               }
+
+               ret = fimc_is_ischain_3aa_buffer_queue(device, queue, index);
+               if (ret) {
+                       merr("fimc_is_ischain_3aa_buffer_queue is fail(%d)", vctx, ret);
+                       return;
+               }
+       } else {
+               queue = GET_DST_QUEUE(vctx);
+               ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+               if (ret) {
+                       merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+                       return;
+               }
+
+               ret = fimc_is_subdev_buffer_queue(leader, index);
+               if (ret) {
+                       merr("fimc_is_subdev_buffer_queue is fail(%d)", vctx, ret);
+                       return;
+               }
+       }
+}
+
+static int fimc_is_3aa_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       u32 index = vb->v4l2_buf.index;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device = vctx->device;
+       struct fimc_is_group *group = &device->group_3aa;
+       struct fimc_is_subdev *subdev = &group->leader;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!device);
+
+#ifdef DBG_STREAMING
+       mdbgv_3aa("%s(%02d:%d)\n", vctx, __func__, vb->v4l2_buf.type, index);
+#endif
+
+       if (V4L2_TYPE_IS_OUTPUT(vb->v4l2_buf.type)) {
+               queue = vctx->q_src;
+               fimc_is_ischain_3aa_buffer_finish(device, index);
+       } else {
+               queue = vctx->q_dst;
+               fimc_is_subdev_buffer_finish(subdev, index);
+       }
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_3aa_qops = {
+       .queue_setup            = fimc_is_3aa_queue_setup,
+       .buf_prepare            = fimc_is_3aa_buffer_prepare,
+       .buf_queue              = fimc_is_3aa_buffer_queue,
+       .buf_finish             = fimc_is_3aa_buffer_finish,
+       .wait_prepare           = fimc_is_3aa_wait_prepare,
+       .wait_finish            = fimc_is_3aa_wait_finish,
+       .start_streaming        = fimc_is_3aa_start_streaming,
+       .stop_streaming         = fimc_is_3aa_stop_streaming,
+};
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-3aac.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-3aac.c
new file mode 100644 (file)
index 0000000..3f63054
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+
+const struct v4l2_file_operations fimc_is_3aac_video_fops;
+const struct v4l2_ioctl_ops fimc_is_3aac_video_ioctl_ops;
+const struct vb2_ops fimc_is_3aac_qops;
+
+int fimc_is_3a0c_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_3a0c;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_3AAC_NAME(0),
+               FIMC_IS_VIDEO_3A0C_NUM,
+               VFL_DIR_RX,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_3aac_video_fops,
+               &fimc_is_3aac_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_3a1c_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_3a1c;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_3AAC_NAME(1),
+               FIMC_IS_VIDEO_3A1C_NUM,
+               VFL_DIR_RX,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_3aac_video_fops,
+               &fimc_is_3aac_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       info("[3AC1:V:1] %s(%d)\n", __func__, ret);
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_3aac_video_open(struct file *file)
+{
+       int ret = 0;
+       u32 refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+
+       if (video->id == FIMC_IS_VIDEO_3A0C_NUM)
+               core = container_of(video, struct fimc_is_core, video_3a0c);
+       else
+               core = container_of(video, struct fimc_is_core, video_3a1c);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_INVALID, FRAMEMGR_ID_3AAC);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[3A%dC:V:%d] %s\n", GET_3AAC_ID(video), vctx->instance, __func__);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount > FIMC_IS_MAX_NODES || refcount < 1) {
+               err("invalid ischain refcount(%d)", refcount);
+               close_vctx(file, video, vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = &core->ischain[refcount - 1];
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_3AAC_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_CAPTURE,
+               &fimc_is_3aac_qops,
+               NULL,
+               &fimc_is_ischain_sub_ops);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_subdev_open(&device->taac, vctx, NULL);
+       if (ret) {
+               err("fimc_is_subdev_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aac_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_device_ischain *device = NULL;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               merr("video is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[3A%dC:V:%d] %s\n", GET_3AAC_ID(video), vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_subdev_close(&device->taac);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_3aac_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+       if (ret)
+               merr("fimc_is_video_poll is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_3aac_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_3aac_video_open,
+       .release        = fimc_is_3aac_video_close,
+       .poll           = fimc_is_3aac_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_3aac_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_3aac_video_querycap(struct file *file, void *fh,
+       struct v4l2_capability *cap)
+{
+       /* Todo : add to query capability code */
+       return 0;
+}
+
+static int fimc_is_3aac_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+       BUG_ON(!format);
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       subdev = &device->taac;
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret) {
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_subdev_s_format(subdev, queue->framecfg.width, queue->framecfg.height);
+       if (ret) {
+               merr("fimc_is_ischain_3aac_s_format is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_3aac_video_try_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_cropcap(struct file *file, void *fh,
+       struct v4l2_cropcap *cropcap)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_get_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_set_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_3aac("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       device = vctx->device;
+       subdev = &device->taac;
+       leader = subdev->leader;
+
+       if (!leader) {
+               merr("leader is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("leader still running, not applied", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(%d)", vctx, ret);
+
+ p_err:
+       return ret;
+}
+
+static int fimc_is_3aac_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_3aac("%s(index : %d)\n", vctx, __func__, buf->index);
+#endif
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_3aac("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo: add enum input control code */
+       return 0;
+}
+
+static int fimc_is_3aac_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_3aac_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       return 0;
+}
+
+static int fimc_is_3aac_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_framemgr *framemgr;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       framemgr = GET_DST_FRAMEMGR(vctx);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_G_COMPLETES:
+               ctrl->value = framemgr->frame_com_cnt;
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int fimc_is_3aac_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       return 0;
+}
+
+static int fimc_is_3aac_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       switch (ctrl->id) {
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_is_3aac_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_3aac_video_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_3aac_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_3aac_video_get_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_3aac_video_set_format_mplane,
+       .vidioc_try_fmt_vid_cap_mplane  = fimc_is_3aac_video_try_format_mplane,
+       .vidioc_cropcap                 = fimc_is_3aac_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_3aac_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_3aac_video_set_crop,
+       .vidioc_reqbufs                 = fimc_is_3aac_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_3aac_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_3aac_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_3aac_video_dqbuf,
+       .vidioc_streamon                = fimc_is_3aac_video_streamon,
+       .vidioc_streamoff               = fimc_is_3aac_video_streamoff,
+       .vidioc_enum_input              = fimc_is_3aac_video_enum_input,
+       .vidioc_g_input                 = fimc_is_3aac_video_g_input,
+       .vidioc_s_input                 = fimc_is_3aac_video_s_input,
+       .vidioc_g_ctrl                  = fimc_is_3aac_video_g_ctrl,
+       .vidioc_s_ctrl                  = fimc_is_3aac_video_s_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_3aac_video_g_ext_ctrl,
+};
+
+static int fimc_is_3aac_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       queue = GET_VCTX_QUEUE(vctx, vbq);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_buffer_prepare(struct vb2_buffer *vb)
+{
+       return 0;
+}
+
+static inline void fimc_is_3aac_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_3aac_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_3aac_start_streaming(struct vb2_queue *vbq,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       queue = GET_VCTX_QUEUE(vctx, vbq);
+       device = vctx->device;
+       subdev = &device->taac;
+
+       ret = fimc_is_queue_start_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_3aac_stop_streaming(struct vb2_queue *vbq)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_3aac("%s\n", vctx, __func__);
+
+       queue = GET_VCTX_QUEUE(vctx, vbq);
+       device = vctx->device;
+       subdev = &device->taac;
+
+       ret = fimc_is_queue_stop_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static void fimc_is_3aac_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_video *video;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+#ifdef DBG_STREAMING
+       mdbgv_3aac("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+
+       queue = GET_DST_QUEUE(vctx);
+       video = vctx->video;
+       device = vctx->device;
+       subdev = &device->taac;
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+
+       ret = fimc_is_subdev_buffer_queue(subdev, vb->v4l2_buf.index);
+       if (ret) {
+               merr("fimc_is_subdev_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+}
+
+static int fimc_is_3aac_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+       struct fimc_is_subdev *subdev = &ischain->taac;
+
+#ifdef DBG_STREAMING
+       mdbgv_3aac("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+
+       ret = fimc_is_subdev_buffer_finish(subdev, vb->v4l2_buf.index);
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_3aac_qops = {
+       .queue_setup            = fimc_is_3aac_queue_setup,
+       .buf_prepare            = fimc_is_3aac_buffer_prepare,
+       .buf_queue              = fimc_is_3aac_buffer_queue,
+       .buf_finish             = fimc_is_3aac_buffer_finish,
+       .wait_prepare           = fimc_is_3aac_wait_prepare,
+       .wait_finish            = fimc_is_3aac_wait_finish,
+       .start_streaming        = fimc_is_3aac_start_streaming,
+       .stop_streaming         = fimc_is_3aac_stop_streaming,
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-companion.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-companion.c
new file mode 100644 (file)
index 0000000..c3da8b7
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-device-companion.h"
+#include "fimc-is-video.h"
+
+const struct v4l2_file_operations fimc_is_comp_video_fops;
+const struct v4l2_ioctl_ops fimc_is_comp_video_ioctl_ops;
+const struct vb2_ops fimc_is_comp_qops;
+
+int fimc_is_comp_video_probe(void *data)
+{
+       int ret = 0;
+       char name[255];
+       u32 number;
+       struct fimc_is_device_companion *device;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       device = (struct fimc_is_device_companion *)data;
+       video = &device->video;
+       snprintf(name, sizeof(name), "%s%d", FIMC_IS_VIDEO_SENSOR_NAME, 9);
+       number = FIMC_IS_VIDEO_SS0_NUM + 9;
+
+       if (!device->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               name,
+               number,
+               VFL_DIR_RX,
+               &device->mem,
+               &device->v4l2_dev,
+               &video->lock,
+               &fimc_is_comp_video_fops,
+               &fimc_is_comp_video_ioctl_ops);
+       if (ret)
+               dev_err(&device->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       info("[CP%d:V:X] %s(%d)\n", number, __func__, ret);
+       return ret;
+}
+
+#ifdef CONFIG_OIS_USE
+extern int fimc_is_ois_sine_mode(struct fimc_is_core *core, int mode);
+#endif
+
+static int fimc_is_comp_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video *video;
+       struct fimc_is_device_companion *device;
+
+       dbg_isp("%s\n", __func__);
+
+       video = video_drvdata(file);
+       device = container_of(video, struct fimc_is_device_companion, video);
+
+       if (!device->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       switch (ctrl->id) {
+#ifdef CONFIG_OIS_USE
+       case V4L2_CID_CAMERA_OIS_SINE_MODE:
+               if (fimc_is_ois_sine_mode(device->private_data, ctrl->value)) {
+                       err("failed to set ois sine mode : %d\n - %d",
+                       ctrl->value, ret);
+                       ret = -EINVAL;
+               }
+               break;
+#endif
+
+       default:
+               info("unsupported ioctl(%d, sine id = %d)\n", ctrl->id, V4L2_CID_CAMERA_OIS_SINE_MODE);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_comp_video_open(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_companion *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       device = container_of(video, struct fimc_is_device_companion, video);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_INVALID, FRAMEMGR_ID_INVALID);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[CP%d:V:%d] %s\n", video->id, vctx->instance, __func__);
+
+       ret = fimc_is_companion_open(device);
+       if (ret) {
+               merr("fimc_is_comp_open is fail(%d)", vctx, ret);
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_comp_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_device_companion *device = NULL;
+
+       BUG_ON(!file);
+
+       video = video_drvdata(file);
+       device = container_of(video, struct fimc_is_device_companion, video);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[CP:V:%d] %s\n", vctx->instance, __func__);
+
+       ret = fimc_is_companion_close(device);
+       if (ret)
+               err("fimc_is_companion_close is fail(%d)", ret);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_comp_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_comp_video_open,
+       .release        = fimc_is_comp_video_close,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+const struct v4l2_ioctl_ops fimc_is_comp_video_ioctl_ops = {
+       .vidioc_s_ctrl                  = fimc_is_comp_video_s_ctrl,
+};
+
+const struct vb2_ops fimc_is_comp_qops = {
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-isp.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-isp.c
new file mode 100644 (file)
index 0000000..2dea151
--- /dev/null
@@ -0,0 +1,967 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/pm_qos.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-metadata.h"
+
+extern struct fimc_is_from_info                *sysfs_finfo;
+extern struct fimc_is_from_info                *sysfs_pinfo;
+extern bool is_dumped_fw_loading_needed;
+
+const struct v4l2_file_operations fimc_is_isp_video_fops;
+const struct v4l2_ioctl_ops fimc_is_isp_video_ioctl_ops;
+const struct vb2_ops fimc_is_isp_qops;
+
+int fimc_is_isp_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_isp;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_ISP_NAME,
+               FIMC_IS_VIDEO_ISP_NUM,
+               VFL_DIR_M2M,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_isp_video_fops,
+               &fimc_is_isp_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_isp_video_open(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       core = container_of(video, struct fimc_is_core, video_isp);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_ISP_GRP, FRAMEMGR_ID_INVALID);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[ISP:V:%d] %s\n", vctx->instance, __func__);
+
+       device = &core->ischain[vctx->instance];
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_ISP_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_OUTPUT,
+               &fimc_is_isp_qops,
+               &fimc_is_ischain_isp_ops,
+               NULL);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_open(device, vctx, &core->minfo);
+       if (ret) {
+               err("fimc_is_ischain_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_isp_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_device_ischain *device = NULL;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               err("video is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[ISP:V:%d] %s\n", video->id, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (pm_qos_request_active(&device->user_qos))
+               pm_qos_remove_request(&device->user_qos);
+
+       fimc_is_ischain_close(device, vctx);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_isp_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+       if (ret)
+               merr("fimc_is_video_poll is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_isp_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_isp_video_open,
+       .release        = fimc_is_isp_video_close,
+       .poll           = fimc_is_isp_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_isp_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_isp_video_querycap(struct file *file, void *fh,
+                                       struct v4l2_capability *cap)
+{
+       struct fimc_is_core *isp = video_drvdata(file);
+
+       strncpy(cap->driver, isp->pdev->name, sizeof(cap->driver) - 1);
+
+       dbg_isp("%s(devname : %s)\n", __func__, cap->driver);
+       strncpy(cap->card, isp->pdev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_STREAMING
+                               | V4L2_CAP_VIDEO_CAPTURE
+                               | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+       return 0;
+}
+
+static int fimc_is_isp_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       dbg_isp("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_isp_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       dbg_isp("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_isp_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       queue = GET_VCTX_QUEUE(vctx, format);
+       device = vctx->device;
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret)
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+
+       fimc_is_ischain_isp_s_format(device,
+               queue->framecfg.width,
+               queue->framecfg.height);
+
+       return ret;
+}
+
+static int fimc_is_isp_video_cropcap(struct file *file, void *fh,
+                                               struct v4l2_cropcap *cropcap)
+{
+       dbg_isp("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_isp_video_get_crop(struct file *file, void *fh,
+                                               struct v4l2_crop *crop)
+{
+       dbg_isp("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_isp_video_set_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *ischain;
+
+       BUG_ON(!vctx);
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       ischain = vctx->device;
+       BUG_ON(!ischain);
+
+       fimc_is_ischain_isp_s_format(ischain,
+               crop->c.width, crop->c.height);
+
+       return 0;
+}
+
+static int fimc_is_isp_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_isp("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_isp_reqbufs(device, buf->count);
+       if (ret) {
+               merr("isp_reqbufs is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(error %d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_isp_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+
+#ifdef DBG_STREAMING
+       mdbgv_isp("%s(index : %d)\n", vctx, __func__, buf->index);
+#endif
+
+       queue = GET_VCTX_QUEUE(vctx, buf);
+
+       if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               merr("stream off state, can NOT qbuf", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_isp_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_isp("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_video_enum_input(struct file *file, void *priv,
+                                               struct v4l2_input *input)
+{
+       /* Todo : add to enum input control code */
+       return 0;
+}
+
+static int fimc_is_isp_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       /* Todo : add to get input control code */
+       return 0;
+}
+
+static int fimc_is_isp_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+
+       mdbgv_isp("%s(input : %08X)\n", vctx, __func__, input);
+
+       device = vctx->device;
+
+       ret = fimc_is_ischain_isp_s_input(device, input);
+       if (ret) {
+               merr("fimc_is_ischain_isp_s_input is fail", vctx);
+               goto p_err;
+       }
+
+       /* if there's only one group of isp, defines group id to 3a0 connected */
+       if (GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a0)
+                       || GET_FIMC_IS_NUM_OF_SUBIP2(device, 3a1))
+               goto p_err;
+
+       ret = fimc_is_ischain_init_wrap(device, input);
+       if (ret) {
+               merr("fimc_is_device_init(%d) is fail", vctx, input);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_isp_video_s_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       int i2c_clk;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_core *core;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+       BUG_ON(!vctx->video);
+
+       dbg_isp("%s\n", __func__);
+
+       device = vctx->device;
+       video = vctx->video;
+       core = container_of(video, struct fimc_is_core, video_isp);
+
+       if (core->resourcemgr.dvfs_ctrl.cur_int_qos == DVFS_L0)
+               i2c_clk = I2C_L0;
+       else
+               i2c_clk = I2C_L1;
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_DEBUG_DUMP:
+               info("Print fimc-is info dump by HAL");
+               if (device != NULL) {
+                       fimc_is_hw_logdump(device->interface);
+                       fimc_is_hw_regdump(device->interface);
+                       CALL_POPS(device, print_clk, device->pdev);
+               }
+               if (ctrl->value) {
+                       err("BUG_ON from HAL");
+                       BUG();
+               }
+               break;
+       case V4L2_CID_IS_DEBUG_SYNC_LOG:
+               fimc_is_logsync(device->interface, ctrl->value, IS_MSG_TEST_SYNC_LOG);
+               break;
+       case V4L2_CID_IS_G_CAPABILITY:
+               ret = fimc_is_ischain_g_capability(device, ctrl->value);
+               dbg_isp("V4L2_CID_IS_G_CAPABILITY : %X\n", ctrl->value);
+               break;
+       case V4L2_CID_IS_FORCE_DONE:
+               set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &device->group_isp.state);
+               break;
+       case V4L2_CID_IS_DVFS_LOCK:
+               ret = fimc_is_itf_i2c_lock(device, I2C_L0, true);
+               if (ret) {
+                       err("fimc_is_itf_i2_clock fail\n");
+                       break;
+               }
+               pm_qos_add_request(&device->user_qos, PM_QOS_DEVICE_THROUGHPUT,
+                                       ctrl->value);
+               ret = fimc_is_itf_i2c_lock(device, I2C_L0, false);
+               if (ret) {
+                       err("fimc_is_itf_i2c_unlock fail\n");
+                       break;
+               }
+               dbg_isp("V4L2_CID_IS_DVFS_LOCK : %d\n", ctrl->value);
+               break;
+       case V4L2_CID_IS_DVFS_UNLOCK:
+               ret = fimc_is_itf_i2c_lock(device, i2c_clk, true);
+               if (ret) {
+                       err("fimc_is_itf_i2_clock fail\n");
+                       break;
+               }
+               pm_qos_remove_request(&device->user_qos);
+               ret = fimc_is_itf_i2c_lock(device, i2c_clk, false);
+               if (ret) {
+                       err("fimc_is_itf_i2c_unlock fail\n");
+                       break;
+               }
+               dbg_isp("V4L2_CID_IS_DVFS_UNLOCK : %d I2C(%d)\n", ctrl->value, i2c_clk);
+               break;
+       case V4L2_CID_IS_SET_SETFILE:
+               if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) {
+                       err("Setting setfile is only avaiable before starting device!! (0x%08x)",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->setfile = ctrl->value;
+                       minfo("[ISP:V] setfile: 0x%08X\n", vctx, ctrl->value);
+               }
+               break;
+       case V4L2_CID_IS_COLOR_RANGE:
+               if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) {
+                       err("failed to change color range: device started already (0x%08x)",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->color_range &= ~FIMC_IS_ISP_CRANGE_MASK;
+
+                       if (ctrl->value)
+                               device->color_range     |=
+                                       (FIMC_IS_CRANGE_LIMITED << FIMC_IS_ISP_CRANGE_SHIFT);
+               }
+               break;
+       case V4L2_CID_IS_MAP_BUFFER:
+               {
+                       struct fimc_is_queue *queue;
+                       struct fimc_is_framemgr *framemgr;
+                       struct fimc_is_frame *frame;
+                       struct dma_buf *dmabuf;
+                       struct dma_buf_attachment *attachment;
+                       dma_addr_t dva;
+                       struct v4l2_buffer *buf = NULL;
+                       struct v4l2_plane *planes;
+                       size_t size;
+                       u32 write, plane, group_id;
+
+                       size = sizeof(struct v4l2_buffer);
+                       buf = kmalloc(size, GFP_KERNEL);
+                       if (!buf) {
+                               merr("kmalloc is fail", vctx);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       ret = copy_from_user(buf, (void __user *)ctrl->value, size);
+                       if (ret) {
+                               merr("copy_from_user is fail(%d)", vctx, ret);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       if (!V4L2_TYPE_IS_MULTIPLANAR(buf->type)) {
+                               merr("single plane is not supported", vctx);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       if (buf->index >= FRAMEMGR_MAX_REQUEST) {
+                               merr("buffer index is invalid(%d)", vctx, buf->index);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       if (buf->length > VIDEO_MAX_PLANES) {
+                               merr("planes[%d] is invalid", vctx, buf->length);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       queue = GET_QUEUE(vctx, buf->type);
+                       if (queue->vbq->memory != V4L2_MEMORY_DMABUF) {
+                               merr("memory type(%d) is not supported", vctx, queue->vbq->memory);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       size = sizeof(struct v4l2_plane) * buf->length;
+                       planes = kmalloc(size, GFP_KERNEL);
+                       if (IS_ERR(planes)) {
+                               merr("kmalloc is fail(%p)", vctx, planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       ret = copy_from_user(planes, (void __user *)buf->m.planes, size);
+                       if (ret) {
+                               merr("copy_from_user is fail(%d)", vctx, ret);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       framemgr = &queue->framemgr;
+                       frame = &framemgr->frame[buf->index];
+                       if (test_bit(FRAME_MAP_MEM, &frame->memory)) {
+                               merr("this buffer(%d) is already mapped", vctx, buf->index);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       /* only last buffer need to map */
+                       if (buf->length > 0) {
+                               plane = buf->length - 1;
+                       } else {
+                               merr("buf size is abnormal(%d)", vctx, buf->length);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+                       dmabuf = dma_buf_get(planes[plane].m.fd);
+                       if (IS_ERR(dmabuf)) {
+                               merr("dma_buf_get is fail(%p)", vctx, dmabuf);
+                               kfree(planes);
+                               kfree(buf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       attachment = dma_buf_attach(dmabuf, &device->pdev->dev);
+                       if (IS_ERR(attachment)) {
+                               merr("dma_buf_attach is fail(%p)", vctx, attachment);
+                               kfree(planes);
+                               kfree(buf);
+                               dma_buf_put(dmabuf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       write = !V4L2_TYPE_IS_OUTPUT(buf->type);
+                       dva = ion_iovmm_map(attachment, 0, dmabuf->size, write, plane);
+                       if (IS_ERR_VALUE(dva)) {
+                               merr("ion_iovmm_map is fail(%X)", vctx, dva);
+                               kfree(planes);
+                               kfree(buf);
+                               dma_buf_detach(dmabuf, attachment);
+                               dma_buf_put(dmabuf);
+                               ret = -EINVAL;
+                               goto p_err;
+                       }
+
+                       group_id = GROUP_ID(device->group_isp.id);
+                       ret = fimc_is_itf_map(device, group_id, dva, dmabuf->size);
+                       if (ret) {
+                               merr("fimc_is_itf_map is fail(%d)", vctx, ret);
+                               kfree(planes);
+                               kfree(buf);
+                               dma_buf_detach(dmabuf, attachment);
+                               dma_buf_put(dmabuf);
+                               goto p_err;
+                       }
+
+                       minfo("[ISP:V] buffer%d.plane%d mapping\n", vctx, buf->index, plane);
+                       set_bit(FRAME_MAP_MEM, &frame->memory);
+                       dma_buf_detach(dmabuf, attachment);
+                       dma_buf_put(dmabuf);
+                       kfree(planes);
+                       kfree(buf);
+               }
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_isp_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+
+       dbg_isp("%s\n", __func__);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_BDS_WIDTH:
+               ctrl->value = ischain->chain0_width;
+               break;
+       case V4L2_CID_IS_BDS_HEIGHT:
+               ctrl->value = ischain->chain0_height;
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int fimc_is_isp_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       int ret = 0;
+       struct v4l2_ext_control *ctrl;
+
+       dbg_isp("%s\n", __func__);
+
+
+       ctrl = ctrls->controls;
+
+       switch (ctrl->id) {
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_is_isp_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_isp_video_querycap,
+       .vidioc_enum_fmt_vid_out_mplane = fimc_is_isp_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_out_mplane    = fimc_is_isp_video_get_format_mplane,
+       .vidioc_s_fmt_vid_out_mplane    = fimc_is_isp_video_set_format_mplane,
+       .vidioc_cropcap                 = fimc_is_isp_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_isp_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_isp_video_set_crop,
+       .vidioc_reqbufs                 = fimc_is_isp_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_isp_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_isp_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_isp_video_dqbuf,
+       .vidioc_streamon                = fimc_is_isp_video_streamon,
+       .vidioc_streamoff               = fimc_is_isp_video_streamoff,
+       .vidioc_enum_input              = fimc_is_isp_video_enum_input,
+       .vidioc_g_input                 = fimc_is_isp_video_g_input,
+       .vidioc_s_input                 = fimc_is_isp_video_s_input,
+       .vidioc_s_ctrl                  = fimc_is_isp_video_s_ctrl,
+       .vidioc_g_ctrl                  = fimc_is_isp_video_g_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_isp_video_g_ext_ctrl,
+};
+
+static int fimc_is_isp_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers, unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       queue = GET_SRC_QUEUE(vctx);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_buffer_prepare(struct vb2_buffer *vb)
+{
+       /*dbg_isp("%s\n", __func__);*/
+       return 0;
+}
+
+static inline void fimc_is_isp_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_isp_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_isp_start_streaming(struct vb2_queue *vbq,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       queue = GET_SRC_QUEUE(vctx);
+       device = vctx->device;
+       leader = &device->group_isp.leader;
+
+       ret = fimc_is_queue_start_streaming(queue, device, leader, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_isp_stop_streaming(struct vb2_queue *q)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       queue = GET_SRC_QUEUE(vctx);
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+       leader = &device->group_isp.leader;
+
+       ret = fimc_is_queue_stop_streaming(queue, device, leader, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static void fimc_is_isp_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       u32 index;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_video *video;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       index = vb->v4l2_buf.index;
+
+#ifdef DBG_STREAMING
+       mdbgv_isp("%s(%d)\n", vctx, __func__, index);
+#endif
+
+       queue = GET_SRC_QUEUE(vctx);
+       video = vctx->video;
+       device = vctx->device;
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+
+       ret = fimc_is_ischain_isp_buffer_queue(device, queue, index);
+       if (ret) {
+               merr("fimc_is_ischain_isp_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+}
+
+static int fimc_is_isp_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device = vctx->device;
+
+#ifdef DBG_STREAMING
+       mdbgv_isp("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+
+       ret = fimc_is_ischain_isp_buffer_finish(device, vb->v4l2_buf.index);
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_isp_qops = {
+       .queue_setup            = fimc_is_isp_queue_setup,
+       .buf_prepare            = fimc_is_isp_buffer_prepare,
+       .buf_queue              = fimc_is_isp_buffer_queue,
+       .buf_finish             = fimc_is_isp_buffer_finish,
+       .wait_prepare           = fimc_is_isp_wait_prepare,
+       .wait_finish            = fimc_is_isp_wait_finish,
+       .start_streaming        = fimc_is_isp_start_streaming,
+       .stop_streaming         = fimc_is_isp_stop_streaming,
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-scc.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-scc.c
new file mode 100644 (file)
index 0000000..ebe1a01
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+
+const struct v4l2_file_operations fimc_is_scc_video_fops;
+const struct v4l2_ioctl_ops fimc_is_scc_video_ioctl_ops;
+const struct vb2_ops fimc_is_scc_qops;
+
+int fimc_is_scc_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_scc;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_SCC_NAME,
+               FIMC_IS_VIDEO_SCC_NUM,
+               VFL_DIR_RX,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_scc_video_fops,
+               &fimc_is_scc_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_scc_video_open(struct file *file)
+{
+       int ret = 0;
+       u32 refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       core = container_of(video, struct fimc_is_core, video_scc);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_INVALID, FRAMEMGR_ID_SCC);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[SCC:V:%d] %s\n", vctx->instance, __func__);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount > FIMC_IS_MAX_NODES || refcount < 1) {
+               err("invalid ischain refcount(%d)", refcount);
+               close_vctx(file, video, vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = &core->ischain[refcount - 1];
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_SCC_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_CAPTURE,
+               &fimc_is_scc_qops,
+               NULL,
+               &fimc_is_ischain_sub_ops);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_subdev_open(&device->scc, vctx, NULL);
+       if (ret) {
+               err("fimc_is_subdev_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_scc_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_device_ischain *device = NULL;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               merr("video is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[SCC:V:%d] %s\n", vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_subdev_close(&device->scc);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_scc_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_scc_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_scc_video_open,
+       .release        = fimc_is_scc_video_close,
+       .poll           = fimc_is_scc_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_scc_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_scc_video_querycap(struct file *file, void *fh,
+                                               struct v4l2_capability *cap)
+{
+       struct fimc_is_core *isp = video_drvdata(file);
+
+       strncpy(cap->driver, isp->pdev->name, sizeof(cap->driver) - 1);
+
+       dbg("(devname : %s)\n", cap->driver);
+       strncpy(cap->card, isp->pdev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_STREAMING
+                               | V4L2_CAP_VIDEO_CAPTURE
+                               | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+       return 0;
+}
+
+static int fimc_is_scc_video_enum_fmt_mplane(struct file *file, void *priv,
+                                   struct v4l2_fmtdesc *f)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_get_format_mplane(struct file *file, void *fh,
+                                               struct v4l2_format *format)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_set_format_mplane(struct file *file, void *fh,
+                                               struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret)
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_try_format_mplane(struct file *file, void *fh,
+                                               struct v4l2_format *format)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_cropcap(struct file *file, void *fh,
+                                               struct v4l2_cropcap *cropcap)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_get_crop(struct file *file, void *fh,
+                                               struct v4l2_crop *crop)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_set_crop(struct file *file, void *fh,
+                                               struct v4l2_crop *crop)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_scc("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       device = vctx->device;
+       subdev = &device->scc;
+       leader = subdev->leader;
+
+       if (!leader) {
+               merr("leader is NULL ptr", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("leader still running, not applied", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_scc_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_scc("%s(index : %d)\n", vctx, __func__, buf->index);
+#endif
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_scc("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo : add to enum input control code */
+       return 0;
+}
+
+static int fimc_is_scc_video_g_input(struct file *file, void *priv,
+                                               unsigned int *input)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scc_video_s_input(struct file *file, void *priv,
+                                               unsigned int input)
+{
+       return 0;
+}
+
+static int fimc_is_scc_video_g_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_framemgr *framemgr = GET_DST_FRAMEMGR(vctx);
+
+       dbg_scc("%s\n", __func__);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_G_COMPLETES:
+               ctrl->value = framemgr->frame_com_cnt;
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int fimc_is_scc_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr = GET_DST_FRAMEMGR(vctx);
+       frame = NULL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_FORCE_DONE:
+               if (framemgr->frame_pro_cnt) {
+                       err("force done can be performed(process count %d)",
+                               framemgr->frame_pro_cnt);
+                       ret = -EINVAL;
+               } else if (!framemgr->frame_req_cnt) {
+                       err("force done can be performed(request count %d)",
+                               framemgr->frame_req_cnt);
+                       ret = -EINVAL;
+               } else {
+                       framemgr_e_barrier_irqs(framemgr, 0, flags);
+
+                       fimc_is_frame_request_head(framemgr, &frame);
+                       if (frame) {
+                               fimc_is_frame_trans_req_to_com(framemgr, frame);
+                               buffer_done(vctx, frame->index);
+                       } else {
+                               err("frame is NULL");
+                               ret = -EINVAL;
+                       }
+
+                       framemgr_x_barrier_irqr(framemgr, 0, flags);
+               }
+               break;
+       case V4L2_CID_IS_COLOR_RANGE:
+               if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) {
+                       err("failed to change color range: device started already (0x%08x)",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->color_range &= ~FIMC_IS_SCC_CRANGE_MASK;
+
+                       if (ctrl->value)
+                               device->color_range     |=
+                                       (FIMC_IS_CRANGE_LIMITED << FIMC_IS_SCC_CRANGE_SHIFT);
+               }
+               break;
+       default:
+               merr("unsupported ioctl(%d)\n", vctx, ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_is_scc_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_scc_video_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_scc_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_scc_video_get_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_scc_video_set_format_mplane,
+       .vidioc_try_fmt_vid_cap_mplane  = fimc_is_scc_video_try_format_mplane,
+       .vidioc_cropcap                 = fimc_is_scc_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_scc_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_scc_video_set_crop,
+       .vidioc_reqbufs                 = fimc_is_scc_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_scc_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_scc_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_scc_video_dqbuf,
+       .vidioc_streamon                = fimc_is_scc_video_streamon,
+       .vidioc_streamoff               = fimc_is_scc_video_streamoff,
+       .vidioc_enum_input              = fimc_is_scc_video_enum_input,
+       .vidioc_g_input                 = fimc_is_scc_video_g_input,
+       .vidioc_s_input                 = fimc_is_scc_video_s_input,
+       .vidioc_g_ctrl                  = fimc_is_scc_video_g_ctrl,
+       .vidioc_s_ctrl                  = fimc_is_scc_video_s_ctrl,
+};
+
+static int fimc_is_scc_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers,
+       unsigned int *num_planes, unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+static int fimc_is_scc_buffer_prepare(struct vb2_buffer *vb)
+{
+       return 0;
+}
+
+static inline void fimc_is_scc_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_scc_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_scc_start_streaming(struct vb2_queue *q,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       subdev = &device->scc;
+
+       ret = fimc_is_queue_start_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scc_stop_streaming(struct vb2_queue *q)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       mdbgv_scc("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+       subdev = &device->scc;
+
+       ret = fimc_is_queue_stop_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static void fimc_is_scc_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue = vctx->q_dst;
+       struct fimc_is_video *video = vctx->video;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+       struct fimc_is_subdev *scc = &ischain->scc;
+
+#ifdef DBG_STREAMING
+       dbg_scc("%s\n", __func__);
+#endif
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+
+       ret = fimc_is_subdev_buffer_queue(scc, vb->v4l2_buf.index);
+       if (ret) {
+               merr("fimc_is_subdev_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+}
+
+static int fimc_is_scc_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+#ifdef DBG_STREAMING
+       mdbgv_scc("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+
+       device = vctx->device;
+       subdev = &device->scc;
+
+       ret = fimc_is_subdev_buffer_finish(subdev, vb->v4l2_buf.index);
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_scc_qops = {
+       .queue_setup            = fimc_is_scc_queue_setup,
+       .buf_prepare            = fimc_is_scc_buffer_prepare,
+       .buf_queue              = fimc_is_scc_buffer_queue,
+       .buf_finish             = fimc_is_scc_buffer_finish,
+       .wait_prepare           = fimc_is_scc_wait_prepare,
+       .wait_finish            = fimc_is_scc_wait_finish,
+       .start_streaming        = fimc_is_scc_start_streaming,
+       .stop_streaming         = fimc_is_scc_stop_streaming,
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-scp.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-scp.c
new file mode 100644 (file)
index 0000000..42600bb
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+
+const struct v4l2_file_operations fimc_is_scp_video_fops;
+const struct v4l2_ioctl_ops fimc_is_scp_video_ioctl_ops;
+const struct vb2_ops fimc_is_scp_qops;
+
+int fimc_is_scp_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_scp;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_SCP_NAME,
+               FIMC_IS_VIDEO_SCP_NUM,
+               VFL_DIR_RX,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_scp_video_fops,
+               &fimc_is_scp_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_scp_video_open(struct file *file)
+{
+       int ret = 0;
+       u32 refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       core = container_of(video, struct fimc_is_core, video_scp);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_INVALID, FRAMEMGR_ID_SCP);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[SCP:V:%d] %s\n", vctx->instance, __func__);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount > FIMC_IS_MAX_NODES || refcount < 1) {
+               err("invalid ischain refcount(%d)", refcount);
+               close_vctx(file, video, vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = &core->ischain[refcount - 1];
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_SCP_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_CAPTURE,
+               &fimc_is_scp_qops,
+               NULL,
+               &fimc_is_ischain_sub_ops);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_subdev_open(&device->scp, vctx, NULL);
+       if (ret) {
+               err("fimc_is_subdev_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_scp_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_device_ischain *device = NULL;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               merr("video is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[SCP:V:%d] %s\n", vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_subdev_close(&device->scp);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_scp_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+
+       return ret;
+}
+
+static int fimc_is_scp_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_scp_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_scp_video_open,
+       .release        = fimc_is_scp_video_close,
+       .poll           = fimc_is_scp_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_scp_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_scp_video_querycap(struct file *file, void *fh,
+       struct v4l2_capability *cap)
+{
+       struct fimc_is_core *core = video_drvdata(file);
+
+       strncpy(cap->driver, core->pdev->name, sizeof(cap->driver) - 1);
+
+       dbg("%s(devname : %s)\n", __func__, cap->driver);
+       strncpy(cap->card, core->pdev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_STREAMING
+                                       | V4L2_CAP_VIDEO_CAPTURE
+                                       | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+       return 0;
+}
+
+static int fimc_is_scp_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scp_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scp_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *ischain;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->device);
+       BUG_ON(!format);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       ischain = vctx->device;
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret) {
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_scp_s_format(ischain,
+               queue->framecfg.format.pixelformat,
+               queue->framecfg.width,
+               queue->framecfg.height);
+       if (ret)
+               merr("fimc_is_ischain_scp_s_format is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_scp_video_try_format_mplane(struct file *file, void *fh,
+                                               struct v4l2_format *format)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scp_video_cropcap(struct file *file, void *fh,
+                                               struct v4l2_cropcap *cropcap)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scp_video_get_crop(struct file *file, void *fh,
+                                               struct v4l2_crop *crop)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scp_video_set_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_scp_s_format(device,
+               queue->framecfg.format.pixelformat,
+               crop->c.width,
+               crop->c.height);
+       if (ret)
+               merr("fimc_is_ischain_scp_s_format is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_scp_video_reqbufs(struct file *file, void *priv,
+                                       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_scp("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       device = vctx->device;
+       subdev = &device->scp;
+       leader = subdev->leader;
+
+       if (!leader) {
+               merr("leader is NULL ptr", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("leader still running, not applied", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_scp_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_scp("%s(index : %d)\n", vctx, __func__, buf->index);
+#endif
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_scp("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo : add to enum input control code */
+       return 0;
+}
+
+static int fimc_is_scp_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       dbg("%s\n", __func__);
+       return 0;
+}
+
+static int fimc_is_scp_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       return 0;
+}
+
+static int fimc_is_scp_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_framemgr *framemgr;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       framemgr = GET_DST_FRAMEMGR(vctx);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_G_COMPLETES:
+               ctrl->value = framemgr->frame_com_cnt;
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int fimc_is_scp_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       return 0;
+}
+
+static int fimc_is_scp_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr = GET_DST_FRAMEMGR(vctx);
+       frame = NULL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_FORCE_DONE:
+               if (framemgr->frame_pro_cnt) {
+                       err("force done can be performed(process count %d)",
+                               framemgr->frame_pro_cnt);
+                       ret = -EINVAL;
+               } else if (!framemgr->frame_req_cnt) {
+                       err("force done can be performed(request count %d)",
+                               framemgr->frame_req_cnt);
+                       ret = -EINVAL;
+               } else {
+                       framemgr_e_barrier_irqs(framemgr, 0, flags);
+
+                       fimc_is_frame_request_head(framemgr, &frame);
+                       if (frame) {
+                               fimc_is_frame_trans_req_to_com(framemgr, frame);
+                               buffer_done(vctx, frame->index);
+                       } else {
+                               err("frame is NULL");
+                               ret = -EINVAL;
+                       }
+
+                       framemgr_x_barrier_irqr(framemgr, 0, flags);
+               }
+               break;
+       case V4L2_CID_IS_COLOR_RANGE:
+               if (test_bit(FIMC_IS_SUBDEV_START, &device->group_isp.leader.state)) {
+                       err("failed to change color range: device started already (0x%08x)",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->color_range &= ~FIMC_IS_SCP_CRANGE_MASK;
+
+                       if (ctrl->value)
+                               device->color_range     |=
+                                       (FIMC_IS_CRANGE_LIMITED << FIMC_IS_SCP_CRANGE_SHIFT);
+               }
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_is_scp_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_scp_video_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_scp_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_scp_video_get_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_scp_video_set_format_mplane,
+       .vidioc_try_fmt_vid_cap_mplane  = fimc_is_scp_video_try_format_mplane,
+       .vidioc_cropcap                 = fimc_is_scp_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_scp_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_scp_video_set_crop,
+       .vidioc_reqbufs                 = fimc_is_scp_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_scp_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_scp_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_scp_video_dqbuf,
+       .vidioc_streamon                = fimc_is_scp_video_streamon,
+       .vidioc_streamoff               = fimc_is_scp_video_streamoff,
+       .vidioc_enum_input              = fimc_is_scp_video_enum_input,
+       .vidioc_g_input                 = fimc_is_scp_video_g_input,
+       .vidioc_s_input                 = fimc_is_scp_video_s_input,
+       .vidioc_g_ctrl                  = fimc_is_scp_video_g_ctrl,
+       .vidioc_s_ctrl                  = fimc_is_scp_video_s_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_scp_video_g_ext_ctrl,
+};
+
+static int fimc_is_scp_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_buffer_prepare(struct vb2_buffer *vb)
+{
+       return 0;
+}
+
+static inline void fimc_is_scp_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_scp_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_scp_start_streaming(struct vb2_queue *q,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       subdev = &device->scp;
+
+       ret = fimc_is_queue_start_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_scp_stop_streaming(struct vb2_queue *q)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+       mdbgv_scp("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+       subdev = &device->scp;
+
+       ret = fimc_is_queue_stop_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static void fimc_is_scp_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_video *video;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+#ifdef DBG_STREAMING
+       dbg_scp("%s\n", __func__);
+#endif
+
+       queue = GET_DST_QUEUE(vctx);
+       video = vctx->video;
+       device = vctx->device;
+       subdev = &device->scp;
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+
+       ret = fimc_is_subdev_buffer_queue(subdev, vb->v4l2_buf.index);
+       if (ret) {
+               merr("fimc_is_subdev_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+}
+
+static int fimc_is_scp_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+       struct fimc_is_subdev *scp = &ischain->scp;
+
+#ifdef DBG_STREAMING
+       dbg_scp("%s(%d)\n", __func__, vb->v4l2_buf.index);
+#endif
+
+       ret = fimc_is_subdev_buffer_finish(scp, vb->v4l2_buf.index);
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_scp_qops = {
+       .queue_setup            = fimc_is_scp_queue_setup,
+       .buf_prepare            = fimc_is_scp_buffer_prepare,
+       .buf_queue              = fimc_is_scp_buffer_queue,
+       .buf_finish             = fimc_is_scp_buffer_finish,
+       .wait_prepare           = fimc_is_scp_wait_prepare,
+       .wait_finish            = fimc_is_scp_wait_finish,
+       .start_streaming        = fimc_is_scp_start_streaming,
+       .stop_streaming         = fimc_is_scp_stop_streaming,
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-sensor.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-sensor.c
new file mode 100644 (file)
index 0000000..d7c7917
--- /dev/null
@@ -0,0 +1,871 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-metadata.h"
+
+const struct v4l2_file_operations fimc_is_sen_video_fops;
+const struct v4l2_ioctl_ops fimc_is_sen_video_ioctl_ops;
+const struct vb2_ops fimc_is_sen_qops;
+
+int fimc_is_sen_video_probe(void *data)
+{
+       int ret = 0;
+       char name[255];
+       u32 number;
+       struct fimc_is_device_sensor *device;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       device = (struct fimc_is_device_sensor *)data;
+       video = &device->video;
+       snprintf(name, sizeof(name), "%s%d", FIMC_IS_VIDEO_SENSOR_NAME, device->instance);
+       number = FIMC_IS_VIDEO_SS0_NUM + device->instance;
+
+       if (!device->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               name,
+               number,
+               VFL_DIR_RX,
+               &device->mem,
+               &device->v4l2_dev,
+               &video->lock,
+               &fimc_is_sen_video_fops,
+               &fimc_is_sen_video_ioctl_ops);
+       if (ret)
+               dev_err(&device->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Video File Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_sen_video_open(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_sensor *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       device = container_of(video, struct fimc_is_device_sensor, video);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_INVALID, FRAMEMGR_ID_SENSOR);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[SS%d:V:%d] %s\n", video->id, vctx->instance, __func__);
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_SENSOR_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_CAPTURE,
+               &fimc_is_sen_qops,
+               NULL,
+               NULL);
+       if (ret) {
+               merr("fimc_is_video_open is fail(%d)", vctx, ret);
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_open(device, vctx);
+       if (ret) {
+               merr("fimc_is_sen_open is fail(%d)", vctx, ret);
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sen_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video = NULL;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_device_sensor *device = NULL;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               merr("video is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[SS0:V:%d] %s\n", vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               merr("device is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_close(device);
+       if (ret)
+               err("fimc_is_sensor_close is fail(%d)", ret);
+
+       ret = fimc_is_video_close(vctx);
+       if (ret)
+               err("fimc_is_video_close is fail(%d)", ret);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_sen_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+
+       return ret;
+}
+
+static int fimc_is_sen_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_sen_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_sen_video_open,
+       .release        = fimc_is_sen_video_close,
+       .poll           = fimc_is_sen_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_sen_video_mmap,
+};
+
+/*
+ * =============================================================================
+ * Video Ioctl Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_sen_video_querycap(struct file *file, void *fh,
+                                       struct v4l2_capability *cap)
+{
+       /* Todo : add to query capability code */
+       return 0;
+}
+
+static int fimc_is_sen_video_enum_fmt_mplane(struct file *file, void *priv,
+                                   struct v4l2_fmtdesc *f)
+{
+       /* Todo : add to enumerate format code */
+       return 0;
+}
+
+static int fimc_is_sen_video_get_format_mplane(struct file *file, void *fh,
+                                               struct v4l2_format *format)
+{
+       /* Todo : add to get format code */
+       return 0;
+}
+
+static int fimc_is_sen_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret) {
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_s_format(device,
+               &queue->framecfg.format,
+               queue->framecfg.width,
+               queue->framecfg.height);
+       if (ret) {
+               merr("fimc_is_sensor_s_format is fail(%d)", vctx, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sen_video_cropcap(struct file *file, void *fh,
+       struct v4l2_cropcap *cropcap)
+{
+       /* Todo : add to crop capability code */
+       return 0;
+}
+
+static int fimc_is_sen_video_get_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       /* Todo : add to get crop control code */
+       return 0;
+}
+
+static int fimc_is_sen_video_set_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_sensor *sensor;
+
+       BUG_ON(!vctx);
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       sensor = vctx->device;
+       BUG_ON(!sensor);
+
+       fimc_is_sensor_s_format(sensor, &sensor->image.format, crop->c.width, crop->c.height);
+
+       return 0;
+}
+
+static int fimc_is_sen_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       BUG_ON(!vctx);
+
+       mdbgv_sensor("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(error %d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_sen_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_sen_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       /*dbg_sensor("%s\n", __func__);*/
+#endif
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_sen_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       bool blocking;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_sensor("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret) {
+               blocking = file->f_flags & O_NONBLOCK;
+               if (!blocking || (ret != -EAGAIN))
+                       merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+       }
+
+       return ret;
+}
+
+static int fimc_is_sen_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_sen_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_sen_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo: add to enumerate input code */
+       info("%s is calld\n", __func__);
+       return 0;
+}
+
+static int fimc_is_sen_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       /* Todo: add to get input control code */
+       return 0;
+}
+
+static int fimc_is_sen_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       int ret = 0;
+       u32 scenario;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_sensor *device;
+       struct fimc_is_framemgr *framemgr;
+
+       BUG_ON(!vctx);
+
+       mdbgv_sensor("%s(input : %08X)\n", vctx, __func__, input);
+
+       device = vctx->device;
+       framemgr = GET_DST_FRAMEMGR(vctx);
+       scenario = (input & SENSOR_SCENARIO_MASK) >> SENSOR_SCENARIO_SHIFT;
+       input = (input & SENSOR_MODULE_MASK) >> SENSOR_MODULE_SHIFT;
+
+       ret = fimc_is_sensor_s_input(device, input, scenario);
+       if (ret) {
+               merr("fimc_is_sensor_s_input is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sen_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_sensor *device;
+       struct v4l2_subdev *subdev_flite;
+
+       BUG_ON(!ctrl);
+       BUG_ON(!vctx);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       subdev_flite = device->subdev_flite;
+       if (!subdev_flite) {
+               err("subdev_flite is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_S_STREAM:
+               {
+                       u32 sstream, instant, noblock;
+
+                       sstream = (ctrl->value & SENSOR_SSTREAM_MASK) >> SENSOR_SSTREAM_SHIFT;
+                       instant = (ctrl->value & SENSOR_INSTANT_MASK) >> SENSOR_INSTANT_SHIFT;
+                       noblock = (ctrl->value & SENSOR_NOBLOCK_MASK) >> SENSOR_NOBLOCK_SHIFT;
+                       /*
+                        * nonblock(0) : blocking command
+                        * nonblock(1) : non-blocking command
+                        */
+
+                       if (sstream == IS_ENABLE_STREAM) {
+                               ret = fimc_is_sensor_front_start(device, instant, noblock);
+                               if (ret) {
+                                       merr("fimc_is_sensor_front_start is fail(%d)", device, ret);
+                                       goto p_err;
+                               }
+                       } else {
+                               ret = fimc_is_sensor_front_stop(device);
+                               if (ret) {
+                                       merr("fimc_is_sensor_front_stop is fail(%d)", device, ret);
+                                       goto p_err;
+                               }
+                       }
+               }
+               break;
+       case V4L2_CID_IS_S_BNS:
+               if (device->pdata->is_bns == false) {
+                       mwarn("Could not support BNS\n", device);
+                       goto p_err;
+               }
+
+               ret = fimc_is_sensor_s_bns(device, ctrl->value);
+               if (ret) {
+                       merr("fimc_is_sensor_s_bns is fail(%d)", device, ret);
+                       goto p_err;
+               }
+
+               ret = v4l2_subdev_call(subdev_flite, core, s_ctrl, ctrl);
+               if (ret) {
+                       merr("v4l2_flite_call(s_ctrl) is fail(%d)", device, ret);
+                       goto p_err;
+               }
+               break;
+       /*
+        * gain boost: min_target_fps,  max_target_fps, scene_mode
+        */
+       case V4L2_CID_IS_MIN_TARGET_FPS:
+               if (test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state)) {
+                       err("failed to set min_target_fps: %d - sensor stream on already\n",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->min_target_fps = ctrl->value;
+               }
+               break;
+       case V4L2_CID_IS_MAX_TARGET_FPS:
+               if (test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state)) {
+                       err("failed to set max_target_fps: %d - sensor stream on already\n",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->max_target_fps = ctrl->value;
+               }
+               break;
+       case V4L2_CID_SCENEMODE:
+               if (test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state)) {
+                       err("failed to set scene_mode: %d - sensor stream on already\n",
+                                       ctrl->value);
+                       ret = -EINVAL;
+               } else {
+                       device->scene_mode = ctrl->value;
+               }
+               break;
+       case V4L2_CID_SENSOR_SET_FRAME_RATE:
+               if (fimc_is_sensor_s_frame_duration(device, ctrl->value)) {
+                       err("failed to set frame duration : %d\n - %d",
+                                       ctrl->value, ret);
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_SENSOR_SET_AE_TARGET:
+               if (fimc_is_sensor_s_exposure_time(device, ctrl->value)) {
+                       err("failed to set exposure time : %d\n - %d",
+                                       ctrl->value, ret);
+                       ret = -EINVAL;
+               }
+               break;
+       default:
+               ret = fimc_is_sensor_s_ctrl(device, ctrl);
+               if (ret) {
+                       err("invalid ioctl(0x%08X) is requested", ctrl->id);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sen_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_G_STREAM:
+               if (device->instant_ret)
+                       ctrl->value = device->instant_ret;
+               else
+                       ctrl->value = (test_bit(FIMC_IS_SENSOR_FRONT_START, &device->state) ?
+                               IS_ENABLE_STREAM : IS_DISABLE_STREAM);
+               break;
+       case V4L2_CID_IS_G_BNS_SIZE:
+               {
+                       u32 width, height;
+
+                       width = fimc_is_sensor_g_bns_width(device);
+                       height = fimc_is_sensor_g_bns_height(device);
+
+                       ctrl->value = (width << 16) | height;
+               }
+               break;
+       case V4L2_CID_IS_G_DTPSTATUS:
+               if (test_bit(FIMC_IS_SENSOR_FRONT_DTP_STOP, &device->state))
+                       ctrl->value = 1;
+               else
+                       ctrl->value = 0;
+               break;
+       default:
+               ret = fimc_is_sensor_g_ctrl(device, ctrl);
+               if (ret) {
+                       err("invalid ioctl(0x%08X) is requested", ctrl->id);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_sen_video_g_parm(struct file *file, void *priv,
+       struct v4l2_streamparm *parm)
+{
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_sensor *device = vctx->device;
+       struct v4l2_captureparm *cp = &parm->parm.capture;
+       struct v4l2_fract *tfp = &cp->timeperframe;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return -EINVAL;
+
+       cp->capability |= V4L2_CAP_TIMEPERFRAME;
+       tfp->numerator = 1;
+       tfp->denominator = device->image.framerate;
+
+       return 0;
+}
+
+static int fimc_is_sen_video_s_parm(struct file *file, void *priv,
+       struct v4l2_streamparm *parm)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!vctx);
+       BUG_ON(!parm);
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_s_framerate(device, parm);
+       if (ret) {
+               merr("fimc_is_sen_s_framerate is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_is_sen_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_sen_video_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_sen_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_sen_video_get_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_sen_video_set_format_mplane,
+       .vidioc_cropcap                 = fimc_is_sen_video_cropcap,
+       .vidioc_g_crop                  = fimc_is_sen_video_get_crop,
+       .vidioc_s_crop                  = fimc_is_sen_video_set_crop,
+       .vidioc_reqbufs                 = fimc_is_sen_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_sen_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_sen_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_sen_video_dqbuf,
+       .vidioc_streamon                = fimc_is_sen_video_streamon,
+       .vidioc_streamoff               = fimc_is_sen_video_streamoff,
+       .vidioc_enum_input              = fimc_is_sen_video_enum_input,
+       .vidioc_g_input                 = fimc_is_sen_video_g_input,
+       .vidioc_s_input                 = fimc_is_sen_video_s_input,
+       .vidioc_s_ctrl                  = fimc_is_sen_video_s_ctrl,
+       .vidioc_g_ctrl                  = fimc_is_sen_video_g_ctrl,
+       .vidioc_g_parm                  = fimc_is_sen_video_g_parm,
+       .vidioc_s_parm                  = fimc_is_sen_video_s_parm,
+};
+
+static int fimc_is_sen_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers, unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_sen_buffer_prepare(struct vb2_buffer *vb)
+{
+       return 0;
+}
+
+static inline void fimc_is_sen_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_sen_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_sen_start_streaming(struct vb2_queue *q,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+
+       if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state) &&
+               test_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state)) {
+               set_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
+               fimc_is_sensor_back_start(device);
+       } else {
+               err("already stream on or buffer is not ready(%ld)",
+                       queue->state);
+               clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+               clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+               fimc_is_sensor_back_stop(device);
+               ret = -EINVAL;
+       }
+
+       return 0;
+}
+
+static int fimc_is_sen_stop_streaming(struct vb2_queue *q)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_sensor *device;
+
+       BUG_ON(!vctx);
+
+       mdbgv_sensor("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+
+       if (test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               clear_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
+               clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+               clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+               ret = fimc_is_sensor_back_stop(device);
+       } else {
+               err("already stream off");
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static void fimc_is_sen_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_video *video;
+       struct fimc_is_device_sensor *device;
+
+#ifdef DBG_STREAMING
+       mdbgv_sensor("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       video = vctx->video;
+       if (!video) {
+               merr("video is NULL", device);
+               return;
+       }
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", device, ret);
+               return;
+       }
+
+       ret = fimc_is_sensor_buffer_queue(device, vb->v4l2_buf.index);
+       if (ret) {
+               merr("fimc_is_sensor_buffer_queue is fail(%d)", device, ret);
+               return;
+       }
+}
+
+static int fimc_is_sen_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_sensor *device;
+
+#ifdef DBG_STREAMING
+       mdbgv_sensor("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+       device = vctx->device;
+
+       ret = fimc_is_sensor_buffer_finish(
+               device,
+               vb->v4l2_buf.index);
+       if (ret) {
+               merr("fimc_is_sensor_buffer_finish is fail(%d)", device, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+const struct vb2_ops fimc_is_sen_qops = {
+       .queue_setup            = fimc_is_sen_queue_setup,
+       .buf_prepare            = fimc_is_sen_buffer_prepare,
+       .buf_queue              = fimc_is_sen_buffer_queue,
+       .buf_finish             = fimc_is_sen_buffer_finish,
+       .wait_prepare           = fimc_is_sen_wait_prepare,
+       .wait_finish            = fimc_is_sen_wait_finish,
+       .start_streaming        = fimc_is_sen_start_streaming,
+       .stop_streaming         = fimc_is_sen_stop_streaming,
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-vdisc.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-vdisc.c
new file mode 100644 (file)
index 0000000..afe74ba
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+
+const struct v4l2_file_operations fimc_is_vdc_video_fops;
+const struct v4l2_ioctl_ops fimc_is_vdc_video_ioctl_ops;
+const struct vb2_ops fimc_is_vdc_qops;
+
+int fimc_is_vdc_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_vdc;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_VDC_NAME,
+               FIMC_IS_VIDEO_VDC_NUM,
+               VFL_DIR_RX,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_vdc_video_fops,
+               &fimc_is_vdc_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_vdc_video_open(struct file *file)
+{
+       int ret = 0;
+       u32 refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       core = container_of(video, struct fimc_is_core, video_vdc);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_INVALID, FRAMEMGR_ID_DIS);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[VDC:V:%d] %s\n", vctx->instance, __func__);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount > FIMC_IS_MAX_NODES || refcount < 1) {
+               err("invalid ischain refcount(%d)", refcount);
+               close_vctx(file, video, vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = &core->ischain[refcount - 1];
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_VDISC_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_CAPTURE,
+               &fimc_is_vdc_qops,
+               NULL,
+               &fimc_is_ischain_sub_ops);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_subdev_open(&device->dis, vctx, NULL);
+       if (ret) {
+               err("fimc_is_subdev_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_vdc_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               merr("video is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[VDC:V:%d] %s\n", vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_subdev_close(&device->dis);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_vdc_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+       if (ret)
+               merr("fimc_is_video_poll is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_querycap(struct file *file, void *fh,
+       struct v4l2_capability *cap)
+{
+       struct fimc_is_core *core = video_drvdata(file);
+
+       dbg_vdisc("%s(devname : %s)\n", __func__, core->pdev->name);
+
+       strncpy(cap->driver, core->pdev->name, sizeof(cap->driver) - 1);
+       strncpy(cap->card, core->pdev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_STREAMING
+               | V4L2_CAP_VIDEO_CAPTURE
+               | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+       return 0;
+}
+
+static int fimc_is_vdc_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       /* Todo: add enum format control code */
+       return 0;
+}
+
+static int fimc_is_vdc_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       /* Todo: add get format control code */
+       return 0;
+}
+
+static int fimc_is_vdc_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue = vctx->q_dst;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret)
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+
+       dbg_vdisc("req w : %d req h : %d\n",
+               queue->framecfg.width,
+               queue->framecfg.height);
+
+       fimc_is_ischain_vdc_s_format(ischain,
+               queue->framecfg.width,
+               queue->framecfg.height);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_set_crop(struct file *file, void *fh,
+       struct v4l2_crop *crop)
+{
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *ischain;
+
+       BUG_ON(!vctx);
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       ischain = vctx->device;
+       BUG_ON(!ischain);
+
+       fimc_is_ischain_vdc_s_format(ischain,
+               crop->c.width, crop->c.height);
+
+       return 0;
+}
+
+static int fimc_is_vdc_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_vdc("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       device = vctx->device;
+       subdev = &device->dis;
+       leader = subdev->leader;
+
+       if (!leader) {
+               merr("leader is NULL ptr", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (test_bit(FIMC_IS_SUBDEV_START, &leader->state)) {
+               merr("leader still running, not applied", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_vdc_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_vdc("%s(index : %d)\n", vctx, __func__, buf->index);
+#endif
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_vdc("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_streamon(struct file *file, void *priv,
+                                               enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_enum_input(struct file *file, void *priv,
+       struct v4l2_input *input)
+{
+       /* Todo : add to enum input control code */
+       return 0;
+}
+
+static int fimc_is_vdc_video_g_input(struct file *file, void *priv,
+                                               unsigned int *input)
+{
+       /* Todo: add get input control code */
+       return 0;
+}
+
+static int fimc_is_vdc_video_s_input(struct file *file, void *priv,
+                                       unsigned int input)
+{
+       /* Todo: add set input control code */
+       return 0;
+}
+
+static int fimc_is_vdc_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_framemgr *framemgr = &vctx->q_dst->framemgr;
+
+       dbg_vdisc("%s\n", __func__);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_G_COMPLETES:
+               ctrl->value = framemgr->frame_com_cnt;
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int fimc_is_vdc_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       /* Todo: add get extra control code */
+       return 0;
+}
+
+static int fimc_is_vdc_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       int ret = 0;
+       unsigned long flags;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       BUG_ON(!vctx);
+       BUG_ON(!ctrl);
+
+       dbg_vdisc("%s\n", __func__);
+
+       framemgr = GET_DST_FRAMEMGR(vctx);
+
+       switch (ctrl->id) {
+       case V4L2_CID_IS_FORCE_DONE:
+               if (framemgr->frame_pro_cnt) {
+                       err("force done can be performed(process count %d)",
+                               framemgr->frame_pro_cnt);
+                       ret = -EINVAL;
+               } else if (!framemgr->frame_req_cnt) {
+                       err("force done can be performed(request count %d)",
+                               framemgr->frame_req_cnt);
+                       ret = -EINVAL;
+               } else {
+                       framemgr_e_barrier_irqs(framemgr, 0, flags);
+
+                       fimc_is_frame_request_head(framemgr, &frame);
+                       if (frame) {
+                               fimc_is_frame_trans_req_to_com(framemgr, frame);
+                               buffer_done(vctx, frame->index);
+                       } else {
+                               err("frame is NULL");
+                               ret = -EINVAL;
+                       }
+
+                       framemgr_x_barrier_irqr(framemgr, 0, flags);
+               }
+               break;
+       default:
+               err("unsupported ioctl(%d)\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_vdc_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_vdc_video_open,
+       .release        = fimc_is_vdc_video_close,
+       .poll           = fimc_is_vdc_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_vdc_video_mmap,
+};
+
+const struct v4l2_ioctl_ops fimc_is_vdc_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_vdc_video_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = fimc_is_vdc_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = fimc_is_vdc_video_get_format_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = fimc_is_vdc_video_set_format_mplane,
+       .vidioc_s_crop                  = fimc_is_vdc_video_set_crop,
+       .vidioc_reqbufs                 = fimc_is_vdc_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_vdc_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_vdc_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_vdc_video_dqbuf,
+       .vidioc_streamon                = fimc_is_vdc_video_streamon,
+       .vidioc_streamoff               = fimc_is_vdc_video_streamoff,
+       .vidioc_enum_input              = fimc_is_vdc_video_enum_input,
+       .vidioc_g_input                 = fimc_is_vdc_video_g_input,
+       .vidioc_s_input                 = fimc_is_vdc_video_s_input,
+       .vidioc_g_ctrl                  = fimc_is_vdc_video_g_ctrl,
+       .vidioc_s_ctrl                  = fimc_is_vdc_video_s_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_vdc_video_g_ext_ctrl,
+};
+
+static int fimc_is_vdc_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_buffer_prepare(struct vb2_buffer *vb)
+{
+       /* Todo: add buffer prepare control code */
+       return 0;
+}
+
+static inline void fimc_is_vdc_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_vdc_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_vdc_start_streaming(struct vb2_queue *q,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       subdev = &device->dis;
+
+       ret = fimc_is_queue_start_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdc_stop_streaming(struct vb2_queue *q)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *subdev;
+
+       BUG_ON(!vctx);
+
+       mdbgv_vdc("%s\n", vctx, __func__);
+
+       queue = GET_DST_QUEUE(vctx);
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+       subdev = &device->dis;
+
+       ret = fimc_is_queue_stop_streaming(queue, device, subdev, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static void fimc_is_vdc_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue = vctx->q_dst;
+       struct fimc_is_video *video = vctx->video;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+       struct fimc_is_subdev *subdev = &ischain->dis;
+
+#ifdef DBG_STREAMING
+       dbg_vdisc("%s\n", __func__);
+#endif
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+
+       ret = fimc_is_subdev_buffer_queue(subdev, vb->v4l2_buf.index);
+       if (ret) {
+               merr("fimc_is_subdev_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+}
+
+static int fimc_is_vdc_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *ischain = vctx->device;
+       struct fimc_is_subdev *dis = &ischain->dis;
+
+#ifdef DBG_STREAMING
+       dbg_vdisc("%s(%d)\n", __func__, vb->v4l2_buf.index);
+#endif
+
+       ret = fimc_is_subdev_buffer_finish(dis, vb->v4l2_buf.index);
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_vdc_qops = {
+       .queue_setup            = fimc_is_vdc_queue_setup,
+       .buf_prepare            = fimc_is_vdc_buffer_prepare,
+       .buf_queue              = fimc_is_vdc_buffer_queue,
+       .buf_finish             = fimc_is_vdc_buffer_finish,
+       .wait_prepare           = fimc_is_vdc_wait_prepare,
+       .wait_finish            = fimc_is_vdc_wait_finish,
+       .start_streaming        = fimc_is_vdc_start_streaming,
+       .stop_streaming         = fimc_is_vdc_stop_streaming,
+};
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video-vdiso.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video-vdiso.c
new file mode 100644 (file)
index 0000000..3270f82
--- /dev/null
@@ -0,0 +1,586 @@
+/*
+ * Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+#include "fimc-is-video.h"
+#include "fimc-is-metadata.h"
+
+const struct v4l2_file_operations fimc_is_vdo_video_fops;
+const struct v4l2_ioctl_ops fimc_is_vdo_video_ioctl_ops;
+const struct vb2_ops fimc_is_vdo_qops;
+
+int fimc_is_vdo_video_probe(void *data)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+
+       BUG_ON(!data);
+
+       core = (struct fimc_is_core *)data;
+       video = &core->video_vdo;
+
+       if (!core->pdev) {
+               err("pdev is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_probe(video,
+               FIMC_IS_VIDEO_VDO_NAME,
+               FIMC_IS_VIDEO_VDO_NUM,
+               VFL_DIR_TX,
+               &core->mem,
+               &core->v4l2_dev,
+               &video->lock,
+               &fimc_is_vdo_video_fops,
+               &fimc_is_vdo_video_ioctl_ops);
+       if (ret)
+               dev_err(&core->pdev->dev, "%s is fail(%d)\n", __func__, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_vdo_video_open(struct file *file)
+{
+       int ret = 0;
+       u32 refcount;
+       struct fimc_is_core *core;
+       struct fimc_is_video *video;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_device_ischain *device;
+
+       vctx = NULL;
+       video = video_drvdata(file);
+       core = container_of(video, struct fimc_is_core, video_vdo);
+
+       ret = open_vctx(file, video, &vctx, FRAMEMGR_ID_DIS_GRP, FRAMEMGR_ID_INVALID);
+       if (ret) {
+               err("open_vctx is fail(%d)", ret);
+               goto p_err;
+       }
+
+       info("[VDO:V:%d] %s\n", vctx->instance, __func__);
+
+       refcount = atomic_read(&core->video_isp.refcount);
+       if (refcount > FIMC_IS_MAX_NODES || refcount < 1) {
+               err("invalid ischain refcount(%d)", refcount);
+               close_vctx(file, video, vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       device = &core->ischain[refcount - 1];
+
+       ret = fimc_is_video_open(vctx,
+               device,
+               VIDEO_VDISO_READY_BUFFERS,
+               video,
+               FIMC_IS_VIDEO_TYPE_OUTPUT,
+               &fimc_is_vdo_qops,
+               &fimc_is_ischain_vdo_ops,
+               &fimc_is_ischain_sub_ops);
+       if (ret) {
+               err("fimc_is_video_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+       ret = fimc_is_ischain_vdo_open(device, vctx);
+       if (ret) {
+               err("fimc_is_ischain_vdo_open is fail");
+               close_vctx(file, video, vctx);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_vdo_video_close(struct file *file)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = NULL;
+       struct fimc_is_video *video;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!file);
+
+       vctx = file->private_data;
+       if (!vctx) {
+               err("vctx is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       video = vctx->video;
+       if (!video) {
+               err("video is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       info("[VDO:V:%d] %s\n", vctx->instance, __func__);
+
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       fimc_is_ischain_vdo_close(device, vctx);
+       fimc_is_video_close(vctx);
+
+       ret = close_vctx(file, video, vctx);
+       if (ret < 0)
+               err("close_vctx is fail(%d)", ret);
+
+p_err:
+       return ret;
+}
+
+static unsigned int fimc_is_vdo_video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_poll(file, vctx, wait);
+       if (ret)
+               merr("fimc_is_video_poll is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_mmap(struct file *file,
+       struct vm_area_struct *vma)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       ret = fimc_is_video_mmap(file, vctx, vma);
+       if (ret)
+               merr("fimc_is_video_mmap is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+const struct v4l2_file_operations fimc_is_vdo_video_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fimc_is_vdo_video_open,
+       .release        = fimc_is_vdo_video_close,
+       .poll           = fimc_is_vdo_video_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = fimc_is_vdo_video_mmap,
+};
+
+static int fimc_is_vdo_video_querycap(struct file *file, void *fh,
+                                       struct v4l2_capability *cap)
+{
+       struct fimc_is_core *core = video_drvdata(file);
+
+       strncpy(cap->driver, core->pdev->name, sizeof(cap->driver) - 1);
+
+       dbg_vdiso("%s(devname : %s)\n", __func__, cap->driver);
+       strncpy(cap->card, core->pdev->name, sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->capabilities = V4L2_CAP_STREAMING
+                               | V4L2_CAP_VIDEO_CAPTURE
+                               | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+
+       return 0;
+}
+
+static int fimc_is_vdo_video_enum_fmt_mplane(struct file *file, void *priv,
+       struct v4l2_fmtdesc *f)
+{
+       /* Todo: add enum format control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_get_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       /* Todo: add get format control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_set_format_mplane(struct file *file, void *fh,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_set_format_mplane(file, vctx, format);
+       if (ret)
+               merr("fimc_is_video_set_format_mplane is fail(%d)", vctx, ret);
+
+       dbg_vdiso("req w : %d req h : %d\n",
+               vctx->q_src->framecfg.width,
+               vctx->q_src->framecfg.height);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdo("%s(buffers : %d)\n", vctx, __func__, buf->count);
+
+       ret = fimc_is_video_reqbufs(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_reqbufs is fail(error %d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_querybuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_querybuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+       struct fimc_is_queue *queue;
+
+#ifdef DBG_STREAMING
+       dbg_vdiso("%s\n", __func__);
+#endif
+
+       queue = GET_SRC_QUEUE(vctx);
+
+       if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               merr("stream off state, can NOT qbuf", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_video_qbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_qbuf is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static int fimc_is_vdo_video_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+#ifdef DBG_STREAMING
+       mdbgv_vdo("%s\n", vctx, __func__);
+#endif
+
+       ret = fimc_is_video_dqbuf(file, vctx, buf);
+       if (ret)
+               merr("fimc_is_video_dqbuf is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamon(file, vctx, type);
+       if (ret)
+               merr("fimc_is_vdo_video_streamon is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = file->private_data;
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       ret = fimc_is_video_streamoff(file, vctx, type);
+       if (ret)
+               merr("fimc_is_video_streamoff is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_video_enum_input(struct file *file, void *priv,
+                                               struct v4l2_input *input)
+{
+       /* Todo : add to enum input control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_g_input(struct file *file, void *priv,
+       unsigned int *input)
+{
+       /* Todo: add get input control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_s_input(struct file *file, void *priv,
+       unsigned int input)
+{
+       /* Todo: add set input control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       /* Todo: add set control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctrl)
+{
+       /* Todo: add get control code */
+       return 0;
+}
+
+static int fimc_is_vdo_video_g_ext_ctrl(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       /* Todo: add get extra control code */
+       return 0;
+}
+
+const struct v4l2_ioctl_ops fimc_is_vdo_video_ioctl_ops = {
+       .vidioc_querycap                = fimc_is_vdo_video_querycap,
+       .vidioc_enum_fmt_vid_out_mplane = fimc_is_vdo_video_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_out_mplane    = fimc_is_vdo_video_get_format_mplane,
+       .vidioc_s_fmt_vid_out_mplane    = fimc_is_vdo_video_set_format_mplane,
+       .vidioc_reqbufs                 = fimc_is_vdo_video_reqbufs,
+       .vidioc_querybuf                = fimc_is_vdo_video_querybuf,
+       .vidioc_qbuf                    = fimc_is_vdo_video_qbuf,
+       .vidioc_dqbuf                   = fimc_is_vdo_video_dqbuf,
+       .vidioc_streamon                = fimc_is_vdo_video_streamon,
+       .vidioc_streamoff               = fimc_is_vdo_video_streamoff,
+       .vidioc_enum_input              = fimc_is_vdo_video_enum_input,
+       .vidioc_g_input                 = fimc_is_vdo_video_g_input,
+       .vidioc_s_input                 = fimc_is_vdo_video_s_input,
+       .vidioc_s_ctrl                  = fimc_is_vdo_video_s_ctrl,
+       .vidioc_g_ctrl                  = fimc_is_vdo_video_g_ctrl,
+       .vidioc_g_ext_ctrls             = fimc_is_vdo_video_g_ext_ctrl,
+};
+
+static int fimc_is_vdo_queue_setup(struct vb2_queue *vbq,
+       const struct v4l2_format *fmt,
+       unsigned int *num_buffers, unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vbq->drv_priv;
+       struct fimc_is_video *video;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+
+       mdbgv_isp("%s\n", vctx, __func__);
+
+       queue = GET_SRC_QUEUE(vctx);
+       video = vctx->video;
+
+       ret = fimc_is_queue_setup(queue,
+               video->alloc_ctx,
+               num_planes,
+               sizes,
+               allocators);
+       if (ret)
+               merr("fimc_is_queue_setup is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_buffer_prepare(struct vb2_buffer *vb)
+{
+       /* Todo: add buffer prepare control code */
+       return 0;
+}
+
+static inline void fimc_is_vdo_wait_prepare(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_prepare(vbq);
+}
+
+static inline void fimc_is_vdo_wait_finish(struct vb2_queue *vbq)
+{
+       fimc_is_queue_wait_finish(vbq);
+}
+
+static int fimc_is_vdo_start_streaming(struct vb2_queue *q,
+       unsigned int count)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       queue = GET_SRC_QUEUE(vctx);
+       device = vctx->device;
+       leader = &device->group_dis.leader;
+
+       ret = fimc_is_queue_start_streaming(queue, device, leader, vctx);
+       if (ret)
+               merr("fimc_is_queue_start_streaming is fail(%d)", vctx, ret);
+
+       return ret;
+}
+
+static int fimc_is_vdo_stop_streaming(struct vb2_queue *q)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = q->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_device_ischain *device;
+       struct fimc_is_subdev *leader;
+
+       BUG_ON(!vctx);
+
+       mdbgv_vdo("%s\n", vctx, __func__);
+
+       queue = GET_SRC_QUEUE(vctx);
+       device = vctx->device;
+       if (!device) {
+               err("device is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+       leader = &device->group_dis.leader;
+
+       ret = fimc_is_queue_stop_streaming(queue, device, leader, vctx);
+       if (ret)
+               merr("fimc_is_queue_stop_streaming is fail(%d)", vctx, ret);
+
+p_err:
+       return ret;
+}
+
+static void fimc_is_vdo_buffer_queue(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       u32 index;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_queue *queue;
+       struct fimc_is_video *video;
+       struct fimc_is_device_ischain *device;
+
+       BUG_ON(!vctx);
+       index = vb->v4l2_buf.index;
+
+#ifdef DBG_STREAMING
+       dbg_vdiso("%s(%d)\n", __func__, index);
+#endif
+
+       queue = GET_SRC_QUEUE(vctx);
+       video = vctx->video;
+       device = vctx->device;
+
+       ret = fimc_is_queue_buffer_queue(queue, video->vb2, vb);
+       if (ret) {
+               merr("fimc_is_queue_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+
+       ret = fimc_is_ischain_vdo_buffer_queue(device, queue, index);
+       if (ret) {
+               merr("fimc_is_ischain_vdo_buffer_queue is fail(%d)", vctx, ret);
+               return;
+       }
+}
+
+static int fimc_is_vdo_buffer_finish(struct vb2_buffer *vb)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = vb->vb2_queue->drv_priv;
+       struct fimc_is_device_ischain *device = vctx->device;
+
+#ifdef DBG_STREAMING
+       mdbgv_vdo("%s(%d)\n", vctx, __func__, vb->v4l2_buf.index);
+#endif
+
+       ret = fimc_is_ischain_vdo_buffer_finish(device, vb->v4l2_buf.index);
+
+       return ret;
+}
+
+const struct vb2_ops fimc_is_vdo_qops = {
+       .queue_setup            = fimc_is_vdo_queue_setup,
+       .buf_prepare            = fimc_is_vdo_buffer_prepare,
+       .buf_queue              = fimc_is_vdo_buffer_queue,
+       .buf_finish             = fimc_is_vdo_buffer_finish,
+       .wait_prepare           = fimc_is_vdo_wait_prepare,
+       .wait_finish            = fimc_is_vdo_wait_finish,
+       .start_streaming        = fimc_is_vdo_start_streaming,
+       .stop_streaming         = fimc_is_vdo_stop_streaming,
+};
+
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video.c b/drivers/media/platform/exynos/fimc-is/fimc-is-video.c
new file mode 100644 (file)
index 0000000..70a1100
--- /dev/null
@@ -0,0 +1,1372 @@
+/*
+* Samsung Exynos5 SoC series FIMC-IS driver
+ *
+ * exynos5 fimc-is video functions
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/videonode.h>
+#include <media/exynos_mc.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_media.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/bug.h>
+
+#include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-mediabus.h>
+#include <media/exynos_mc.h>
+
+#include "fimc-is-time.h"
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-cmd.h"
+#include "fimc-is-regs.h"
+#include "fimc-is-err.h"
+
+#define SPARE_PLANE 1
+#define SPARE_SIZE (32 * 1024)
+
+struct fimc_is_fmt fimc_is_formats[] = {
+        {
+               .name           = "YUV 4:2:2 packed, YCbYCr",
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .num_planes     = 1 + SPARE_PLANE,
+               .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
+       }, {
+               .name           = "YUV 4:2:2 packed, CbYCrY",
+               .pixelformat    = V4L2_PIX_FMT_UYVY,
+               .num_planes     = 1 + SPARE_PLANE,
+               .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
+       }, {
+               .name           = "YUV 4:2:2 planar, Y/Cb/Cr",
+               .pixelformat    = V4L2_PIX_FMT_YUV422P,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 planar, YCbCr",
+               .pixelformat    = V4L2_PIX_FMT_YUV420,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 planar, YCbCr",
+               .pixelformat    = V4L2_PIX_FMT_YVU420,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 planar, Y/CbCr",
+               .pixelformat    = V4L2_PIX_FMT_NV12,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 planar, Y/CrCb",
+               .pixelformat    = V4L2_PIX_FMT_NV21,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
+               .pixelformat    = V4L2_PIX_FMT_NV12M,
+               .num_planes     = 2 + SPARE_PLANE,
+       }, {
+               .name           = "YVU 4:2:0 non-contiguous 2-planar, Y/CrCb",
+               .pixelformat    = V4L2_PIX_FMT_NV21M,
+               .num_planes     = 2 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
+               .pixelformat    = V4L2_PIX_FMT_YUV420M,
+               .num_planes     = 3 + SPARE_PLANE,
+       }, {
+               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb",
+               .pixelformat    = V4L2_PIX_FMT_YVU420M,
+               .num_planes     = 3 + SPARE_PLANE,
+       }, {
+               .name           = "BAYER 8 bit",
+               .pixelformat    = V4L2_PIX_FMT_SGRBG8,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "BAYER 10 bit",
+               .pixelformat    = V4L2_PIX_FMT_SBGGR10,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "BAYER 12 bit",
+               .pixelformat    = V4L2_PIX_FMT_SBGGR12,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "BAYER 16 bit",
+               .pixelformat    = V4L2_PIX_FMT_SBGGR16,
+               .num_planes     = 1 + SPARE_PLANE,
+       }, {
+               .name           = "JPEG",
+               .pixelformat    = V4L2_PIX_FMT_JPEG,
+               .num_planes     = 1 + SPARE_PLANE,
+               .mbus_code      = V4L2_MBUS_FMT_JPEG_1X8,
+       }
+};
+
+struct fimc_is_fmt *fimc_is_find_format(u32 *pixelformat,
+       u32 *mbus_code, int index)
+{
+       struct fimc_is_fmt *fmt, *def_fmt = NULL;
+       unsigned int i;
+
+       if (index >= ARRAY_SIZE(fimc_is_formats))
+               return NULL;
+
+       for (i = 0; i < ARRAY_SIZE(fimc_is_formats); ++i) {
+               fmt = &fimc_is_formats[i];
+               if (pixelformat && fmt->pixelformat == *pixelformat)
+                       return fmt;
+               if (mbus_code && fmt->mbus_code == *mbus_code)
+                       return fmt;
+               if (index == i)
+                       def_fmt = fmt;
+       }
+       return def_fmt;
+
+}
+
+int get_plane_size_flite(int width, int height)
+{
+    int PlaneSize;
+    int Alligned_Width;
+    int Bytes;
+
+    Alligned_Width = (width + 9) / 10 * 10;
+    Bytes = Alligned_Width * 8 / 5 ;
+
+    PlaneSize = Bytes * height;
+
+    return PlaneSize;
+}
+
+void fimc_is_set_plane_size(struct fimc_is_frame_cfg *frame, unsigned int sizes[])
+{
+       u32 plane;
+       u32 width[FIMC_IS_MAX_PLANES];
+
+       for (plane = 0; plane < FIMC_IS_MAX_PLANES; ++plane)
+               width[plane] = frame->width + frame->width_stride[plane];
+
+       switch (frame->format.pixelformat) {
+       case V4L2_PIX_FMT_YUYV:
+               dbg("V4L2_PIX_FMT_YUYV(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = width[0]*frame->height*2;
+               sizes[1] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_NV12:
+               dbg("V4L2_PIX_FMT_NV12(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = width[0] * frame->height * 3 / 2;
+               sizes[1] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_NV12M:
+               dbg("V4L2_PIX_FMT_NV12M(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = width[0]*frame->height;
+               sizes[1] = width[1]*frame->height/2;
+               sizes[2] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_NV21:
+               dbg("V4L2_PIX_FMT_NV21(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = width[0] * frame->height * 3 / 2;
+               sizes[1] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_NV21M:
+               dbg("V4L2_PIX_FMT_NV21M(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = width[0]*frame->height;
+               sizes[1] = width[1]*frame->height/2;
+               sizes[2] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               dbg("V4L2_PIX_FMT_YVU420M(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = width[0]*frame->height;
+               sizes[1] = width[1]*frame->height/4;
+               sizes[2] = width[2]*frame->height/4;
+               sizes[3] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_SGRBG8:
+               dbg("V4L2_PIX_FMT_SGRBG8(w:%d)(h:%d)\n", frame->width, frame->height);
+               sizes[0] = frame->width*frame->height;
+               sizes[1] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_SBGGR10:
+               dbg("V4L2_PIX_FMT_SBGGR10(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = get_plane_size_flite(frame->width,frame->height);
+               if (frame->bytesperline[0]) {
+                       if (frame->bytesperline[0] >= frame->width * 5 / 4) {
+                       sizes[0] = frame->bytesperline[0]
+                           * frame->height;
+                       } else {
+                               err("Bytesperline too small\
+                                       (fmt(V4L2_PIX_FMT_SBGGR10), W(%d), Bytes(%d))",
+                               frame->width,
+                               frame->bytesperline[0]);
+                       }
+               }
+               sizes[1] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_SBGGR16:
+               dbg("V4L2_PIX_FMT_SBGGR16(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = frame->width*frame->height*2;
+               if (frame->bytesperline[0]) {
+                       if (frame->bytesperline[0] >= frame->width * 2) {
+                               sizes[0] = frame->bytesperline[0]
+                                               * frame->height;
+                       } else {
+                               err("Bytesperline too small\
+                                       (fmt(V4L2_PIX_FMT_SBGGR16), W(%d), Bytes(%d))",
+                               frame->width,
+                               frame->bytesperline[0]);
+                       }
+               }
+               sizes[1] = SPARE_SIZE;
+               break;
+       case V4L2_PIX_FMT_SBGGR12:
+               dbg("V4L2_PIX_FMT_SBGGR12(w:%d)(h:%d)\n",
+                               frame->width, frame->height);
+               sizes[0] = get_plane_size_flite(frame->width,frame->height);
+               if (frame->bytesperline[0]) {
+                       if (frame->bytesperline[0] >= frame->width * 3 / 2) {
+                               sizes[0] = frame->bytesperline[0]
+                                               * frame->height;
+                       } else {
+                               err("Bytesperline too small\
+                               (fmt(V4L2_PIX_FMT_SBGGR12), W(%d), Bytes(%d))",
+                               frame->width,
+                               frame->bytesperline[0]);
+                       }
+               }
+               sizes[1] = SPARE_SIZE;
+               break;
+       default:
+               err("unknown pixelformat\n");
+               break;
+       }
+}
+
+static inline void vref_init(struct fimc_is_video *video)
+{
+       atomic_set(&video->refcount, 0);
+}
+
+static inline int vref_get(struct fimc_is_video *video)
+{
+       return atomic_inc_return(&video->refcount) - 1;
+}
+
+static inline int vref_put(struct fimc_is_video *video,
+       void (*release)(struct fimc_is_video *video))
+{
+       int ret = 0;
+
+       ret = atomic_sub_and_test(1, &video->refcount);
+       if (ret)
+               pr_debug("closed all instacne");
+
+       return atomic_read(&video->refcount);
+}
+
+static int queue_init(void *priv, struct vb2_queue *vbq_src,
+       struct vb2_queue *vbq_dst)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx = priv;
+
+       BUG_ON(!vctx);
+
+       if (vctx->type == FIMC_IS_VIDEO_TYPE_OUTPUT) {
+               BUG_ON(!vbq_src);
+
+               vbq_src->type           = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+               vbq_src->io_modes       = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+               vbq_src->drv_priv       = vctx;
+               vbq_src->ops            = vctx->vb2_ops;
+               vbq_src->mem_ops        = vctx->mem_ops;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
+               vbq_src->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+#endif
+               ret = vb2_queue_init(vbq_src);
+               if (ret) {
+                       err("vb2_queue_init fail");
+                       goto p_err;
+               }
+               vctx->q_src->vbq = vbq_src;
+       } else if (vctx->type == FIMC_IS_VIDEO_TYPE_CAPTURE) {
+               BUG_ON(!vbq_dst);
+
+               vbq_dst->type           = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+               vbq_dst->io_modes       = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+               vbq_dst->drv_priv       = vctx;
+               vbq_dst->ops            = vctx->vb2_ops;
+               vbq_dst->mem_ops        = vctx->mem_ops;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
+               vbq_dst->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+#endif
+               ret = vb2_queue_init(vbq_dst);
+               if (ret) {
+                       err("vb2_queue_init fail");
+                       goto p_err;
+               }
+               vctx->q_dst->vbq = vbq_dst;
+       } else if (vctx->type == FIMC_IS_VIDEO_TYPE_M2M) {
+               BUG_ON(!vbq_src);
+               BUG_ON(!vbq_dst);
+
+               vbq_src->type           = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+               vbq_src->io_modes       = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+               vbq_src->drv_priv       = vctx;
+               vbq_src->ops            = vctx->vb2_ops;
+               vbq_src->mem_ops        = vctx->mem_ops;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
+               vbq_src->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+#endif
+               ret = vb2_queue_init(vbq_src);
+               if (ret) {
+                       err("vb2_queue_init fail");
+                       goto p_err;
+               }
+               vctx->q_src->vbq = vbq_src;
+
+               vbq_dst->type           = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+               vbq_dst->io_modes       = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+               vbq_dst->drv_priv       = vctx;
+               vbq_dst->ops            = vctx->vb2_ops;
+               vbq_dst->mem_ops        = vctx->mem_ops;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
+               vbq_dst->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+#endif
+               ret = vb2_queue_init(vbq_dst);
+               if (ret) {
+                       err("vb2_queue_init fail");
+                       goto p_err;
+               }
+               vctx->q_dst->vbq = vbq_dst;
+       } else {
+               merr("video type is invalid(%d)", vctx, vctx->type);
+               ret = -EINVAL;
+       }
+
+p_err:
+       return ret;
+}
+
+int open_vctx(struct file *file,
+       struct fimc_is_video *video,
+       struct fimc_is_video_ctx **vctx,
+       u32 id_src, u32 id_dst)
+{
+       int ret = 0;
+       struct fimc_is_queue *q_src = NULL;
+       struct fimc_is_queue *q_dst = NULL;
+
+       BUG_ON(!file);
+       BUG_ON(!video);
+
+       if (atomic_read(&video->refcount) > FIMC_IS_MAX_NODES) {
+               err("can't open vctx, refcount is invalid");
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       *vctx = kzalloc(sizeof(struct fimc_is_video_ctx), GFP_KERNEL);
+       if (*vctx == NULL) {
+               err("kzalloc is fail");
+               ret = -ENOMEM;
+               *vctx = NULL;
+               goto exit;
+       }
+
+       q_src = kzalloc(sizeof(struct fimc_is_queue), GFP_KERNEL);
+       if (q_src == NULL) {
+               err("kzalloc is fail(q_src)");
+               ret = -ENOMEM;
+               kfree(*vctx);
+               *vctx = NULL;
+               goto exit;
+       }
+
+       q_dst = kzalloc(sizeof(struct fimc_is_queue), GFP_KERNEL);
+       if (q_dst == NULL) {
+               err("kzalloc is fail(q_dst)");
+               ret = -ENOMEM;
+               kfree(*vctx);
+               kfree(q_src);
+               *vctx = NULL;
+               goto exit;
+       }
+
+       (*vctx)->instance = vref_get(video);
+       (*vctx)->q_src = q_src;
+       (*vctx)->q_dst = q_dst;
+       (*vctx)->q_src->id = id_src;
+       (*vctx)->q_dst->id = id_dst;
+
+       file->private_data = *vctx;
+
+exit:
+       return ret;
+}
+
+int close_vctx(struct file *file,
+       struct fimc_is_video *video,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+
+       kfree(vctx->q_src);
+       kfree(vctx->q_dst);
+       kfree(vctx);
+       file->private_data = NULL;
+       ret = vref_put(video, NULL);
+
+       return ret;
+}
+
+/*
+ * =============================================================================
+ * Queue Opertation
+ * =============================================================================
+ */
+
+static int fimc_is_queue_open(struct fimc_is_queue *queue,
+       u32 rdycount)
+{
+       int ret = 0;
+
+       queue->buf_maxcount = 0;
+       queue->buf_refcount = 0;
+       queue->buf_rdycount = rdycount;
+       clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+       clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+       clear_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
+       memset(&queue->framecfg, 0, sizeof(struct fimc_is_frame_cfg));
+       fimc_is_frame_probe(&queue->framemgr, queue->id);
+
+       return ret;
+}
+
+static int fimc_is_queue_close(struct fimc_is_queue *queue)
+{
+       int ret = 0;
+
+       queue->buf_maxcount = 0;
+       queue->buf_refcount = 0;
+       clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+       clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+       clear_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
+       fimc_is_frame_close(&queue->framemgr);
+
+       return ret;
+}
+
+static int fimc_is_queue_set_format_mplane(struct fimc_is_queue *queue,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       u32 plane;
+       struct v4l2_pix_format_mplane *pix;
+       struct fimc_is_fmt *fmt;
+
+       pix = &format->fmt.pix_mp;
+       fmt = fimc_is_find_format(&pix->pixelformat, NULL, 0);
+       if (!fmt) {
+               err("pixel format is not found\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       queue->framecfg.format.pixelformat      = fmt->pixelformat;
+       queue->framecfg.format.mbus_code        = fmt->mbus_code;
+       queue->framecfg.format.num_planes       = fmt->num_planes;
+       queue->framecfg.width                   = pix->width;
+       queue->framecfg.height                  = pix->height;
+
+       for (plane = 0; plane < fmt->num_planes; ++plane) {
+               if (pix->plane_fmt[plane].bytesperline) {
+                       queue->framecfg.bytesperline[plane] =
+                               pix->plane_fmt[plane].bytesperline;
+                       queue->framecfg.width_stride[plane] =
+                               pix->plane_fmt[plane].bytesperline - pix->width;
+               } else {
+                       queue->framecfg.bytesperline[plane] = 0;
+                       queue->framecfg.width_stride[plane] = 0;
+               }
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_queue_setup(struct fimc_is_queue *queue,
+       void *alloc_ctx,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[])
+{
+       u32 ret = 0;
+       u32 plane;
+
+       BUG_ON(!queue);
+       BUG_ON(!alloc_ctx);
+       BUG_ON(!num_planes);
+       BUG_ON(!sizes);
+       BUG_ON(!allocators);
+
+       *num_planes = (unsigned int)(queue->framecfg.format.num_planes);
+       fimc_is_set_plane_size(&queue->framecfg, sizes);
+
+       for (plane = 0; plane < *num_planes; plane++) {
+               allocators[plane] = alloc_ctx;
+               queue->framecfg.size[plane] = sizes[plane];
+               mdbgv_vid("queue[%d] size : %d\n", plane, sizes[plane]);
+       }
+
+       return ret;
+}
+
+int fimc_is_queue_buffer_queue(struct fimc_is_queue *queue,
+       const struct fimc_is_vb2 *vb2,
+       struct vb2_buffer *vb)
+{
+       u32 ret = 0, i;
+       u32 index;
+       u32 ext_size;
+       u32 spare;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_frame *frame;
+
+       index = vb->v4l2_buf.index;
+       framemgr = &queue->framemgr;
+
+       BUG_ON(framemgr->id == FRAMEMGR_ID_INVALID);
+
+       for (i = 0; i < vb->num_planes; i++)
+               queue->buf_dva[index][i] = vb2->plane_addr(vb, i);
+
+       frame = &framemgr->frame[index];
+
+       /* uninitialized frame need to get info */
+       if (!test_bit(FRAME_INI_MEM, &frame->memory))
+               goto set_info;
+
+       /* plane count check */
+       if (frame->planes != vb->num_planes) {
+               err("plane count is changed(%08X != %08X)",
+                       frame->planes, vb->num_planes);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       /* plane address check */
+       for (i = 0; i < frame->planes; i++) {
+               if (frame->dvaddr_buffer[i] != queue->buf_dva[index][i]) {
+                       err("buffer %d plane %d is changed(%08X != %08X)",
+                               index, i,
+                               frame->dvaddr_buffer[i],
+                               queue->buf_dva[index][i]);
+                       ret = -EINVAL;
+                       goto exit;
+               }
+       }
+
+       goto exit;
+
+set_info:
+       if (test_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state)) {
+               err("already prepared but new index(%d) is came", index);
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       frame->vb = vb;
+       frame->planes = vb->num_planes;
+       spare = frame->planes - 1;
+
+       for (i = 0; i < frame->planes; i++) {
+               frame->dvaddr_buffer[i] = queue->buf_dva[index][i];
+#ifdef PRINT_BUFADDR
+               info("%04X %d.%d %08X\n", framemgr->id, index, i, frame->dvaddr_buffer[i]);
+#endif
+       }
+
+       if (framemgr->id & FRAMEMGR_ID_SHOT) {
+               ext_size = sizeof(struct camera2_shot_ext) - sizeof(struct camera2_shot);
+
+               /* Create Kvaddr for Metadata */
+               queue->buf_kva[index][spare] = vb2->plane_kvaddr(vb, spare);
+               if (!queue->buf_kva[index][spare]) {
+                       err("plane_kvaddr is fail(%08X)", framemgr->id);
+                       ret = -EINVAL;
+                       goto exit;
+               }
+
+               frame->dvaddr_shot = queue->buf_dva[index][spare] + ext_size;
+               frame->kvaddr_shot = queue->buf_kva[index][spare] + ext_size;
+               frame->cookie_shot = (u32)vb2_plane_cookie(vb, spare);
+               frame->shot = (struct camera2_shot *)frame->kvaddr_shot;
+               frame->shot_ext = (struct camera2_shot_ext *)queue->buf_kva[index][spare];
+               frame->shot_size = queue->framecfg.size[spare] - ext_size;
+#ifdef MEASURE_TIME
+               frame->tzone = (struct timeval *)frame->shot_ext->timeZone;
+#endif
+       } else {
+               /* Create Kvaddr for frame sync */
+               queue->buf_kva[index][spare] = vb2->plane_kvaddr(vb, spare);
+               if (!queue->buf_kva[index][spare]) {
+                       err("plane_kvaddr is fail(%08X)", framemgr->id);
+                       ret = -EINVAL;
+                       goto exit;
+               }
+
+               frame->stream = (struct camera2_stream *)queue->buf_kva[index][spare];
+               frame->stream->address = queue->buf_kva[index][spare];
+               frame->stream_size = queue->framecfg.size[spare];
+       }
+
+       set_bit(FRAME_INI_MEM, &frame->memory);
+
+       queue->buf_refcount++;
+
+       if (queue->buf_rdycount == queue->buf_refcount)
+               set_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+
+       if (queue->buf_maxcount == queue->buf_refcount)
+               set_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+
+exit:
+       return ret;
+}
+
+void fimc_is_queue_wait_prepare(struct vb2_queue *vbq)
+{
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_video *video;
+
+       BUG_ON(!vbq);
+
+       vctx = vbq->drv_priv;
+       if (!vctx) {
+               err("vctx is NULL");
+               return;
+       }
+
+       video = vctx->video;
+       mutex_unlock(&video->lock);
+}
+
+void fimc_is_queue_wait_finish(struct vb2_queue *vbq)
+{
+       int ret = 0;
+       struct fimc_is_video_ctx *vctx;
+       struct fimc_is_video *video;
+
+       BUG_ON(!vbq);
+
+       vctx = vbq->drv_priv;
+       if (!vctx) {
+               err("vctx is NULL");
+               return;
+       }
+
+       video = vctx->video;
+       ret = mutex_lock_interruptible(&video->lock);
+       if (ret)
+               err("mutex_lock_interruptible is fail(%d)", ret);
+}
+
+int fimc_is_queue_start_streaming(struct fimc_is_queue *queue,
+       struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+
+       BUG_ON(!queue);
+       BUG_ON(!device);
+       BUG_ON(!subdev);
+       BUG_ON(!vctx);
+
+       if (test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               merr("already stream on(%ld)", vctx, queue->state);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state)) {
+               merr("buffer state is not ready(%ld)", vctx, queue->state);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = CALL_QOPS(queue, start_streaming, device, subdev, queue);
+       if (ret) {
+               merr("start_streaming is fail(%d)", vctx, ret);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       set_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_queue_stop_streaming(struct fimc_is_queue *queue,
+       struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+
+       BUG_ON(!queue);
+       BUG_ON(!device);
+       BUG_ON(!subdev);
+       BUG_ON(!vctx);
+
+       if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               merr("already stream off(%ld)", vctx, queue->state);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = CALL_QOPS(queue, stop_streaming, device, subdev, queue);
+       if (ret) {
+               merr("stop_streaming is fail(%d)", vctx, ret);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+p_err:
+       /* HACK: this state must be clear only if all ops was finished */
+       clear_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state);
+       clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+       clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+
+       return ret;
+}
+
+int fimc_is_video_probe(struct fimc_is_video *video,
+       char *video_name,
+       u32 video_number,
+       u32 vfl_dir,
+       struct fimc_is_mem *mem,
+       struct v4l2_device *v4l2_dev,
+       struct mutex *lock,
+       const struct v4l2_file_operations *fops,
+       const struct v4l2_ioctl_ops *ioctl_ops)
+{
+       int ret = 0;
+       u32 video_id;
+
+       vref_init(video);
+       mutex_init(&video->lock);
+       snprintf(video->vd.name, sizeof(video->vd.name), "%s", video_name);
+       video->id               = video_number;
+       video->vb2              = mem->vb2;
+       video->alloc_ctx        = mem->alloc_ctx;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
+       video->vd.vfl_dir       = vfl_dir;
+#endif
+       video->vd.v4l2_dev      = v4l2_dev;
+       video->vd.fops          = fops;
+       video->vd.ioctl_ops     = ioctl_ops;
+       video->vd.minor         = -1;
+       video->vd.release       = video_device_release;
+       video->vd.lock          = lock;
+       video_set_drvdata(&video->vd, video);
+
+       video_id = EXYNOS_VIDEONODE_FIMC_IS + video_number;
+       ret = video_register_device(&video->vd,
+               VFL_TYPE_GRABBER,
+               (EXYNOS_VIDEONODE_FIMC_IS + video_number));
+       if (ret) {
+               err("Failed to register video device");
+               goto p_err;
+       }
+
+p_err:
+       info("[VID] %s(%d) is created\n", video_name, video_id);
+       return ret;
+}
+
+int fimc_is_video_open(struct fimc_is_video_ctx *vctx,
+       void *device,
+       u32 buf_rdycount,
+       struct fimc_is_video *video,
+       u32 video_type,
+       const struct vb2_ops *vb2_ops,
+       const struct fimc_is_queue_ops *src_qops,
+       const struct fimc_is_queue_ops *dst_qops)
+{
+       int ret = 0;
+       struct fimc_is_queue *q_src, *q_dst;
+
+       BUG_ON(!video);
+       BUG_ON(!video->vb2);
+       BUG_ON(!vb2_ops);
+
+       q_src = vctx->q_src;
+       q_dst = vctx->q_dst;
+       q_src->vbq = NULL;
+       q_dst->vbq = NULL;
+       q_src->qops = src_qops;
+       q_dst->qops = dst_qops;
+
+       vctx->type              = video_type;
+       vctx->device            = device;
+       vctx->video             = video;
+       vctx->vb2_ops           = vb2_ops;
+       vctx->mem_ops           = video->vb2->ops;
+       mutex_init(&vctx->lock);
+
+       switch (video_type) {
+       case FIMC_IS_VIDEO_TYPE_OUTPUT:
+               fimc_is_queue_open(q_src, buf_rdycount);
+
+               q_src->vbq = kzalloc(sizeof(struct vb2_queue), GFP_KERNEL);
+               if (!q_src->vbq) {
+                       err("kzalloc is fail");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+
+               ret = queue_init(vctx, q_src->vbq, NULL);
+               if (ret) {
+                       err("queue_init fail");
+                       kfree(q_src->vbq);
+                       goto p_err;
+               }
+               break;
+       case FIMC_IS_VIDEO_TYPE_CAPTURE:
+               fimc_is_queue_open(q_dst, buf_rdycount);
+
+               q_dst->vbq = kzalloc(sizeof(struct vb2_queue), GFP_KERNEL);
+               if (!q_dst->vbq) {
+                       err("kzalloc is fail");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+
+               ret = queue_init(vctx, NULL, q_dst->vbq);
+               if (ret) {
+                       err("queue_init fail");
+                       kfree(q_dst->vbq);
+                       goto p_err;
+               }
+               break;
+       case FIMC_IS_VIDEO_TYPE_M2M:
+               fimc_is_queue_open(q_src, buf_rdycount);
+               fimc_is_queue_open(q_dst, buf_rdycount);
+
+               q_src->vbq = kzalloc(sizeof(struct vb2_queue), GFP_KERNEL);
+               if (!q_src->vbq) {
+                       err("kzalloc is fail");
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+
+               q_dst->vbq = kzalloc(sizeof(struct vb2_queue), GFP_KERNEL);
+               if (!q_dst->vbq) {
+                       err("kzalloc is fail");
+                       kfree(q_src->vbq);
+                       ret = -ENOMEM;
+                       goto p_err;
+               }
+
+               ret = queue_init(vctx, q_src->vbq, q_dst->vbq);
+               if (ret) {
+                       err("queue_init fail");
+                       kfree(q_src->vbq);
+                       kfree(q_dst->vbq);
+                       goto p_err;
+               }
+               break;
+       default:
+               merr("invalid type(%d)", vctx, video_type);
+               ret = -EINVAL;
+               break;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_video_close(struct fimc_is_video_ctx *vctx)
+{
+       int ret = 0;
+       u32 video_type;
+       struct fimc_is_queue *q_src, *q_dst;
+
+       BUG_ON(!vctx);
+
+       video_type = vctx->type;
+
+       q_src = vctx->q_src;
+       q_dst = vctx->q_dst;
+
+       switch (video_type) {
+       case FIMC_IS_VIDEO_TYPE_OUTPUT:
+               BUG_ON(!q_src->vbq);
+               fimc_is_queue_close(q_src);
+               vb2_queue_release(q_src->vbq);
+               kfree(q_src->vbq);
+               break;
+       case FIMC_IS_VIDEO_TYPE_CAPTURE:
+               BUG_ON(!q_dst->vbq);
+               fimc_is_queue_close(q_dst);
+               vb2_queue_release(q_dst->vbq);
+               kfree(q_dst->vbq);
+               break;
+       case FIMC_IS_VIDEO_TYPE_M2M:
+               BUG_ON(!q_src->vbq);
+               BUG_ON(!q_dst->vbq);
+               fimc_is_queue_close(q_src);
+               vb2_queue_release(q_src->vbq);
+               fimc_is_queue_close(q_dst);
+               vb2_queue_release(q_dst->vbq);
+               kfree(q_src->vbq);
+               kfree(q_dst->vbq);
+               break;
+       default:
+               merr("invalid type(%d)", vctx, video_type);
+               ret = -EINVAL;
+               break;
+       }
+
+       /*
+        * vb2 release can call stop callback
+        * not if video node is not stream off
+        */
+       vctx->device = NULL;
+
+       return ret;
+}
+
+u32 fimc_is_video_poll(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct poll_table_struct *wait)
+{
+       u32 ret = 0;
+       u32 video_type = vctx->type;
+
+       switch (video_type) {
+       case FIMC_IS_VIDEO_TYPE_OUTPUT:
+               ret = vb2_poll(vctx->q_src->vbq, file, wait);
+               break;
+       case FIMC_IS_VIDEO_TYPE_CAPTURE:
+               ret = vb2_poll(vctx->q_dst->vbq, file, wait);
+               break;
+       case FIMC_IS_VIDEO_TYPE_M2M:
+               merr("video poll is not supported", vctx);
+               ret = -EINVAL;
+               break;
+       default:
+               merr("invalid type(%d)", vctx, video_type);
+               break;
+       }
+
+       return ret;
+}
+
+int fimc_is_video_mmap(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct vm_area_struct *vma)
+{
+       u32 ret = 0;
+       u32 video_type = vctx->type;
+
+       switch (video_type) {
+       case FIMC_IS_VIDEO_TYPE_OUTPUT:
+               ret = vb2_mmap(vctx->q_src->vbq, vma);
+               break;
+       case FIMC_IS_VIDEO_TYPE_CAPTURE:
+               ret = vb2_mmap(vctx->q_dst->vbq, vma);
+               break;
+       case FIMC_IS_VIDEO_TYPE_M2M:
+               merr("video mmap is not supported", vctx);
+               ret = -EINVAL;
+               break;
+       default:
+               merr("invalid type(%d)", vctx, video_type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+int fimc_is_video_reqbufs(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_requestbuffers *request)
+{
+       int ret = 0;
+       struct fimc_is_framemgr *framemgr;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!request);
+
+       queue = GET_VCTX_QUEUE(vctx, request);
+
+       if (test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               err("video is stream on, not applied");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = vb2_reqbufs(queue->vbq, request);
+       if (ret) {
+               err("vb2_reqbufs is fail(%d)", ret);
+               goto p_err;
+       }
+
+       framemgr = &queue->framemgr;
+       queue->buf_maxcount = request->count;
+       if (queue->buf_maxcount == 0) {
+               queue->buf_refcount = 0;
+               clear_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+               clear_bit(FIMC_IS_QUEUE_BUFFER_PREPARED, &queue->state);
+               fimc_is_frame_close(framemgr);
+       } else {
+               if (queue->buf_maxcount < queue->buf_rdycount) {
+                       err("buffer count is not invalid(%d < %d)",
+                               queue->buf_maxcount, queue->buf_rdycount);
+                       ret = -EINVAL;
+                       goto p_err;
+               }
+
+               if (!queue->buf_rdycount)
+                       set_bit(FIMC_IS_QUEUE_BUFFER_READY, &queue->state);
+
+               fimc_is_frame_open(framemgr, queue->buf_maxcount);
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_video_querybuf(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+
+       queue = GET_VCTX_QUEUE(vctx, buf);
+
+       ret = vb2_querybuf(queue->vbq, buf);
+
+       return ret;
+}
+
+int fimc_is_video_set_format_mplane(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_format *format)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!format);
+
+       queue = GET_VCTX_QUEUE(vctx, format);
+
+       ret = fimc_is_queue_set_format_mplane(queue, format);
+
+       mdbgv_vid("set_format(%d x %d)\n", queue->framecfg.width,
+               queue->framecfg.height);
+
+       return ret;
+}
+
+int fimc_is_video_qbuf(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+       struct vb2_queue *vbq;
+       struct vb2_buffer *vb;
+
+       BUG_ON(!file);
+       BUG_ON(!vctx);
+       BUG_ON(!buf);
+
+       buf->flags &= ~V4L2_BUF_FLAG_USE_SYNC;
+       queue = GET_VCTX_QUEUE(vctx, buf);
+       vbq = queue->vbq;
+
+       if (!vbq) {
+               merr("vbq is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (vbq->fileio) {
+               merr("file io in progress", vctx);
+               ret = -EBUSY;
+               goto p_err;
+       }
+
+       if (buf->type != queue->vbq->type) {
+               merr("buf type is invalid(%d != %d)", vctx,
+                       buf->type, queue->vbq->type);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (buf->index >= vbq->num_buffers) {
+               merr("buffer index%d out of range", vctx, buf->index);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (buf->memory != vbq->memory) {
+               merr("invalid memory type%d", vctx, buf->memory);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       vb = vbq->bufs[buf->index];
+       if (!vb) {
+               merr("vb is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = vb2_qbuf(queue->vbq, buf);
+       if (ret) {
+               merr("vb2_qbuf is fail(index : %d, %d)", vctx, buf->index, ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int fimc_is_video_dqbuf(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_buffer *buf)
+{
+       int ret = 0;
+       u32 qcount;
+       bool blocking;
+       struct fimc_is_queue *queue;
+       struct fimc_is_framemgr *framemgr;
+
+       BUG_ON(!file);
+       BUG_ON(!vctx);
+       BUG_ON(!buf);
+
+       blocking = file->f_flags & O_NONBLOCK;
+       queue = GET_VCTX_QUEUE(vctx, buf);
+       framemgr = &queue->framemgr;
+
+       if (!queue->vbq) {
+               merr("vbq is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (buf->type != queue->vbq->type) {
+               merr("buf type is invalid(%d != %d)", vctx,
+                       buf->type, queue->vbq->type);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               merr("queue is not streamon(%ld)", vctx, queue->state);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr_e_barrier_irq(framemgr, 0);
+       qcount = framemgr->frame_req_cnt +
+               framemgr->frame_pro_cnt +
+               framemgr->frame_com_cnt;
+       framemgr_x_barrier_irq(framemgr, 0);
+
+       if (qcount <= 0) {
+               /* HACK : this log is commented until timeout issue fixed */
+               /* merr("dqbuf can not be executed without qbuf(%d)", vctx, qcount); */
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = vb2_dqbuf(queue->vbq, buf, blocking);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_video_streamon(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+       struct vb2_queue *vbq;
+
+       BUG_ON(!file);
+       BUG_ON(!vctx);
+
+       queue = GET_QUEUE(vctx, type);
+       vbq = queue->vbq;
+       if (!vbq) {
+               merr("vbq is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (vbq->type != type) {
+               merr("invalid stream type(%d != %d)", vctx, vbq->type, type);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (vbq->streaming) {
+               merr("streamon: already streaming", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = vb2_streamon(vbq, type);
+
+p_err:
+       return ret;
+}
+
+int fimc_is_video_streamoff(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       enum v4l2_buf_type type)
+{
+       int ret = 0;
+       u32 qcount;
+       struct fimc_is_queue *queue;
+       struct vb2_queue *vbq;
+       struct fimc_is_framemgr *framemgr;
+
+       BUG_ON(!file);
+       BUG_ON(!vctx);
+
+       queue = GET_QUEUE(vctx, type);
+       framemgr = &queue->framemgr;
+       vbq = queue->vbq;
+       if (!vbq) {
+               merr("vbq is NULL", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framemgr_e_barrier_irq(framemgr, 0);
+       qcount = framemgr->frame_req_cnt +
+               framemgr->frame_pro_cnt +
+               framemgr->frame_com_cnt;
+       framemgr_x_barrier_irq(framemgr, 0);
+
+       if (qcount > 0)
+               mwarn("video%d stream off : queued buffer is not empty(%d)", vctx,
+                       vctx->video->id, qcount);
+
+       if (vbq->type != type) {
+               merr("invalid stream type(%d != %d)", vctx, vbq->type, type);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!vbq->streaming) {
+               merr("streamoff: not streaming", vctx);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = vb2_streamoff(vbq, type);
+
+p_err:
+       return ret;
+}
+
+int queue_done(struct fimc_is_video_ctx *vctx,
+       struct fimc_is_queue *queue,
+       u32 index, u32 state)
+{
+       int ret = 0;
+       struct vb2_buffer *vb;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+       BUG_ON(!queue);
+       BUG_ON(!queue->vbq);
+       BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
+
+       vb = queue->vbq->bufs[index];
+
+       if (!test_bit(FIMC_IS_QUEUE_STREAM_ON, &queue->state)) {
+               warn("%d video queue is not stream on", vctx->video->id);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (vb->state != VB2_BUF_STATE_ACTIVE) {
+               err("vb buffer[%d] state is not active(%d)", index, vb->state);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       vb2_buffer_done(vb, state);
+
+p_err:
+       return ret;
+}
+
+int buffer_done(struct fimc_is_video_ctx *vctx, u32 index)
+{
+       int ret = 0;
+       struct fimc_is_queue *queue;
+
+       BUG_ON(!vctx);
+       BUG_ON(!vctx->video);
+       BUG_ON(index >= FRAMEMGR_MAX_REQUEST);
+       BUG_ON(vctx->type == FIMC_IS_VIDEO_TYPE_M2M);
+
+       switch (vctx->type) {
+       case FIMC_IS_VIDEO_TYPE_OUTPUT:
+               queue = GET_SRC_QUEUE(vctx);
+               queue_done(vctx, queue, index, VB2_BUF_STATE_DONE);
+               break;
+       case FIMC_IS_VIDEO_TYPE_CAPTURE:
+               queue = GET_DST_QUEUE(vctx);
+               queue_done(vctx, queue, index, VB2_BUF_STATE_DONE);
+               break;
+       default:
+               merr("invalid type(%d)", vctx, vctx->type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/fimc-is-video.h b/drivers/media/platform/exynos/fimc-is/fimc-is-video.h
new file mode 100644 (file)
index 0000000..817bf4c
--- /dev/null
@@ -0,0 +1,234 @@
+#ifndef FIMC_IS_VIDEO_H
+#define FIMC_IS_VIDEO_H
+
+#include <linux/version.h>
+#include <media/v4l2-ioctl.h>
+#include "fimc-is-type.h"
+#include "fimc-is-mem.h"
+#include "fimc-is-framemgr.h"
+#include "fimc-is-metadata.h"
+#include "fimc-is-config.h"
+
+/* configuration by linux kernel version */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
+#define VFL_DIR_RX             0
+#define VFL_DIR_TX             1
+#define VFL_DIR_M2M            2
+#endif
+
+#define FIMC_IS_MAX_NODES                      (3)
+#define FIMC_IS_INVALID_BUF_INDEX              (0xFF)
+
+#define VIDEO_SENSOR_READY_BUFFERS             0
+#define VIDEO_3AA_READY_BUFFERS                        0
+#define VIDEO_3AAC_READY_BUFFERS               0
+#define VIDEO_3AAP_READY_BUFFERS               0
+#define VIDEO_ISP_READY_BUFFERS                        0
+#define VIDEO_SCC_READY_BUFFERS                        0
+#define VIDEO_SCP_READY_BUFFERS                        0
+#define VIDEO_VDISC_READY_BUFFERS              1
+#define VIDEO_VDISO_READY_BUFFERS              0
+
+#define FIMC_IS_VIDEO_NAME(name)               ("exynos-fimc-is-"name)
+#define FIMC_IS_VIDEO_SENSOR_NAME              FIMC_IS_VIDEO_NAME("sensor")
+#define FIMC_IS_VIDEO_3AA_NAME(id)             FIMC_IS_VIDEO_NAME("3aa."#id)
+#define FIMC_IS_VIDEO_3AAC_NAME(id)            FIMC_IS_VIDEO_NAME("3aa."#id"c")
+#define FIMC_IS_VIDEO_3AAP_NAME(id)            FIMC_IS_VIDEO_NAME("3aa."#id"p")
+#define FIMC_IS_VIDEO_ISP_NAME                 FIMC_IS_VIDEO_NAME("isp")
+#define FIMC_IS_VIDEO_SCC_NAME                 FIMC_IS_VIDEO_NAME("scalerc")
+#define FIMC_IS_VIDEO_SCP_NAME                 FIMC_IS_VIDEO_NAME("scalerp")
+#define FIMC_IS_VIDEO_VDC_NAME                 FIMC_IS_VIDEO_NAME("vdisc")
+#define FIMC_IS_VIDEO_VDO_NAME                 FIMC_IS_VIDEO_NAME("vdiso")
+
+struct fimc_is_device_ischain;
+struct fimc_is_subdev;
+struct fimc_is_queue;
+
+enum fimc_is_video_dev_num {
+       FIMC_IS_VIDEO_SS0_NUM   = 0,
+       FIMC_IS_VIDEO_SS1_NUM   = 1,
+       FIMC_IS_VIDEO_SS2_NUM   = 2,
+       FIMC_IS_VIDEO_SS3_NUM   = 3,
+       FIMC_IS_VIDEO_3A0_NUM   = 10,
+       FIMC_IS_VIDEO_3A0C_NUM  = 11,
+       FIMC_IS_VIDEO_3A0P_NUM  = 12,
+       FIMC_IS_VIDEO_3A1_NUM   = 14,
+       FIMC_IS_VIDEO_3A1C_NUM  = 15,
+       FIMC_IS_VIDEO_3A1P_NUM  = 16,
+       FIMC_IS_VIDEO_ISP_NUM   = 30,
+       FIMC_IS_VIDEO_SCC_NUM   = 34,
+       FIMC_IS_VIDEO_SCP_NUM   = 37,
+       FIMC_IS_VIDEO_VDC_NUM   = 40,
+       FIMC_IS_VIDEO_VDO_NUM   = 41,
+       FIMC_IS_VIDEO_FD_NUM    = 46,
+       FIMC_IS_VIDEO_MAX_NUM   = 49
+};
+
+enum fimc_is_video_type {
+       FIMC_IS_VIDEO_TYPE_CAPTURE,
+       FIMC_IS_VIDEO_TYPE_OUTPUT,
+       FIMC_IS_VIDEO_TYPE_M2M,
+};
+
+enum fimc_is_queue_state {
+       FIMC_IS_QUEUE_BUFFER_PREPARED,
+       FIMC_IS_QUEUE_BUFFER_READY,
+       FIMC_IS_QUEUE_STREAM_ON
+};
+
+struct fimc_is_frame_cfg {
+       struct fimc_is_fmt              format;
+       u32                             width;
+       u32                             height;
+       u32                             width_stride[FIMC_IS_MAX_PLANES];
+       u32                             size[FIMC_IS_MAX_PLANES];
+       u32                             bytesperline[FIMC_IS_MAX_PLANES];
+};
+
+struct fimc_is_queue_ops {
+       int (*start_streaming)(struct fimc_is_device_ischain *device,
+               struct fimc_is_subdev *subdev,
+               struct fimc_is_queue *queue);
+       int (*stop_streaming)(struct fimc_is_device_ischain *device,
+               struct fimc_is_subdev *subdev,
+               struct fimc_is_queue *queue);
+};
+
+struct fimc_is_queue {
+       struct vb2_queue                *vbq;
+       const struct fimc_is_queue_ops  *qops;
+       struct fimc_is_framemgr         framemgr;
+       struct fimc_is_frame_cfg        framecfg;
+
+       u32                             buf_maxcount;
+       u32                             buf_rdycount;
+       u32                             buf_refcount;
+       u32                             buf_dva[FIMC_IS_MAX_BUFS][FIMC_IS_MAX_PLANES];
+       u32                             buf_kva[FIMC_IS_MAX_BUFS][FIMC_IS_MAX_PLANES];
+
+       u32                             id;
+       unsigned long                   state;
+};
+
+struct fimc_is_video_ctx {
+       struct fimc_is_queue            *q_src;
+       struct fimc_is_queue            *q_dst;
+       struct mutex                    lock;
+       u32                             type;
+       u32                             instance;
+
+       void                            *device;
+       struct fimc_is_video            *video;
+
+       const struct vb2_ops            *vb2_ops;
+       const struct vb2_mem_ops        *mem_ops;
+};
+
+struct fimc_is_video {
+       u32                             id;
+       atomic_t                        refcount;
+       struct mutex                    lock;
+
+       struct video_device             vd;
+       struct media_pad                pads;
+       const struct fimc_is_vb2        *vb2;
+       void                            *alloc_ctx;
+};
+
+struct fimc_is_core *fimc_is_video_ctx_2_core(struct fimc_is_video_ctx *vctx);
+
+/* video context operation */
+int open_vctx(struct file *file,
+       struct fimc_is_video *video,
+       struct fimc_is_video_ctx **vctx,
+       u32 id_src, u32 id_dst);
+int close_vctx(struct file *file,
+       struct fimc_is_video *video,
+       struct fimc_is_video_ctx *vctx);
+
+/* queue operation */
+int fimc_is_queue_setup(struct fimc_is_queue *queue,
+       void *alloc_ctx,
+       unsigned int *num_planes,
+       unsigned int sizes[],
+       void *allocators[]);
+int fimc_is_queue_buffer_queue(struct fimc_is_queue *queue,
+       const struct fimc_is_vb2 *vb2,
+       struct vb2_buffer *vb);
+void fimc_is_queue_wait_prepare(struct vb2_queue *vbq);
+void fimc_is_queue_wait_finish(struct vb2_queue *vbq);
+int fimc_is_queue_start_streaming(struct fimc_is_queue *queue,
+       struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_video_ctx *vctx);
+int fimc_is_queue_stop_streaming(struct fimc_is_queue *queue,
+       struct fimc_is_device_ischain *device,
+       struct fimc_is_subdev *subdev,
+       struct fimc_is_video_ctx *vctx);
+
+/* video operation */
+int fimc_is_video_probe(struct fimc_is_video *video,
+       char *video_name,
+       u32 video_number,
+       u32 vfl_dir,
+       struct fimc_is_mem *mem,
+       struct v4l2_device *v4l2_dev,
+       struct mutex *lock,
+       const struct v4l2_file_operations *fops,
+       const struct v4l2_ioctl_ops *ioctl_ops);
+int fimc_is_video_open(struct fimc_is_video_ctx *vctx,
+       void *device,
+       u32 buf_rdycount,
+       struct fimc_is_video *video,
+       u32 video_type,
+       const struct vb2_ops *vb2_ops,
+       const struct fimc_is_queue_ops *src_qops,
+       const struct fimc_is_queue_ops *dst_qops);
+int fimc_is_video_close(struct fimc_is_video_ctx *vctx);
+u32 fimc_is_video_poll(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct poll_table_struct *wait);
+int fimc_is_video_mmap(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct vm_area_struct *vma);
+int fimc_is_video_reqbufs(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_requestbuffers *request);
+int fimc_is_video_querybuf(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_buffer *buf);
+int fimc_is_video_set_format_mplane(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_format *format);
+int fimc_is_video_qbuf(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_buffer *buf);
+int fimc_is_video_dqbuf(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       struct v4l2_buffer *buf);
+int fimc_is_video_streamon(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       enum v4l2_buf_type type);
+int fimc_is_video_streamoff(struct file *file,
+       struct fimc_is_video_ctx *vctx,
+       enum v4l2_buf_type type);
+
+int queue_done(struct fimc_is_video_ctx *vctx,
+       struct fimc_is_queue *queue,
+       u32 index, u32 state);
+int buffer_done(struct fimc_is_video_ctx *vctx, u32 index);
+long video_ioctl3(struct file *file, unsigned int cmd, unsigned long arg);
+
+#define GET_QUEUE(vctx, type) \
+       (V4L2_TYPE_IS_OUTPUT((type)) ? vctx->q_src : vctx->q_dst)
+#define GET_VCTX_QUEUE(vctx, vbq) (GET_QUEUE(vctx, vbq->type))
+
+#define GET_SRC_QUEUE(vctx) (vctx->q_src)
+#define GET_DST_QUEUE(vctx) (vctx->q_dst)
+
+#define GET_SRC_FRAMEMGR(vctx) (&vctx->q_src->framemgr)
+#define GET_DST_FRAMEMGR(vctx) (&vctx->q_dst->framemgr)
+
+#define CALL_QOPS(q, op, args...) (((q)->qops->op) ? ((q)->qops->op(args)) : 0)
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2.c
new file mode 100644 (file)
index 0000000..aa062f0
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-2p2.h"
+
+#define SENSOR_NAME "S5K2P2"
+
+static struct fimc_is_sensor_cfg config_2p2[] = {
+       /* 5328x3000@30fps */
+       FIMC_IS_SENSOR_CFG(5328, 3000, 30, 30, 0),
+       /* 5328x3000@24fps */
+       FIMC_IS_SENSOR_CFG(5328, 3000, 24, 30, 1),
+       /* 4000X3000@30fps */
+       FIMC_IS_SENSOR_CFG(4000, 3000, 30, 23, 2),
+       /* 4000X3000@24fps */
+       FIMC_IS_SENSOR_CFG(4000, 3000, 24, 23, 3),
+       /* 3008X3000@30fps */
+       FIMC_IS_SENSOR_CFG(3008, 3000, 30, 19, 4),
+       /* 3008X3000@30fps */
+       FIMC_IS_SENSOR_CFG(3008, 3000, 24, 19, 5),
+       /* 2664X1500@60fps */
+       FIMC_IS_SENSOR_CFG(2664, 1500, 60, 19, 6),
+       /* 1328X748@120fps */
+       FIMC_IS_SENSOR_CFG(1328, 748, 120, 13, 7),
+       /* 824X496@300fps */
+       FIMC_IS_SENSOR_CFG(824, 496, 300, 13, 8),
+};
+
+static int sensor_2p2_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_2p2_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+#ifdef CONFIG_OF
+#ifdef CONFIG_COMPANION_USE
+static int sensor_2p2_power_setpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpio_comp_en = 0, gpio_comp_rst = 0;
+       int gpio_none = 0;
+       int gpio_reset = 0;
+       int gpios_cam_en = -EINVAL;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_comp_en = of_get_named_gpio(dnode, "gpios_comp_en", 0);
+       if (!gpio_is_valid(gpio_comp_en)) {
+               dev_err(dev, "failed to get main comp en gpio\n");
+       } else {
+               gpio_request_one(gpio_comp_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_comp_en);
+       }
+
+       gpio_comp_rst = of_get_named_gpio(dnode, "gpios_comp_reset", 0);
+       if (!gpio_is_valid(gpio_comp_rst)) {
+               dev_err(dev, "failed to get main comp reset gpio\n");
+       } else {
+               gpio_request_one(gpio_comp_rst, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_comp_rst);
+       }
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+       if (!gpio_is_valid(gpios_cam_en)) {
+               dev_err(dev, "failed to get main/front cam en gpio\n");
+       } else {
+               gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_cam_en);
+       }
+
+       /* COMPANION - POWER ON */
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_none, 0, "VDDA_1.8V_COMP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_comp_en, 0, NULL, 150, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_comp_rst, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 7, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 8, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 9, gpio_none, 0, "af", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 10, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* COMPANION - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_comp_rst, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_comp_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VDDA_1.8V_COMP", 0, PIN_REGULATOR_OFF);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 7, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 8, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 9, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#else
+static int sensor_2p2_power_setpin(struct device *dev)
+{
+       return 0;
+}
+#endif /* CONFIG_COMPANION_USE */
+#endif /* CONFIG_OF */
+
+int sensor_2p2_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_2P2_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K2P2;
+       module->subdev = subdev_module;
+       module->device = SENSOR_2P2_INSTANCE;
+       module->client = client;
+       module->active_width = 5312;
+       module->active_height = 2990;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 300;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K2P2";
+       module->setfile_name = "setfile_2p2.bin";
+       module->cfgs = ARRAY_SIZE(config_2p2);
+       module->cfg = config_2p2;
+       module->ops = NULL;
+       module->private_data = NULL;
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_2p2_power_setpin;
+#endif
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = SENSOR_NAME_S5K2P2;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x5A;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7345;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x5A;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+#ifdef CONFIG_LEDS_MAX77804
+       ext->flash_con.product_name = FLADRV_NAME_MAX77693;
+#endif
+#if defined(CONFIG_LEDS_LM3560) || !defined(CONFIG_USE_VENDER_FEATURE)
+       ext->flash_con.product_name = FLADRV_NAME_LM3560;
+#endif
+#ifdef CONFIG_LEDS_SKY81296
+       ext->flash_con.product_name = FLADRV_NAME_SKY81296;
+#endif
+       ext->flash_con.peri_type = SE_GPIO;
+#ifdef CONFIG_USE_VENDER_FEATURE
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 1;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 2;
+#else
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 2;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 3;
+#endif
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+#ifdef CONFIG_COMPANION_USE
+       ext->companion_con.product_name = COMPANION_NAME_73C1;
+       ext->companion_con.peri_info0.valid = true;
+       ext->companion_con.peri_info0.peri_type = SE_SPI;
+       ext->companion_con.peri_info0.peri_setting.spi.channel = (int) core->companion_spi_channel;
+       ext->companion_con.peri_info1.valid = true;
+       ext->companion_con.peri_info1.peri_type = SE_I2C;
+       ext->companion_con.peri_info1.peri_setting.i2c.channel = 0;
+       ext->companion_con.peri_info1.peri_setting.i2c.slave_address = 0x7A;
+       ext->companion_con.peri_info1.peri_setting.i2c.speed = 400000;
+       ext->companion_con.peri_info2.valid = true;
+       ext->companion_con.peri_info2.peri_type = SE_FIMC_LITE;
+       ext->companion_con.peri_info2.peri_setting.fimc_lite.channel = FLITE_ID_D;
+#else
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+#endif
+
+#if defined(CONFIG_OIS_USE)
+       ext->ois_con.product_name = OIS_NAME_IDG2030;
+       ext->ois_con.peri_type = SE_I2C;
+       ext->ois_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->ois_con.peri_setting.i2c.slave_address = 0x48;
+       ext->ois_con.peri_setting.i2c.speed = 400000;
+#else
+       ext->ois_con.product_name = OIS_NAME_NOTHING;
+       ext->ois_con.peri_type = SE_NULL;
+#endif
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2.h
new file mode 100644 (file)
index 0000000..f4820cc
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_2P2_H
+#define FIMC_IS_DEVICE_2P2_H
+
+#define SENSOR_2P2_INSTANCE    0
+#define SENSOR_2P2_NAME                SENSOR_NAME_S5K2P2
+
+int sensor_2p2_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2_12m.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2_12m.c
new file mode 100644 (file)
index 0000000..979f05a
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-2p2_12m.h"
+
+#define SENSOR_NAME "S5K2P2_12M"
+
+static struct fimc_is_sensor_cfg config_2p2_12m[] = {
+       /* 4624x2604@30fps */
+       FIMC_IS_SENSOR_CFG(4624, 2604, 30, 22, 0),
+       /* 4624x2604@24fps */
+       FIMC_IS_SENSOR_CFG(4624, 2604, 24, 21, 1),
+       /* 3472X2604@30fps */
+       FIMC_IS_SENSOR_CFG(3472, 2604, 30, 17, 2),
+       /* 3472X2604@24fps */
+       FIMC_IS_SENSOR_CFG(3472, 2604, 24, 17, 3),
+       /* 2608X2604@30fps */
+       FIMC_IS_SENSOR_CFG(2608, 2604, 30, 17, 4),
+       /* 2608X2604@24fps */
+       FIMC_IS_SENSOR_CFG(2608, 2604, 24, 17, 5),
+       /* 2312X1300@60fps */
+       FIMC_IS_SENSOR_CFG(2312, 1300, 60, 13, 6),
+       /* 2312X1300@30fps */
+       FIMC_IS_SENSOR_CFG(2312, 1300, 30, 13, 7),
+       /* 1156X650@120fps */
+       FIMC_IS_SENSOR_CFG(1156, 650, 120, 13, 8),
+};
+
+static int sensor_2p2_12m_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_2p2_12m_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+#ifdef CONFIG_OF
+#ifdef CONFIG_COMPANION_USE
+static int sensor_2p2_12m_power_setpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpio_comp_en = 0, gpio_comp_rst = 0;
+       int gpio_none = 0;
+       int gpio_reset = 0;
+       int gpios_cam_en = -EINVAL;
+#ifdef CONFIG_OIS_USE
+       int gpios_ois_en = 0;
+#endif
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_comp_en = of_get_named_gpio(dnode, "gpios_comp_en", 0);
+       if (!gpio_is_valid(gpio_comp_en)) {
+               dev_err(dev, "failed to get main comp en gpio\n");
+       } else {
+               gpio_request_one(gpio_comp_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_comp_en);
+       }
+
+       gpio_comp_rst = of_get_named_gpio(dnode, "gpios_comp_reset", 0);
+       if (!gpio_is_valid(gpio_comp_rst)) {
+               dev_err(dev, "failed to get main comp reset gpio\n");
+       } else {
+               gpio_request_one(gpio_comp_rst, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_comp_rst);
+       }
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       if (of_get_property(dnode, "gpios_cam_en", NULL)) {
+               gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+               if (!gpio_is_valid(gpios_cam_en)) {
+                       dev_err(dev, "failed to get main cam en gpio\n");
+               } else {
+                       gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+                       gpio_free(gpios_cam_en);
+               }
+       }
+
+#ifdef CONFIG_OIS_USE
+       gpios_ois_en = of_get_named_gpio(dnode, "gpios_ois_en", 0);
+       pdata->pin_ois_en = gpios_ois_en;
+       if (!gpio_is_valid(gpios_ois_en)) {
+               dev_err(dev, "failed to get ois en gpio\n");
+       } else {
+               gpio_request_one(gpios_ois_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_ois_en);
+       }
+#endif
+
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+#ifdef CONFIG_OIS_USE
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_ON);
+#endif
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, "VDDA_1.8V_COMP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 7, gpio_comp_en, 0, NULL, 150, PIN_OUTPUT_HIGH);
+       if (pdata->companion_use_pmic) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 8, gpio_none, 0, "VDD_MIPI_1.0V_COMP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 9, gpio_comp_rst, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 10, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 11, gpio_none, 0, "af", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 12, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 13, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* BACK CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_comp_rst, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (pdata->companion_use_pmic) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VDD_MIPI_1.0V_COMP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_comp_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, "VDDA_1.8V_COMP", 0, PIN_REGULATOR_OFF);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 7, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 7, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 8, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 9, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+#ifdef CONFIG_OIS_USE
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 10, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 11, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_OFF);
+#endif
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 12, gpio_none, 0, NULL, 0, PIN_END);
+
+#ifdef CONFIG_OIS_USE
+       /* OIS_FACTORY  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 1, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 2, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 3, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 4, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 5, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* OIS_FACTORY  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 1, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 2, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 3, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 5, gpio_none, 0, NULL, 0, PIN_END);
+#endif
+
+       return 0;
+}
+#else
+static int sensor_2p2_12m_power_setpin(struct device *dev)
+{
+       return 0;
+}
+#endif /* CONFIG_COMPANION_USE */
+#endif /* CONFIG_OF */
+
+
+int sensor_2p2_12m_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_2P2_12M_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K2P2_12M;
+       module->subdev = subdev_module;
+       module->device = SENSOR_2P2_12M_INSTANCE;
+       module->client = client;
+       module->active_width = 4608;
+       module->active_height = 2594;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 300;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K2P2";
+       module->setfile_name = "setfile_2p2_12m.bin";
+       module->cfgs = ARRAY_SIZE(config_2p2_12m);
+       module->cfg = config_2p2_12m;
+       module->ops = NULL;
+       module->private_data = NULL;
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_2p2_12m_power_setpin;
+#endif
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = SENSOR_NAME_S5K2P2_12M;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x5A;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7345;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x5A;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+#ifdef CONFIG_LEDS_MAX77804
+       ext->flash_con.product_name = FLADRV_NAME_MAX77693;
+#endif
+#if defined(CONFIG_LEDS_LM3560) || !defined(CONFIG_USE_VENDER_FEATURE)
+       ext->flash_con.product_name = FLADRV_NAME_LM3560;
+#endif
+#ifdef CONFIG_LEDS_SKY81296
+       ext->flash_con.product_name = FLADRV_NAME_SKY81296;
+#endif
+       ext->flash_con.peri_type = SE_GPIO;
+#ifdef CONFIG_USE_VENDER_FEATURE
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 1;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 2;
+#else
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 2;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 3;
+#endif
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+#ifdef CONFIG_COMPANION_USE
+       ext->companion_con.product_name = COMPANION_NAME_73C1;
+       ext->companion_con.peri_info0.valid = true;
+       ext->companion_con.peri_info0.peri_type = SE_SPI;
+       ext->companion_con.peri_info0.peri_setting.spi.channel = (int) core->companion_spi_channel;
+       ext->companion_con.peri_info1.valid = true;
+       ext->companion_con.peri_info1.peri_type = SE_I2C;
+       ext->companion_con.peri_info1.peri_setting.i2c.channel = 0;
+       ext->companion_con.peri_info1.peri_setting.i2c.slave_address = 0x7A;
+       ext->companion_con.peri_info1.peri_setting.i2c.speed = 400000;
+       ext->companion_con.peri_info2.valid = true;
+       ext->companion_con.peri_info2.peri_type = SE_FIMC_LITE;
+       ext->companion_con.peri_info2.peri_setting.fimc_lite.channel = FLITE_ID_D;
+#else
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+#endif
+
+       if (client) {
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       } else {
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+       }
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2_12m.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p2_12m.h
new file mode 100644 (file)
index 0000000..d28ca8d
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_2P2_12M_H
+#define FIMC_IS_DEVICE_2P2_12M_H
+
+#define SENSOR_2P2_12M_INSTANCE        0
+#define SENSOR_2P2_12M_NAME            SENSOR_NAME_S5K2P2_12M
+
+int sensor_2p2_12m_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p3.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p3.c
new file mode 100644 (file)
index 0000000..ed22f2f
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-2p3.h"
+
+#define SENSOR_NAME "S5K2P3"
+
+static struct fimc_is_sensor_cfg config_2p3[] = {
+       /* 5328x3000@30fps */
+       FIMC_IS_SENSOR_CFG(5328, 3000, 30, 30, 0),
+       /* 5328x3000@24fps */
+       FIMC_IS_SENSOR_CFG(5328, 3000, 24, 24, 1),
+       /* 4000X3000@30fps */
+       FIMC_IS_SENSOR_CFG(4000, 3000, 30, 23, 2),
+       /* 4000X3000@24fps */
+       FIMC_IS_SENSOR_CFG(4000, 3000, 24, 19, 3),
+       /* 3008X3000@30fps */
+       FIMC_IS_SENSOR_CFG(3008, 3000, 30, 19, 4),
+       /* 3008X3000@30fps */
+       FIMC_IS_SENSOR_CFG(3008, 3000, 24, 14, 5),
+       /* 2664X1500@60fps */
+       FIMC_IS_SENSOR_CFG(2664, 1500, 60, 19, 6),
+       /* 1328X748@120fps */
+       FIMC_IS_SENSOR_CFG(1328, 748, 120, 13, 7),
+       /* 824X496@300fps */
+/*     FIMC_IS_SENSOR_CFG(824, 496, 300, 13, 8), TODO: Temporary Disabled. */
+};
+
+static int sensor_2p3_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_2p3_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+#ifdef CONFIG_OF
+static int sensor_2p3_power_setpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpio_none = 0;
+       int gpio_reset = 0;
+       int gpios_cam_en = -EINVAL;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+       if (!gpio_is_valid(gpios_cam_en)) {
+               dev_err(dev, "failed to get main/front cam en gpio\n");
+       } else {
+               gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_cam_en);
+       }
+
+       /* POWER ON */
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 7, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 8, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 9, gpio_none, 0, "af", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 10, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 7, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 8, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 9, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#endif /* CONFIG_OF */
+
+int sensor_2p3_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_2P3_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K2P3;
+       module->subdev = subdev_module;
+       module->device = SENSOR_2P3_INSTANCE;
+       module->client = client;
+       module->active_width = 5312;
+       module->active_height = 2990;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 300;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K2P3";
+       module->setfile_name = "setfile_2p3.bin";
+       module->cfgs = ARRAY_SIZE(config_2p3);
+       module->cfg = config_2p3;
+       module->ops = NULL;
+       module->private_data = NULL;
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_2p3_power_setpin;
+#endif
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = SENSOR_NAME_S5K2P3;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x20;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7345;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x20;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+#ifdef CONFIG_LEDS_MAX77804
+       ext->flash_con.product_name = FLADRV_NAME_MAX77693;
+#endif
+#if defined(CONFIG_LEDS_LM3560) || !defined(CONFIG_USE_VENDER_FEATURE)
+       ext->flash_con.product_name = FLADRV_NAME_LM3560;
+#endif
+#ifdef CONFIG_LEDS_SKY81296
+       ext->flash_con.product_name = FLADRV_NAME_SKY81296;
+#endif
+       ext->flash_con.peri_type = SE_GPIO;
+#ifdef CONFIG_USE_VENDER_FEATURE
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 1;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 2;
+#else
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 2;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 3;
+#endif
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+#ifdef CONFIG_COMPANION_USE
+       ext->companion_con.product_name = COMPANION_NAME_73C1;
+       ext->companion_con.peri_info0.valid = true;
+       ext->companion_con.peri_info0.peri_type = SE_SPI;
+       ext->companion_con.peri_info0.peri_setting.spi.channel = (int) core->companion_spi_channel;
+       ext->companion_con.peri_info1.valid = true;
+       ext->companion_con.peri_info1.peri_type = SE_I2C;
+       ext->companion_con.peri_info1.peri_setting.i2c.channel = 0;
+       ext->companion_con.peri_info1.peri_setting.i2c.slave_address = 0x7A;
+       ext->companion_con.peri_info1.peri_setting.i2c.speed = 400000;
+       ext->companion_con.peri_info2.valid = true;
+       ext->companion_con.peri_info2.peri_type = SE_FIMC_LITE;
+       ext->companion_con.peri_info2.peri_setting.fimc_lite.channel = FLITE_ID_D;
+#else
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+#endif
+
+#if defined(CONFIG_OIS_USE)
+       ext->ois_con.product_name = OIS_NAME_IDG2030;
+       ext->ois_con.peri_type = SE_I2C;
+       ext->ois_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->ois_con.peri_setting.i2c.slave_address = 0x48;
+       ext->ois_con.peri_setting.i2c.speed = 400000;
+#else
+       ext->ois_con.product_name = OIS_NAME_NOTHING;
+       ext->ois_con.peri_type = SE_NULL;
+#endif
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p3.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-2p3.h
new file mode 100644 (file)
index 0000000..7e3791d
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_2P3_H
+#define FIMC_IS_DEVICE_2P3_H
+
+#define SENSOR_2P3_INSTANCE    0
+#define SENSOR_2P3_NAME                SENSOR_NAME_S5K2P3
+
+int sensor_2p3_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h5.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h5.c
new file mode 100644 (file)
index 0000000..8676a22
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-3h5.h"
+
+#define SENSOR_NAME "S5K3H5"
+
+static struct fimc_is_sensor_cfg config_3h5[] = {
+       /* 3264x2448@30fps */
+       FIMC_IS_SENSOR_CFG(3264, 2448, 30, 15, 0),
+};
+
+static int sensor_3h5_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_3h5_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_3h5_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K3H5_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K3H5;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K3H5_INSTANCE;
+       module->client = client;
+       module->active_width = 3248;
+       module->active_height = 2438;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K3H5";
+       module->setfile_name = "setfile_3h5.bin";
+       module->cfgs = ARRAY_SIZE(config_3h5);
+       module->cfg = config_3h5;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = 0;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x5A;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_HYBRIDVCA;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+
+       ext->flash_con.product_name = FLADRV_NAME_AAT1290A; /* == FLADRV_NAME_AAT1274 */
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 6;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 8;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h5.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h5.h
new file mode 100644 (file)
index 0000000..644e149
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_3H5_H
+#define FIMC_IS_DEVICE_3H5_H
+
+#define SENSOR_S5K3H5_INSTANCE 0
+#define SENSOR_S5K3H5_NAME     SENSOR_NAME_S5K3H5
+
+int sensor_3h5_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7.c
new file mode 100644 (file)
index 0000000..b4bfd2f
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-3h7.h"
+
+#define SENSOR_NAME "S5K3H7"
+
+static struct fimc_is_sensor_cfg config_3h7[] = {
+       /* 3280x2458@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 30, 15, 0),
+};
+
+static int sensor_3h7_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_3h7_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_3h7_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K3H7_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K3H7;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K3H7_INSTANCE;
+       module->client = client;
+       module->active_width = 3248;
+       module->active_height = 2438;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K3H7";
+       module->setfile_name = "setfile_3h7.bin";
+       module->cfgs = ARRAY_SIZE(config_3h7);
+       module->cfg = config_3h7;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = 0;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x20;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7343;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+
+       ext->flash_con.product_name = FLADRV_NAME_KTD267;
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 17;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 16;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7.h
new file mode 100644 (file)
index 0000000..d2a13f3
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_3H7_H
+#define FIMC_IS_DEVICE_3H7_H
+
+#define SENSOR_S5K3H7_INSTANCE 0
+#define SENSOR_S5K3H7_NAME     SENSOR_NAME_S5K3H7
+
+int sensor_3h7_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7_sunny.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7_sunny.c
new file mode 100644 (file)
index 0000000..52f6f88
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-3h7_sunny.h"
+
+#define SENSOR_NAME "S5K3H7_SUNNY"
+
+static struct fimc_is_sensor_cfg config_3h7_sunny[] = {
+       /* 3264x2448@30fps */
+       FIMC_IS_SENSOR_CFG(3264, 2448, 30, 15, 0),
+};
+
+static int sensor_3h7_sunny_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_3h7_sunny_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_3h7_sunny_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K3H7_SUNNY_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K3H7_SUNNY;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K3H7_SUNNY_INSTANCE;
+       module->client = client;
+       module->active_width = 3248;
+       module->active_height = 2438;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K3H7";
+       module->setfile_name = "setfile_3h7_sunny.bin";
+       module->cfgs = ARRAY_SIZE(config_3h7_sunny);
+       module->cfg = config_3h7_sunny;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = 0;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x20;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_DWXXXX;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x20;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+#if defined(CONFIG_EXYNOS5260_XYREF_REV0)
+       ext->flash_con.product_name = FLADRV_NAME_NOTHING;
+#else
+       ext->flash_con.product_name = FLADRV_NAME_AS3643;
+#endif
+       ext->flash_con.peri_type = SE_I2C;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 5;
+#if defined(CONFIG_MACH_XYREF4415)
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 6;
+#else
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 8;
+#endif
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7_sunny.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3h7_sunny.h
new file mode 100644 (file)
index 0000000..3e0d1c4
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_3H7_SUNNY_H
+#define FIMC_IS_DEVICE_3H7_SYNNY_H
+
+#define SENSOR_S5K3H7_SUNNY_INSTANCE   0
+#define SENSOR_S5K3H7_SUNNY_NAME       SENSOR_NAME_S5K3H7_SUNNY
+
+int sensor_3h7_sunny_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3l2.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3l2.c
new file mode 100644 (file)
index 0000000..21c5d04
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-3l2.h"
+
+#define SENSOR_NAME "S5K3L2"
+
+static struct fimc_is_sensor_cfg config_3l2[] = {
+       /* 4144x3106@30fps */
+       FIMC_IS_SENSOR_CFG(4144, 3106, 30, 25, 0),
+       /* 4144x2332@30fps */
+       FIMC_IS_SENSOR_CFG(4144, 2332, 30, 25, 1),
+       /* 2072x1554@24fps */
+       FIMC_IS_SENSOR_CFG(2072, 1554, 24, 25, 2),
+       /* 2072x1166@24fps */
+       FIMC_IS_SENSOR_CFG(2072, 1166, 24, 25, 3),
+       /* 1040x584@120fps */
+       FIMC_IS_SENSOR_CFG(1040, 584, 120, 17, 4),
+       /* 2072x1166@60fps */
+       FIMC_IS_SENSOR_CFG(2072, 1166, 60, 19, 5),
+};
+
+static int sensor_3l2_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_3l2_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_3l2_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K3L2_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K3L2;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K3L2_INSTANCE;
+       module->client = client;
+       module->active_width = 4128;
+       module->active_height = 3096;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 120;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K3L2";
+       module->setfile_name = "setfile_3l2.bin";
+       module->cfgs = ARRAY_SIZE(config_3l2);
+       module->cfg = config_3l2;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = SENSOR_NAME_S5K3L2;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x20;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_DWXXXX;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x20;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+       ext->flash_con.product_name = FLADRV_NAME_AS3643;
+       ext->flash_con.peri_type = SE_I2C;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 2;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 3;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3l2.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-3l2.h
new file mode 100644 (file)
index 0000000..816dbdd
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_3L2_H
+#define FIMC_IS_DEVICE_3L2_H
+
+#define SENSOR_S5K3L2_INSTANCE 0
+#define SENSOR_S5K3L2_NAME     SENSOR_NAME_S5K3L2
+
+int sensor_3l2_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4e5.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4e5.c
new file mode 100644 (file)
index 0000000..25b4443
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-4e5.h"
+
+#define SENSOR_NAME "S5K4E5"
+
+static int sensor_4e5_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_4e5_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_4e5_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K4E5_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K4E5;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K4E5_INSTANCE;
+       module->client = client;
+       module->pixel_width = 2560 + 16;
+       module->pixel_height = 1920 + 10;
+       module->active_width = 2560;
+       module->active_height = 1920;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K4E5";
+       module->setfile_name = "setfile_4e5.bin";
+       module->cfgs = 0;
+       module->cfg = NULL;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = 0;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_DWXXXX;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+
+       ext->flash_con.product_name = FLADRV_NAME_KTD267;
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 17;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 16;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4e5.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4e5.h
new file mode 100644 (file)
index 0000000..4d41ed0
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_4E5_H
+#define FIMC_IS_DEVICE_4E5_H
+
+#define SENSOR_S5K4E5_INSTANCE 0
+#define SENSOR_S5K4E5_NAME     SENSOR_NAME_S5K4E5
+
+int sensor_4e5_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4h5.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4h5.c
new file mode 100644 (file)
index 0000000..b12063b
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-4h5.h"
+
+#define SENSOR_NAME "S5K4H5"
+
+static struct fimc_is_sensor_cfg config_4h5[] = {
+       /* 3280x2458@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 30, 14, 0),
+       /* 3280x1846@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 30, 11, 1),
+       /* 1640x924@60fps */
+       FIMC_IS_SENSOR_CFG(1640, 924, 60, 14, 2),
+       /* 816x460@120fps */
+       FIMC_IS_SENSOR_CFG(816, 460, 120, 14, 3),
+};
+
+static int sensor_4h5_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_4h5_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_4h5_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K4H5_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_S5K4H5;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K4H5_INSTANCE;
+       module->ops = NULL;
+       module->client = client;
+       module->active_width = 3264;
+       module->active_height = 2448;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 120;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K4H5";
+       module->setfile_name = "setfile_4h5.bin";
+       module->cfgs = ARRAY_SIZE(config_4h5);
+       module->cfg = config_4h5;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = 0;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x6E;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_DW9804;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel
+               = SENSOR_CONTROL_I2C0;
+
+       ext->flash_con.product_name = FLADRV_NAME_RT5033;
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 8;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 6;
+
+       /* ext->from_con.product_name = FROMDRV_NAME_W25Q80BW; */
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+       ext->mclk = 0;
+       ext->mipi_lane_num = 0;
+       ext->mipi_speed = 0;
+       ext->fast_open_sensor = 0;
+       ext->self_calibration_mode = 0;
+       ext->I2CSclk = I2C_L0;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4h5.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-4h5.h
new file mode 100644 (file)
index 0000000..2407921
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_S5K4H5_H
+#define FIMC_IS_DEVICE_S5K4H5_H
+
+#define SENSOR_S5K4H5_INSTANCE 0
+#define SENSOR_S5K4H5_NAME     SENSOR_NAME_S5K4H5
+
+int sensor_4h5_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6a3.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6a3.c
new file mode 100644 (file)
index 0000000..5693f86
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-6a3.h"
+
+#define SENSOR_NAME "S5K6A3"
+
+static struct fimc_is_sensor_cfg config_6a3[] = {
+       /* 1412x796@30fps */
+       FIMC_IS_SENSOR_CFG(1412, 796, 30, 16, 0),
+};
+
+static int sensor_6a3_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_6a3_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_6a3_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       int enum_idx = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K6A3_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       enum_idx = atomic_read(&core->resourcemgr.rsccount_module);
+       module = &device->module_enum[enum_idx];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_S5K6A3_NAME;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K6A3_INSTANCE;
+       module->client = client;
+       module->active_width = 1392;
+       module->active_height = 1402;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_FRONT;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_1;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K6A3";
+       module->setfile_name = "setfile_6a3.bin";
+       module->cfgs = ARRAY_SIZE(config_6a3);
+       module->cfg = config_6a3;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+       ext->mipi_settle_line = 18;
+
+       ext->sensor_con.product_name = SENSOR_S5K6A3_NAME;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x20;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6a3.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6a3.h
new file mode 100644 (file)
index 0000000..bebfd88
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_6A3_H
+#define FIMC_IS_DEVICE_6A3_H
+
+#define SENSOR_S5K6A3_INSTANCE 1
+#define SENSOR_S5K6A3_NAME     SENSOR_NAME_S5K6A3
+
+int sensor_6a3_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6b2.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6b2.c
new file mode 100644 (file)
index 0000000..6db6c49
--- /dev/null
@@ -0,0 +1,785 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-6b2.h"
+
+#define SENSOR_NAME "S5K6B2"
+#define DEFAULT_SENSOR_WIDTH   184
+#define DEFAULT_SENSOR_HEIGHT  104
+#define SENSOR_MEMSIZE DEFAULT_SENSOR_WIDTH * DEFAULT_SENSOR_HEIGHT
+
+#define SENSOR_REG_VIS_DURATION_MSB                    (0x6026)
+#define SENSOR_REG_VIS_DURATION_LSB                    (0x6027)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_MSB       (0x4340)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_LSB       (0x4341)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_MSB                (0x4342)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_LSB                (0x4343)
+#define SENSOR_REG_VIS_GAIN_RED                                (0x6029)
+#define SENSOR_REG_VIS_GAIN_GREEN                      (0x602A)
+#define SENSOR_REG_VIS_AE_TARGET                       (0x600A)
+#define SENSOR_REG_VIS_AE_SPEED                                (0x5034)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_MSB          (0x5030)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_LSB          (0x5031)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x1_2          (0x6000)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x3_4          (0x6001)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x1_2          (0x6002)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x3_4          (0x6003)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x1_2          (0x6004)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x3_4          (0x6005)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x1_2          (0x6006)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x3_4          (0x6007)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_MSB               (0x5039)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_LSB               (0x503A)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_MSB               (0x503B)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_LSB               (0x503C)
+#define SENSOR_REG_VIS_BIT_CONVERTING_MSB              (0x602B)
+#define SENSOR_REG_VIS_BIT_CONVERTING_LSB              (0x7203)
+#define SENSOR_REG_VIS_AE_OFF                          (0x5000)
+
+static struct fimc_is_sensor_cfg config_6b2[] = {
+       /* 1936x1090@30fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 30, 16, 0),
+       /* 1936x1090@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 24, 13, 1),
+       /* 1296x730@30fps */
+       FIMC_IS_SENSOR_CFG(1296, 730, 30, 13, 2),
+};
+
+static int sensor_6b2_open(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_6b2_close(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_6b2_registered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+
+static void sensor_6b2_unregistered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+}
+
+static const struct v4l2_subdev_internal_ops internal_ops = {
+       .open = sensor_6b2_open,
+       .close = sensor_6b2_close,
+       .registered = sensor_6b2_registered,
+       .unregistered = sensor_6b2_unregistered,
+};
+
+static int sensor_6b2_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_module_6b2 *module_6b2;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       module_6b2 = module->private_data;
+       client = module->client;
+
+       module_6b2->system_clock = 146 * 1000 * 1000;
+       module_6b2->line_length_pck = 146 * 1000 * 1000;
+
+       pr_info("%s\n", __func__);
+       /* sensor init */
+       /* 8 bit mode */
+       fimc_is_sensor_write8(client, 0x7203, 0x40);
+       fimc_is_sensor_write8(client, 0x602B, 0x02);
+       fimc_is_sensor_write8(client, 0x702A, 0x3D);
+       fimc_is_sensor_write8(client, 0x702B, 0xB0);
+       fimc_is_sensor_write8(client, 0x7030, 0x0E);
+       fimc_is_sensor_write8(client, 0x7031, 0x2F);
+
+       /* Analog Tuning */
+       fimc_is_sensor_write8(client, 0x7067, 0x00);
+       fimc_is_sensor_write8(client, 0x7073, 0xFF);
+       fimc_is_sensor_write8(client, 0x7074, 0x22);
+
+       /* Dark Tuning */
+       fimc_is_sensor_write8(client, 0x7042, 0x1F);
+       fimc_is_sensor_write8(client, 0x7403, 0xC0);
+       fimc_is_sensor_write8(client, 0x7245, 0x04);
+       fimc_is_sensor_write8(client, 0x7205, 0xA1);
+
+       /* Remove Dark Band */
+       fimc_is_sensor_write8(client, 0x7430, 0x07);
+       fimc_is_sensor_write8(client, 0x705C, 0x7E);
+
+       /* Remove  Sun spot */
+       fimc_is_sensor_write8(client, 0x702C, 0x3C);
+       fimc_is_sensor_write8(client, 0x7075, 0x3D);
+
+       /* Remove CFPN */
+       fimc_is_sensor_write8(client, 0x7066, 0x0C);
+
+       /* AE setting */
+       fimc_is_sensor_write8(client, 0x6000, 0x44);
+       fimc_is_sensor_write8(client, 0x6001, 0x44);
+       fimc_is_sensor_write8(client, 0x6002, 0x44);
+       fimc_is_sensor_write8(client, 0x6003, 0x44);
+       fimc_is_sensor_write8(client, 0x6004, 0x44);
+       fimc_is_sensor_write8(client, 0x6005, 0x44);
+       fimc_is_sensor_write8(client, 0x6006, 0x44);
+       fimc_is_sensor_write8(client, 0x6007, 0x44);
+
+       /* AE target */
+       fimc_is_sensor_write8(client, 0x600A, 0xB4);
+
+       /* speed */
+       fimc_is_sensor_write8(client, 0x5034, 0x00);
+
+       /* Cintc_min */
+       fimc_is_sensor_write8(client, 0x5017, 0x01);
+
+       /* Number of pixel */
+       fimc_is_sensor_write8(client, 0x5030, 0x4A);
+       fimc_is_sensor_write8(client, 0x5031, 0xC0);
+
+       /* G + R Setting */
+       /* Vision Senser Data = 0.5*Gr + 0.5*R */
+       fimc_is_sensor_write8(client, 0x6029, 0x02);
+       fimc_is_sensor_write8(client, 0x602A, 0x02);
+
+       /* For Analog Gain 16x */
+       fimc_is_sensor_write8(client, 0x7018, 0xCF);
+       fimc_is_sensor_write8(client, 0x7019, 0xDB);
+       fimc_is_sensor_write8(client, 0x702A, 0x8D);
+       fimc_is_sensor_write8(client, 0x702B, 0x60);
+       fimc_is_sensor_write8(client, 0x5035, 0x02);
+
+       /* BIT_RATE_MBPS_alv */
+       fimc_is_sensor_write8(client, 0x7351, 0x02);
+       fimc_is_sensor_write8(client, 0x7352, 0x48);
+       fimc_is_sensor_write8(client, 0x7353, 0x00);
+       fimc_is_sensor_write8(client, 0x7354, 0x00);
+
+       fimc_is_sensor_write8(client, 0x7339, 0x03);
+
+       /* Analog gain */
+       fimc_is_sensor_write8(client, 0x4204, 0x00);
+       fimc_is_sensor_write8(client, 0x4205, 0x32);
+
+       /* frame rate - default 10fps*/
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_MSB, 0x00);
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_LSB, 0x6A);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_6b2_init
+};
+
+static int sensor_6b2_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (enable) {
+               ret = CALL_MOPS(sensor, stream_on, subdev);
+               if (ret) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       } else {
+               ret = CALL_MOPS(sensor, stream_off, subdev);
+               if (ret) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return 0;
+}
+
+static int sensor_6b2_s_param(struct v4l2_subdev *subdev, struct v4l2_streamparm *param)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct v4l2_captureparm *cp;
+       struct v4l2_fract *tpf;
+       u64 duration;
+
+       BUG_ON(!subdev);
+       BUG_ON(!param);
+
+       pr_info("%s\n", __func__);
+
+       cp = &param->parm.capture;
+       tpf = &cp->timeperframe;
+
+       if (!tpf->denominator) {
+               err("denominator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!tpf->numerator) {
+               err("numerator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       duration = (u64)(tpf->numerator * 1000 * 1000 * 1000) /
+                                       (u64)(tpf->denominator);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = CALL_MOPS(sensor, s_duration, subdev, duration);
+       if (ret) {
+               err("s_duration is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int sensor_6b2_s_format(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *fmt)
+{
+       /* TODO */
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = sensor_6b2_s_stream,
+       .s_parm = sensor_6b2_s_param,
+       .s_mbus_fmt = sensor_6b2_s_format
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops
+};
+
+int sensor_6b2_stream_on(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 1);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int sensor_6b2_stream_off(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 0);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+/*
+ * @ brief
+ * frame duration time
+ * @ unit
+ * nano second
+ * @ remarks
+ */
+int sensor_6b2_s_duration(struct v4l2_subdev *subdev, u64 duration)
+{
+       int ret = 0;
+       u8 value[2];
+       u32 framerate, result;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       framerate = 1000 * 1000 * 1000 / (u32)duration;
+       result = 1060 / framerate;
+       value[0] = result & 0xFF;
+       value[1] = (result >> 8) & 0xFF;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_MSB, value[1]);
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_LSB, value[0]);
+
+p_err:
+       return ret;
+}
+
+int sensor_6b2_g_min_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_g_max_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_s_exposure(struct v4l2_subdev *subdev, u64 exposure)
+{
+       int ret = 0;
+       u8 value;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s(%d)\n", __func__, (u32)exposure);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       value = exposure & 0xFF;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_AE_TARGET, value);
+
+p_err:
+       return ret;
+}
+
+int sensor_6b2_g_min_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_g_max_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_s_again(struct v4l2_subdev *subdev, u64 sensitivity)
+{
+       int ret = 0;
+
+       pr_info("%s\n", __func__);
+
+       return ret;
+}
+
+int sensor_6b2_g_min_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_g_max_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_s_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_g_min_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6b2_g_max_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+struct fimc_is_sensor_ops module_6b2_ops = {
+       .stream_on      = sensor_6b2_stream_on,
+       .stream_off     = sensor_6b2_stream_off,
+       .s_duration     = sensor_6b2_s_duration,
+       .g_min_duration = sensor_6b2_g_min_duration,
+       .g_max_duration = sensor_6b2_g_max_duration,
+       .s_exposure     = sensor_6b2_s_exposure,
+       .g_min_exposure = sensor_6b2_g_min_exposure,
+       .g_max_exposure = sensor_6b2_g_max_exposure,
+       .s_again        = sensor_6b2_s_again,
+       .g_min_again    = sensor_6b2_g_min_again,
+       .g_max_again    = sensor_6b2_g_max_again,
+       .s_dgain        = sensor_6b2_s_dgain,
+       .g_min_dgain    = sensor_6b2_g_min_dgain,
+       .g_max_dgain    = sensor_6b2_g_max_dgain
+};
+
+#ifdef CONFIG_OF
+static int sensor_6b2_power_setpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpio_none = 0;
+       int gpio_reset = 0, gpio_standby = 0;
+       int gpios_cam_en = 0;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               err("failed to get PIN_RESET");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+       if (!gpio_is_valid(gpios_cam_en)) {
+               err("failed to get front cam en gpio");
+       } else {
+               gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_cam_en);
+       }
+
+       gpio_standby = of_get_named_gpio(dnode, "gpio_standby", 0);
+       if (!gpio_is_valid(gpio_standby)) {
+               err("failed to get gpio_standby");
+       } else {
+               gpio_request_one(gpio_standby, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_standby);
+       }
+
+       /* FRONT CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* FRONT CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 1, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 4, gpio_standby, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 2, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 5, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#endif
+
+int sensor_6b2_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+       static bool probe_retried = false;
+
+       if (!fimc_is_dev)
+               goto probe_defer;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K6B2_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       /* S5K6B2 */
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_S5K6B2_NAME;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K6B2_INSTANCE;
+       module->ops = &module_6b2_ops;
+       module->client = client;
+       module->active_width = 1920;
+       module->active_height = 1080;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_FRONT;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_1;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K6B2";
+       module->setfile_name = "setfile_6b2.bin";
+       module->cfgs = ARRAY_SIZE(config_6b2);
+       module->cfg = config_6b2;
+       module->private_data = kzalloc(sizeof(struct fimc_is_module_6b2), GFP_KERNEL);
+       if (!module->private_data) {
+               err("private_data is NULL");
+               ret = -ENOMEM;
+               kfree(subdev_module);
+               goto p_err;
+       }
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_6b2_power_setpin;
+#endif
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+       ext->sensor_con.product_name = SENSOR_NAME_S5K6B2;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client) {
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+               subdev_module->internal_ops = &internal_ops;
+       } else {
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+       }
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+
+probe_defer:
+       if (probe_retried) {
+               err("probe has already been retried!!");
+               BUG();
+       }
+
+       probe_retried = true;
+       err("core device is not yet probed");
+       return -EPROBE_DEFER;
+}
+
+static int sensor_6b2_remove(struct i2c_client *client)
+{
+       int ret = 0;
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_sensor_6b2_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-sensor-6b2",
+       },
+       {},
+};
+#endif
+
+static const struct i2c_device_id sensor_6b2_idt[] = {
+       { SENSOR_NAME, 0 },
+};
+
+static struct i2c_driver sensor_6b2_driver = {
+       .driver = {
+               .name   = SENSOR_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = exynos_fimc_is_sensor_6b2_match
+#endif
+       },
+       .probe  = sensor_6b2_probe,
+       .remove = sensor_6b2_remove,
+       .id_table = sensor_6b2_idt
+};
+
+static int __init sensor_6b2_load(void)
+{
+        return i2c_add_driver(&sensor_6b2_driver);
+}
+
+static void __exit sensor_6b2_unload(void)
+{
+        i2c_del_driver(&sensor_6b2_driver);
+}
+
+module_init(sensor_6b2_load);
+module_exit(sensor_6b2_unload);
+
+MODULE_AUTHOR("Gilyeon lim");
+MODULE_DESCRIPTION("Sensor 6B2 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6b2.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6b2.h
new file mode 100644 (file)
index 0000000..284f08a
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_6B2_H
+#define FIMC_IS_DEVICE_6B2_H
+
+#define SENSOR_S5K6B2_INSTANCE 1
+#define SENSOR_S5K6B2_NAME     SENSOR_NAME_S5K6B2
+
+struct fimc_is_module_6b2 {
+       u16             vis_duration;
+       u16             frame_length_line;
+       u32             line_length_pck;
+       u32             system_clock;
+};
+
+int sensor_6b2_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6d1.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6d1.c
new file mode 100644 (file)
index 0000000..82ba540
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-6d1.h"
+
+#define SENSOR_NAME "S5K6D1"
+#define DEFAULT_SENSOR_WIDTH   184
+#define DEFAULT_SENSOR_HEIGHT  104
+#define SENSOR_MEMSIZE DEFAULT_SENSOR_WIDTH * DEFAULT_SENSOR_HEIGHT
+
+#define SENSOR_REG_VIS_DURATION_MSB                    (0x6026)
+#define SENSOR_REG_VIS_DURATION_LSB                    (0x6027)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_MSB       (0x4340)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_LSB       (0x4341)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_MSB                (0x4342)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_LSB                (0x4343)
+#define SENSOR_REG_VIS_GAIN_RED                                (0x6029)
+#define SENSOR_REG_VIS_GAIN_GREEN                      (0x602A)
+#define SENSOR_REG_VIS_AE_TARGET                       (0x600A)
+#define SENSOR_REG_VIS_AE_SPEED                                (0x5034)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_MSB          (0x5030)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_LSB          (0x5031)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x1_2          (0x6000)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x3_4          (0x6001)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x1_2          (0x6002)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x3_4          (0x6003)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x1_2          (0x6004)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x3_4          (0x6005)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x1_2          (0x6006)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x3_4          (0x6007)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_MSB               (0x5039)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_LSB               (0x503A)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_MSB               (0x503B)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_LSB               (0x503C)
+#define SENSOR_REG_VIS_BIT_CONVERTING_MSB              (0x602B)
+#define SENSOR_REG_VIS_BIT_CONVERTING_LSB              (0x7203)
+#define SENSOR_REG_VIS_AE_OFF                          (0x5000)
+
+static u16 setfile_vision_6d1[][2] = {
+       {0x4200, 0x02},
+       {0x4201, 0xAE},
+       {0x4301, 0x04},
+       {0x4309, 0x04},
+       {0x4345, 0x08},
+       {0x4347, 0x08},
+       {0x4348, 0x0A},
+       {0x4349, 0x01},
+       {0x434A, 0x05},
+       {0x434B, 0xA0},
+       {0x434C, 0x01},
+       {0x434D, 0x40},
+       {0x434E, 0x00},
+       {0x434F, 0xB4},
+       {0x4381, 0x01},
+       {0x4383, 0x07},
+       {0x4385, 0x08},
+       {0x4387, 0x08},
+       {0x5004, 0x01},
+       {0x5005, 0x1E},
+       {0x5014, 0x11},
+       {0x5015, 0x9E},
+       {0x5016, 0x00},
+       {0x5017, 0x02},
+       {0x5030, 0x1C},
+       {0x5031, 0x20},
+       {0x5034, 0x00},
+       {0x5035, 0x02},
+       {0x5036, 0x00},
+       {0x5037, 0x06},
+       {0x5038, 0xC0},
+       {0x5039, 0x00},
+       {0x503A, 0x00},
+       {0x503B, 0x00},
+       {0x503C, 0x00},
+       {0x503D, 0x20},
+       {0x503E, 0x70},
+       {0x503F, 0x02},
+       {0x600A, 0x2A},
+       {0x600E, 0x05},
+       {0x6014, 0x27},
+       {0x6015, 0x1D},
+       {0x6018, 0x01},
+       {0x6026, 0x00},
+       {0x6027, 0x68},
+       {0x6029, 0x08},
+       {0x602A, 0x08},
+       {0x602B, 0x00},
+       {0x602C, 0x00},
+       {0x7008, 0x00},
+       {0x7009, 0x10},
+       {0x700A, 0x00},
+       {0x700B, 0x10},
+       {0x7014, 0x2B},
+       {0x7015, 0x91},
+       {0x7016, 0x82},
+       {0x701B, 0x16},
+       {0x701D, 0x0B},
+       {0x701F, 0x0B},
+       {0x7026, 0x1A},
+       {0x7027, 0x46},
+       {0x7029, 0x14},
+       {0x702A, 0x02},
+       {0x7038, 0x01},
+       {0x7039, 0x14},
+       {0x703A, 0x32},
+       {0x703B, 0x22},
+       {0x7040, 0x01},
+       {0x7041, 0x14},
+       {0x7042, 0x32},
+       {0x7043, 0x22},
+       {0x7050, 0x0A},
+       {0x7051, 0xA8},
+       {0x7052, 0x35},
+       {0x7053, 0x54},
+       {0x7054, 0x00},
+       {0x7055, 0x00},
+       {0x7056, 0x00},
+       {0x7057, 0x00},
+       {0x705E, 0x0E},
+       {0x705F, 0x10},
+       {0x7060, 0x01},
+       {0x7064, 0x05},
+       {0x7065, 0x3C},
+       {0x7066, 0x00},
+       {0x7067, 0x00},
+       {0x7068, 0x4A},
+       {0x706C, 0x01},
+       {0x7077, 0x88},
+       {0x7078, 0x88},
+       {0x7082, 0x90},
+       {0x7091, 0x05},
+       {0x7098, 0x00},
+       {0x7112, 0x01},
+       {0x720A, 0x06},
+       {0x720B, 0x80},
+       {0x7245, 0xC1},
+       {0x7301, 0x01},
+       {0x7305, 0x13},
+       {0x7306, 0x01},
+       {0x7323, 0x01},
+       {0x7339, 0x07},
+       {0x7351, 0x01},
+       {0x7352, 0x24},
+       {0x7405, 0x28},
+       {0x7406, 0x28},
+       {0x7407, 0xC0},
+       {0x7454, 0x01},
+       {0x7460, 0x01},
+       {0x7461, 0x20},
+       {0x7462, 0xC0},
+       {0x7463, 0x1E},
+       {0x7464, 0x02},
+       {0x7465, 0x4B},
+       {0x7467, 0x20},
+       {0x7468, 0x20},
+       {0x7469, 0x20},
+       {0x746A, 0x20},
+       {0x746B, 0x20},
+       {0x746C, 0x20},
+       {0x746D, 0x09},
+       {0x746E, 0xFF},
+       {0x746F, 0x01},
+       {0x7472, 0x00},
+       {0x7473, 0x02},
+       {0x7474, 0xC1},
+       {0x7475, 0x00},
+       {0x7476, 0x00},
+       {0x7477, 0x00},
+       {0x7478, 0x00},
+       {0x4100, 0x01},
+};
+
+static struct fimc_is_sensor_cfg config_6d1[] = {
+       /* 2576x1456@30fps */
+       FIMC_IS_SENSOR_CFG(2576, 1456, 30, 14, 0),
+       /* 2576x1456@24fps */
+       FIMC_IS_SENSOR_CFG(2576, 1456, 24, 14, 1),
+#if 0
+       /* 1924x1082@30fps */
+       FIMC_IS_SENSOR_CFG(1924, 1082, 30, 16, 1),
+       /* 1444x1082@30fps */
+       FIMC_IS_SENSOR_CFG(1444, 1082, 30, 16, 2),
+       /* 1084x1082@30fps */
+       FIMC_IS_SENSOR_CFG(1084, 1082, 30, 16, 3),
+       /* 964x542@30fps */
+       FIMC_IS_SENSOR_CFG(964, 542, 30, 16, 4),
+       /* 724x542@30fps */
+       FIMC_IS_SENSOR_CFG(724, 542, 30, 16, 5),
+       /* 544x542@30fps */
+       FIMC_IS_SENSOR_CFG(544, 542, 30, 16, 6),
+       /* 320x180@10fps : only for vision(settle) */
+       FIMC_IS_SENSOR_CFG(320, 180, 10, 4, 6),
+       /* 1936x1090@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 24, 13, 7),
+#endif
+};
+
+static int sensor_6d1_open(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_6d1_close(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_6d1_registered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+
+static void sensor_6d1_unregistered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+}
+
+static const struct v4l2_subdev_internal_ops internal_ops = {
+       .open = sensor_6d1_open,
+       .close = sensor_6d1_close,
+       .registered = sensor_6d1_registered,
+       .unregistered = sensor_6d1_unregistered,
+};
+
+static int sensor_6d1_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int i, ret = 0;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_module_6d1 *module_6d1;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       module_6d1 = module->private_data;
+       client = module->client;
+
+       module_6d1->system_clock = 146 * 1000 * 1000;
+       module_6d1->line_length_pck = 146 * 1000 * 1000;
+
+       pr_info("%s\n", __func__);
+
+       /* sensor init */
+       for (i = 0; i < ARRAY_SIZE(setfile_vision_6d1); i++) {
+               fimc_is_sensor_write8(client, setfile_vision_6d1[i][0],
+                               (u8)setfile_vision_6d1[i][1]);
+       }
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_6d1_init
+};
+
+static int sensor_6d1_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (enable) {
+               ret = CALL_MOPS(sensor, stream_on, subdev);
+               if (ret < 0) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       } else {
+               ret = CALL_MOPS(sensor, stream_off, subdev);
+               if (ret < 0) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return 0;
+}
+
+static int sensor_6d1_s_param(struct v4l2_subdev *subdev, struct v4l2_streamparm *param)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct v4l2_captureparm *cp;
+       struct v4l2_fract *tpf;
+       u64 duration;
+
+       BUG_ON(!subdev);
+       BUG_ON(!param);
+
+       pr_info("%s\n", __func__);
+
+       cp = &param->parm.capture;
+       tpf = &cp->timeperframe;
+
+       if (!tpf->denominator) {
+               err("denominator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!tpf->numerator) {
+               err("numerator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       duration = (u64)(tpf->numerator * 1000 * 1000 * 1000) /
+                                       (u64)(tpf->denominator);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = CALL_MOPS(sensor, s_duration, subdev, duration);
+       if (ret) {
+               err("s_duration is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int sensor_6d1_s_format(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *fmt)
+{
+       /* TODO */
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = sensor_6d1_s_stream,
+       .s_parm = sensor_6d1_s_param,
+       .s_mbus_fmt = sensor_6d1_s_format
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops
+};
+
+int sensor_6d1_stream_on(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 1);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int sensor_6d1_stream_off(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 0);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+/*
+ * @ brief
+ * frame duration time
+ * @ unit
+ * nano second
+ * @ remarks
+ */
+int sensor_6d1_s_duration(struct v4l2_subdev *subdev, u64 duration)
+{
+       int ret = 0;
+       u8 value[2];
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /*
+        * forcely set 10fps for 6d1,
+        */
+       value[0] = 0x52;
+       value[1] = 0x0;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_MSB, value[1]);
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_LSB, value[0]);
+
+p_err:
+       return ret;
+}
+
+int sensor_6d1_g_min_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_g_max_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_s_exposure(struct v4l2_subdev *subdev, u64 exposure)
+{
+       int ret = 0;
+       u8 value;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s(%d)\n", __func__, (u32)exposure);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       value = exposure & 0xFF;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_AE_TARGET, value);
+
+p_err:
+       return ret;
+}
+
+int sensor_6d1_g_min_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_g_max_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_s_again(struct v4l2_subdev *subdev, u64 sensitivity)
+{
+       int ret = 0;
+
+       pr_info("%s\n", __func__);
+
+       return ret;
+}
+
+int sensor_6d1_g_min_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_g_max_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_s_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_g_min_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_6d1_g_max_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+struct fimc_is_sensor_ops module_6d1_ops = {
+       .stream_on      = sensor_6d1_stream_on,
+       .stream_off     = sensor_6d1_stream_off,
+       .s_duration     = sensor_6d1_s_duration,
+       .g_min_duration = sensor_6d1_g_min_duration,
+       .g_max_duration = sensor_6d1_g_max_duration,
+       .s_exposure     = sensor_6d1_s_exposure,
+       .g_min_exposure = sensor_6d1_g_min_exposure,
+       .g_max_exposure = sensor_6d1_g_max_exposure,
+       .s_again        = sensor_6d1_s_again,
+       .g_min_again    = sensor_6d1_g_min_again,
+       .g_max_again    = sensor_6d1_g_max_again,
+       .s_dgain        = sensor_6d1_s_dgain,
+       .g_min_dgain    = sensor_6d1_g_min_dgain,
+       .g_max_dgain    = sensor_6d1_g_max_dgain
+};
+
+#ifdef CONFIG_OF
+static int sensor_6d1_power_setpin(struct device *dev)
+{
+       int gpio_none = 0, gpio_reset = 0, gpio_standby = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       struct pinctrl *pinctrl_ch = NULL;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpio_standby = of_get_named_gpio(dnode, "gpio_standby", 0);
+       if (!gpio_is_valid(gpio_standby)) {
+               dev_err(dev, "failed to get gpio_standby\n");
+       } else {
+               gpio_request_one(gpio_standby, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_standby);
+       }
+
+       /* initial - i2c off */
+       pinctrl_ch = devm_pinctrl_get_select(dev, "off1");
+       if (IS_ERR_OR_NULL(pinctrl_ch)) {
+               pr_err("%s: cam %s pins are not configured\n", __func__, "off1");
+       } else {
+               devm_pinctrl_put(pinctrl_ch);
+       }
+
+       /* FRONT CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* FRONT CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 4, gpio_standby, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 2, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#endif
+
+int sensor_6d1_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+       static bool probe_retried = false;
+
+       if (!fimc_is_dev)
+               goto probe_defer;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K6D1_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       /* S5K6D1 */
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_S5K6D1_NAME;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K6D1_INSTANCE;
+       module->ops = &module_6d1_ops;
+       module->client = client;
+       module->active_width = 2560;
+       module->active_height = 1446;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_FRONT;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_2;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K6D1";
+       module->setfile_name = "setfile_6d1.bin";
+       module->cfgs = ARRAY_SIZE(config_6d1);
+       module->cfg = config_6d1;
+       module->private_data = kzalloc(sizeof(struct fimc_is_module_6d1), GFP_KERNEL);
+       if (!module->private_data) {
+               err("private_data is NULL");
+               ret = -ENOMEM;
+               kfree(subdev_module);
+               goto p_err;
+       }
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_6d1_power_setpin;
+#endif
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+       ext->sensor_con.product_name = SENSOR_NAME_S5K6D1;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client) {
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+               subdev_module->internal_ops = &internal_ops;
+       } else {
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+       }
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+
+probe_defer:
+       if (probe_retried) {
+               err("probe has already been retried!!");
+               BUG();
+       }
+
+       probe_retried = true;
+       err("core device is not yet probed");
+       return -EPROBE_DEFER;
+}
+
+static int sensor_6d1_remove(struct i2c_client *client)
+{
+       int ret = 0;
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_sensor_6d1_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-sensor-6d1",
+       },
+       {},
+};
+#endif
+
+static const struct i2c_device_id sensor_6d1_idt[] = {
+       { SENSOR_NAME, 0 },
+};
+
+static struct i2c_driver sensor_6d1_driver = {
+       .driver = {
+               .name   = SENSOR_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = exynos_fimc_is_sensor_6d1_match
+#endif
+       },
+       .probe  = sensor_6d1_probe,
+       .remove = sensor_6d1_remove,
+       .id_table = sensor_6d1_idt
+};
+
+static int __init sensor_6d1_load(void)
+{
+        return i2c_add_driver(&sensor_6d1_driver);
+}
+
+static void __exit sensor_6d1_unload(void)
+{
+        i2c_del_driver(&sensor_6d1_driver);
+}
+
+module_init(sensor_6d1_load);
+module_exit(sensor_6d1_unload);
+
+MODULE_AUTHOR("Gilyeon lim");
+MODULE_DESCRIPTION("Sensor 6D1 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6d1.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-6d1.h
new file mode 100644 (file)
index 0000000..c6c46ca
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_6D1_H
+#define FIMC_IS_DEVICE_6D1_H
+
+#define SENSOR_S5K6D1_INSTANCE 1
+#define SENSOR_S5K6D1_NAME     SENSOR_NAME_S5K6D1
+
+struct fimc_is_module_6d1 {
+       u16             vis_duration;
+       u16             frame_length_line;
+       u32             line_length_pck;
+       u32             system_clock;
+};
+
+int sensor_6d1_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-8b1.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-8b1.c
new file mode 100644 (file)
index 0000000..936bf4c
--- /dev/null
@@ -0,0 +1,850 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-8b1.h"
+
+#define SENSOR_NAME "S5K8B1"
+#define DEFAULT_SENSOR_WIDTH   184
+#define DEFAULT_SENSOR_HEIGHT  104
+#define SENSOR_MEMSIZE DEFAULT_SENSOR_WIDTH * DEFAULT_SENSOR_HEIGHT
+
+#define SENSOR_REG_VIS_DURATION_MSB                    (0x6026)
+#define SENSOR_REG_VIS_DURATION_LSB                    (0x6027)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_MSB       (0x4340)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_LSB       (0x4341)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_MSB                (0x4342)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_LSB                (0x4343)
+#define SENSOR_REG_VIS_GAIN_RED                                (0x6029)
+#define SENSOR_REG_VIS_GAIN_GREEN                      (0x602A)
+#define SENSOR_REG_VIS_AE_TARGET                       (0x600A)
+#define SENSOR_REG_VIS_AE_SPEED                                (0x5034)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_MSB          (0x5030)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_LSB          (0x5031)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x1_2          (0x6000)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x3_4          (0x6001)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x1_2          (0x6002)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x3_4          (0x6003)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x1_2          (0x6004)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x3_4          (0x6005)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x1_2          (0x6006)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x3_4          (0x6007)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_MSB               (0x5039)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_LSB               (0x503A)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_MSB               (0x503B)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_LSB               (0x503C)
+#define SENSOR_REG_VIS_BIT_CONVERTING_MSB              (0x602B)
+#define SENSOR_REG_VIS_BIT_CONVERTING_LSB              (0x7203)
+#define SENSOR_REG_VIS_AE_OFF                          (0x5000)
+
+static struct fimc_is_sensor_cfg config_8b1[] = {
+       /* 1936x1090@30fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 30, 16, 0),
+       /* 1924x1082@30fps */
+       FIMC_IS_SENSOR_CFG(1924, 1082, 30, 16, 1),
+       /* 1444x1082@30fps */
+       FIMC_IS_SENSOR_CFG(1444, 1082, 30, 16, 2),
+       /* 1084x1082@30fps */
+       FIMC_IS_SENSOR_CFG(1084, 1082, 30, 16, 3),
+       /* 964x542@30fps */
+       FIMC_IS_SENSOR_CFG(964, 542, 30, 16, 4),
+       /* 724x542@30fps */
+       FIMC_IS_SENSOR_CFG(724, 542, 30, 16, 5),
+       /* 544x542@30fps */
+       FIMC_IS_SENSOR_CFG(544, 542, 30, 16, 6),
+       /* 320x180@10fps : only for vision(settle) */
+       FIMC_IS_SENSOR_CFG(320, 180, 10, 4, 6),
+       /* 1936x1090@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 24, 13, 7),
+};
+
+static int sensor_8b1_open(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_8b1_close(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_8b1_registered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+
+static void sensor_8b1_unregistered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+}
+
+static const struct v4l2_subdev_internal_ops internal_ops = {
+       .open = sensor_8b1_open,
+       .close = sensor_8b1_close,
+       .registered = sensor_8b1_registered,
+       .unregistered = sensor_8b1_unregistered,
+};
+
+static int sensor_8b1_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_module_8b1 *module_8b1;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       module_8b1 = module->private_data;
+       client = module->client;
+
+       module_8b1->system_clock = 146 * 1000 * 1000;
+       module_8b1->line_length_pck = 146 * 1000 * 1000;
+
+       pr_info("%s\n", __func__);
+       /* sensor init */
+       fimc_is_sensor_write8(client, 0x4200, 0x01);
+       fimc_is_sensor_write8(client, 0x4201, 0x24);
+       fimc_is_sensor_write8(client, 0x4305, 0x06);
+       fimc_is_sensor_write8(client, 0x4307, 0xC0);
+       fimc_is_sensor_write8(client, 0x4342, 0x03);
+
+       fimc_is_sensor_write8(client, 0x4343, 0x90);
+       fimc_is_sensor_write8(client, 0x4345, 0x08);
+       fimc_is_sensor_write8(client, 0x4347, 0x08);
+       fimc_is_sensor_write8(client, 0x4348, 0x07);
+       fimc_is_sensor_write8(client, 0x4349, 0x83); /* 10 */
+
+       fimc_is_sensor_write8(client, 0x434A, 0x04);
+       fimc_is_sensor_write8(client, 0x434B, 0x3A);
+       fimc_is_sensor_write8(client, 0x434C, 0x01);
+       fimc_is_sensor_write8(client, 0x434D, 0x40);
+       fimc_is_sensor_write8(client, 0x434E, 0x00);
+
+       fimc_is_sensor_write8(client, 0x434F, 0xB4);
+       fimc_is_sensor_write8(client, 0x4381, 0x01);
+       fimc_is_sensor_write8(client, 0x4383, 0x05);
+       fimc_is_sensor_write8(client, 0x4385, 0x06);
+       fimc_is_sensor_write8(client, 0x4387, 0x06); /* 20 */
+
+       fimc_is_sensor_write8(client, 0x5004, 0x01);
+       fimc_is_sensor_write8(client, 0x5005, 0x1E);
+#ifdef VISION_30FPS
+       fimc_is_sensor_write8(client, 0x5014, 0x05);
+       fimc_is_sensor_write8(client, 0x5015, 0x73);
+#else
+       fimc_is_sensor_write8(client, 0x5014, 0x13);
+       fimc_is_sensor_write8(client, 0x5015, 0x33);
+#endif
+       fimc_is_sensor_write8(client, 0x5016, 0x00);
+
+       fimc_is_sensor_write8(client, 0x5017, 0x02);
+       fimc_is_sensor_write8(client, 0x5030, 0x0E);
+       fimc_is_sensor_write8(client, 0x5031, 0x10);
+       fimc_is_sensor_write8(client, 0x5034, 0x00);
+       fimc_is_sensor_write8(client, 0x5035, 0x02); /* 30 */
+
+       fimc_is_sensor_write8(client, 0x5036, 0x00);
+       fimc_is_sensor_write8(client, 0x5037, 0x04);
+       fimc_is_sensor_write8(client, 0x5038, 0xC0);
+       fimc_is_sensor_write8(client, 0x503D, 0x20);
+       fimc_is_sensor_write8(client, 0x503E, 0x70);
+
+       fimc_is_sensor_write8(client, 0x503F, 0x02);
+       fimc_is_sensor_write8(client, 0x600A, 0x3A);
+       fimc_is_sensor_write8(client, 0x600E, 0x05);
+       fimc_is_sensor_write8(client, 0x6014, 0x27);
+       fimc_is_sensor_write8(client, 0x6015, 0x1D); /* 40 */
+
+       fimc_is_sensor_write8(client, 0x6018, 0x01);
+       fimc_is_sensor_write8(client, 0x6026, 0x00);
+#ifdef VISION_30FPS
+       fimc_is_sensor_write8(client, 0x6027, 0x1B);
+#else
+       fimc_is_sensor_write8(client, 0x6027, 0x52);
+#endif
+       fimc_is_sensor_write8(client, 0x6029, 0x08);
+       fimc_is_sensor_write8(client, 0x602A, 0x08);
+
+       fimc_is_sensor_write8(client, 0x602B, 0x00);
+       fimc_is_sensor_write8(client, 0x602c, 0x00);
+       fimc_is_sensor_write8(client, 0x6032, 0x63);
+       fimc_is_sensor_write8(client, 0x6033, 0x94);
+       fimc_is_sensor_write8(client, 0x7007, 0x18); /* 50 */
+
+       fimc_is_sensor_write8(client, 0x7015, 0x28);
+       fimc_is_sensor_write8(client, 0x7016, 0x2C);
+       fimc_is_sensor_write8(client, 0x7027, 0x14);
+       fimc_is_sensor_write8(client, 0x7028, 0x3C);
+       fimc_is_sensor_write8(client, 0x7029, 0x02);
+
+       fimc_is_sensor_write8(client, 0x702A, 0x02);
+       fimc_is_sensor_write8(client, 0x703A, 0x04);
+       fimc_is_sensor_write8(client, 0x703B, 0x36);
+       fimc_is_sensor_write8(client, 0x7042, 0x04);
+       fimc_is_sensor_write8(client, 0x7043, 0x36); /* 60 */
+
+       fimc_is_sensor_write8(client, 0x7058, 0x6F);
+       fimc_is_sensor_write8(client, 0x705A, 0x01);
+       fimc_is_sensor_write8(client, 0x705C, 0x40);
+       fimc_is_sensor_write8(client, 0x7060, 0x07);
+       fimc_is_sensor_write8(client, 0x7061, 0x40);
+
+       fimc_is_sensor_write8(client, 0x7064, 0x43);
+       fimc_is_sensor_write8(client, 0x706D, 0x77);
+       fimc_is_sensor_write8(client, 0x706E, 0xFA);
+       fimc_is_sensor_write8(client, 0x7070, 0x0A);
+       fimc_is_sensor_write8(client, 0x7073, 0x04); /* 70 */
+
+       fimc_is_sensor_write8(client, 0x7087, 0x00);
+       fimc_is_sensor_write8(client, 0x7090, 0x01);
+       fimc_is_sensor_write8(client, 0x7115, 0x01);
+       fimc_is_sensor_write8(client, 0x7209, 0xF5);
+       fimc_is_sensor_write8(client, 0x720B, 0xF5);
+
+       fimc_is_sensor_write8(client, 0x7245, 0xC4);
+       fimc_is_sensor_write8(client, 0x7301, 0x02);
+       fimc_is_sensor_write8(client, 0x7306, 0x02);
+       fimc_is_sensor_write8(client, 0x7339, 0x03);
+       fimc_is_sensor_write8(client, 0x7351, 0x00); /* 80 */
+
+       fimc_is_sensor_write8(client, 0x7352, 0xC0);
+       fimc_is_sensor_write8(client, 0x7405, 0x28);
+       fimc_is_sensor_write8(client, 0x7406, 0x28);
+       fimc_is_sensor_write8(client, 0x7407, 0xC0);
+       fimc_is_sensor_write8(client, 0x740C, 0x60);
+
+       fimc_is_sensor_write8(client, 0x740D, 0x00);
+       fimc_is_sensor_write8(client, 0x7436, 0x03);
+       fimc_is_sensor_write8(client, 0x7437, 0x03);
+       fimc_is_sensor_write8(client, 0x7454, 0x01);
+       fimc_is_sensor_write8(client, 0x7460, 0x00); /* 90 */
+
+       fimc_is_sensor_write8(client, 0x7461, 0x01);
+       fimc_is_sensor_write8(client, 0x7462, 0x68);
+       fimc_is_sensor_write8(client, 0x7463, 0x1E);
+       fimc_is_sensor_write8(client, 0x7464, 0x03);
+       fimc_is_sensor_write8(client, 0x7465, 0x4B);
+
+       fimc_is_sensor_write8(client, 0x7467, 0x20);
+       fimc_is_sensor_write8(client, 0x7468, 0x20);
+       fimc_is_sensor_write8(client, 0x7469, 0x20);
+       fimc_is_sensor_write8(client, 0x746A, 0x20);
+       fimc_is_sensor_write8(client, 0x746B, 0x20); /* 100 */
+
+       fimc_is_sensor_write8(client, 0x746C, 0x20);
+       fimc_is_sensor_write8(client, 0x746D, 0x02);
+       fimc_is_sensor_write8(client, 0x746E, 0x80);
+       fimc_is_sensor_write8(client, 0x746F, 0x01);
+       fimc_is_sensor_write8(client, 0x4100, 0x01);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_8b1_init
+};
+
+static int sensor_8b1_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (enable) {
+               ret = CALL_MOPS(sensor, stream_on, subdev);
+               if (ret) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       } else {
+               ret = CALL_MOPS(sensor, stream_off, subdev);
+               if (ret) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return 0;
+}
+
+static int sensor_8b1_s_param(struct v4l2_subdev *subdev, struct v4l2_streamparm *param)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct v4l2_captureparm *cp;
+       struct v4l2_fract *tpf;
+       u64 duration;
+
+       BUG_ON(!subdev);
+       BUG_ON(!param);
+
+       pr_info("%s\n", __func__);
+
+       cp = &param->parm.capture;
+       tpf = &cp->timeperframe;
+
+       if (!tpf->denominator) {
+               err("denominator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!tpf->numerator) {
+               err("numerator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       duration = (u64)(tpf->numerator * 1000 * 1000 * 1000) /
+                                       (u64)(tpf->denominator);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = CALL_MOPS(sensor, s_duration, subdev, duration);
+       if (ret) {
+               err("s_duration is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int sensor_8b1_s_format(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *fmt)
+{
+       /* TODO */
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = sensor_8b1_s_stream,
+       .s_parm = sensor_8b1_s_param,
+       .s_mbus_fmt = sensor_8b1_s_format
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops
+};
+
+int sensor_8b1_stream_on(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 1);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int sensor_8b1_stream_off(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 0);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+/*
+ * @ brief
+ * frame duration time
+ * @ unit
+ * nano second
+ * @ remarks
+ */
+int sensor_8b1_s_duration(struct v4l2_subdev *subdev, u64 duration)
+{
+       int ret = 0;
+       u8 value[2];
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /*
+        * forcely set 10fps for 8b1,
+        */
+       value[0] = 0x52;
+       value[1] = 0x0;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_MSB, value[1]);
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_LSB, value[0]);
+
+p_err:
+       return ret;
+}
+
+int sensor_8b1_g_min_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_g_max_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_s_exposure(struct v4l2_subdev *subdev, u64 exposure)
+{
+       int ret = 0;
+       u8 value;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s(%d)\n", __func__, (u32)exposure);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       value = exposure & 0xFF;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_AE_TARGET, value);
+
+p_err:
+       return ret;
+}
+
+int sensor_8b1_g_min_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_g_max_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_s_again(struct v4l2_subdev *subdev, u64 sensitivity)
+{
+       int ret = 0;
+
+       pr_info("%s\n", __func__);
+
+       return ret;
+}
+
+int sensor_8b1_g_min_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_g_max_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_s_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_g_min_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_8b1_g_max_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+struct fimc_is_sensor_ops module_8b1_ops = {
+       .stream_on      = sensor_8b1_stream_on,
+       .stream_off     = sensor_8b1_stream_off,
+       .s_duration     = sensor_8b1_s_duration,
+       .g_min_duration = sensor_8b1_g_min_duration,
+       .g_max_duration = sensor_8b1_g_max_duration,
+       .s_exposure     = sensor_8b1_s_exposure,
+       .g_min_exposure = sensor_8b1_g_min_exposure,
+       .g_max_exposure = sensor_8b1_g_max_exposure,
+       .s_again        = sensor_8b1_s_again,
+       .g_min_again    = sensor_8b1_g_min_again,
+       .g_max_again    = sensor_8b1_g_max_again,
+       .s_dgain        = sensor_8b1_s_dgain,
+       .g_min_dgain    = sensor_8b1_g_min_dgain,
+       .g_max_dgain    = sensor_8b1_g_max_dgain
+};
+
+#ifdef CONFIG_OF
+static int sensor_8b1_power_setpin(struct device *dev)
+{
+       int gpio_none = 0, gpio_reset = 0, gpio_standby = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpios_cam_en = 0;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+       if (!gpio_is_valid(gpios_cam_en)) {
+               dev_err(dev, "failed to get main/front cam en gpio\n");
+       } else {
+               gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_cam_en);
+       }
+
+       gpio_standby = of_get_named_gpio(dnode, "gpio_standby", 0);
+       if (!gpio_is_valid(gpio_standby)) {
+               dev_err(dev, "failed to get gpio_standby\n");
+       } else {
+               gpio_request_one(gpio_standby, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_standby);
+       }
+
+       /* FRONT CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpios_cam_en, 0, NULL, 1000, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* FRONT CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 3, gpios_cam_en, 0, NULL, 1000, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 4, gpio_standby, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 2, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 3, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#endif /* CONFIG_OF */
+
+int sensor_8b1_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+       static bool probe_retried = false;
+
+       if (!fimc_is_dev)
+               goto probe_defer;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_S5K8B1_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       /* S5K8B1 */
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_S5K8B1_NAME;
+       module->subdev = subdev_module;
+       module->device = SENSOR_S5K8B1_INSTANCE;
+       module->ops = &module_8b1_ops;
+       module->client = client;
+       module->active_width = 1920;
+       module->active_height = 1080;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 30;
+       module->position = SENSOR_POSITION_FRONT;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_1;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K8B1";
+       module->setfile_name = "setfile_8b1.bin";
+       module->cfgs = ARRAY_SIZE(config_8b1);
+       module->cfg = config_8b1;
+       module->private_data = kzalloc(sizeof(struct fimc_is_module_8b1), GFP_KERNEL);
+       if (!module->private_data) {
+               err("private_data is NULL");
+               ret = -ENOMEM;
+               kfree(subdev_module);
+               goto p_err;
+       }
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_8b1_power_setpin;
+#endif
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+       ext->sensor_con.product_name = SENSOR_NAME_S5K8B1;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client) {
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+               subdev_module->internal_ops = &internal_ops;
+       } else {
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+       }
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+
+probe_defer:
+       if (probe_retried) {
+               err("probe has already been retried!!");
+               BUG();
+       }
+
+       probe_retried = true;
+       err("core device is not yet probed");
+       return -EPROBE_DEFER;
+}
+
+static int sensor_8b1_remove(struct i2c_client *client)
+{
+       int ret = 0;
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_sensor_8b1_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-sensor-8b1",
+       },
+       {},
+};
+#endif
+
+static const struct i2c_device_id sensor_8b1_idt[] = {
+       { SENSOR_NAME, 0 },
+};
+
+static struct i2c_driver sensor_8b1_driver = {
+       .driver = {
+               .name   = SENSOR_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = exynos_fimc_is_sensor_8b1_match
+#endif
+       },
+       .probe  = sensor_8b1_probe,
+       .remove = sensor_8b1_remove,
+       .id_table = sensor_8b1_idt
+};
+
+static int __init sensor_8b1_load(void)
+{
+        return i2c_add_driver(&sensor_8b1_driver);
+}
+
+static void __exit sensor_8b1_unload(void)
+{
+        i2c_del_driver(&sensor_8b1_driver);
+}
+
+module_init(sensor_8b1_load);
+module_exit(sensor_8b1_unload);
+
+MODULE_AUTHOR("Gilyeon lim");
+MODULE_DESCRIPTION("Sensor 8B1 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-8b1.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-8b1.h
new file mode 100644 (file)
index 0000000..b6a76e4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_8B1_H
+#define FIMC_IS_DEVICE_8B1_H
+
+#define SENSOR_S5K8B1_INSTANCE 1
+#define SENSOR_S5K8B1_NAME     SENSOR_NAME_S5K8B1
+
+struct fimc_is_module_8b1 {
+       u16             vis_duration;
+       u16             frame_length_line;
+       u32             line_length_pck;
+       u32             system_clock;
+};
+
+int sensor_8b1_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx134.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx134.c
new file mode 100644 (file)
index 0000000..af121b3
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "fimc-is-device-imx134.h"
+
+
+#include <mach/exynos-fimc-is-sensor.h>
+#include "../fimc-is-hw.h"
+
+
+
+#define SENSOR_NAME "IMX134"
+
+static struct fimc_is_sensor_cfg config_imx134[] = {
+       /* 3280X2458@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 30, 15, 0),
+       /* 3280X1846@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 30, 11, 1),
+       /* 3280X2458@24fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 24, 12, 2),
+       /* 3280X1846@24fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 24, 9, 3),
+       /* 1936X1450@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1450, 24, 12, 4),
+       /* 1936X1090@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 24, 9, 5),
+       /* 816X460@120fps */
+       FIMC_IS_SENSOR_CFG(816, 460, 120, 7, 6),
+       /* 1640X924@60fps */
+       FIMC_IS_SENSOR_CFG(1640, 924, 60, 6, 7),
+};
+
+
+static int sensor_imx134_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_imx134_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+#ifdef CONFIG_OF
+#ifdef CONFIG_COMPANION_USE
+static int sensor_imx134_power_setpin(struct device *dev)
+{
+       return 0;
+}
+#else
+static int sensor_imx134_power_setpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpio_none = 0;
+       int gpio_reset = 0, gpios_cam_en = 0;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               err("failed to get PIN_RESET");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+       if (!gpio_is_valid(gpios_cam_en)) {
+               err("failed to get main cam en gpio");
+       } else {
+               gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_cam_en);
+       }
+
+       /* BACK CAMERA  - POWER ON */
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "CAM_IO_1.8V_AP", 2000, PIN_REGULATOR_ON);
+
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, "af", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 7, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* BACK CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_OFF);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#endif /* CONFIG_COMPANION_USE */
+#endif /* CONFIG_OF */
+
+int sensor_imx134_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               info("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_IMX134_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               info("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_IMX134;
+       module->subdev = subdev_module;
+       module->device = SENSOR_IMX134_INSTANCE;
+       module->ops = NULL;
+       module->client = client;
+       module->active_width = 3264;
+       module->active_height = 2448;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 300;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SONY";
+       module->sensor_name = "IMX134";
+       module->setfile_name = "setfile_imx134.bin";
+       module->cfgs = ARRAY_SIZE(config_imx134);
+       module->cfg = config_imx134;
+       module->ops = NULL;
+       module->private_data = NULL;
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_imx134_power_setpin;
+#endif
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = SENSOR_NAME_IMX134;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x34;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7345;//ACTUATOR_NAME_NOTHING;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x34;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+#ifdef CONFIG_LEDS_MAX77804
+       ext->flash_con.product_name = FLADRV_NAME_MAX77693;
+#endif
+#ifdef CONFIG_LEDS_LM3560
+       ext->flash_con.product_name = FLADRV_NAME_LM3560;
+#endif
+#ifdef CONFIG_LEDS_SKY81296
+       ext->flash_con.product_name = FLADRV_NAME_SKY81296;
+#endif
+#ifdef CONFIG_LEDS_KTD2692
+       ext->flash_con.product_name = FLADRV_NAME_KTD2692;
+#endif
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 1;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 2;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
+
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx134.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx134.h
new file mode 100644 (file)
index 0000000..e189c18
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_IMX134_H
+#define FIMC_IS_DEVICE_IMX134_H
+
+#define SENSOR_IMX134_INSTANCE 0
+#define SENSOR_IMX134_NAME     SENSOR_NAME_IMX134
+
+int sensor_imx134_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
+
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx135.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx135.c
new file mode 100644 (file)
index 0000000..53dccf5
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-imx135.h"
+
+#define SENSOR_NAME "IMX135"
+
+static struct fimc_is_sensor_cfg config_imx135[] = {
+       /* 4144x3106@30fps */
+       FIMC_IS_SENSOR_CFG(4144, 3106, 30, 23, 0),
+       /* 4144x2332@30fps */
+       FIMC_IS_SENSOR_CFG(4144, 2332, 30, 18, 1),
+       /* 1936x1450@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1450, 24, 9, 2),
+       /* 1936x1090@24fps */
+       FIMC_IS_SENSOR_CFG(1936, 1090, 24, 7, 3),
+       /* 1024x576@120fps */
+       FIMC_IS_SENSOR_CFG(1024, 576, 120, 9, 4),
+       /* 2072x1166@60fps */
+       FIMC_IS_SENSOR_CFG(2072, 1166, 60, 18, 5),
+};
+
+static int sensor_imx135_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_imx135_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_imx135_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_IMX135_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_IMX135;
+       module->subdev = subdev_module;
+       module->device = SENSOR_IMX135_INSTANCE;
+       module->ops = NULL;
+       module->client = client;
+       module->active_width = 4128;
+       module->active_height = 3096;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 120;
+       module->sensor_maker = "SONY";
+       module->sensor_name = "IMX135";
+       module->setfile_name = "setfile_imx135.bin";
+       module->cfgs = ARRAY_SIZE(config_imx135);
+       module->cfg = config_imx135;
+       module->private_data = NULL;
+       module->lanes = CSI_DATA_LANES_4;
+
+       ext = &module->ext;
+       memset(ext, 0x0, sizeof(struct sensor_open_extended));
+       ext->mipi_lane_num = 4;
+       ext->sensor_con.product_name = 0;
+       ext->sensor_con.peri_type = SE_I2C;
+       //ext->sensor_con.peri_setting.i2c.channel = sensor_info->i2c_channel;
+       //ext->sensor_con.peri_setting.i2c.slave_address = sensor_info->sensor_slave_address;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7345;
+       ext->actuator_con.peri_type = SE_I2C;
+       //ext->actuator_con.peri_setting.i2c.channel = sensor_info->actuator_i2c;
+
+       //ext->flash_con.product_name = sensor_info->flash_id;
+       ext->flash_con.peri_type = SE_GPIO;
+       //ext->flash_con.peri_setting.gpio.first_gpio_port_no = sensor_info->flash_first_gpio;
+       //ext->flash_con.peri_setting.gpio.second_gpio_port_no = sensor_info->flash_second_gpio;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+       ext->mclk = 0;
+       ext->mipi_lane_num = 0;
+       ext->mipi_speed = 0;
+       ext->fast_open_sensor = 0;
+       ext->self_calibration_mode = 0;
+       ext->I2CSclk = I2C_L0;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx135.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx135.h
new file mode 100644 (file)
index 0000000..6051f4d
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_IMX135_H
+#define FIMC_IS_DEVICE_IMX135_H
+
+#define SENSOR_IMX135_INSTANCE 0
+#define SENSOR_IMX135_NAME     SENSOR_NAME_IMX135
+
+int sensor_imx135_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx175.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx175.c
new file mode 100644 (file)
index 0000000..3e64e62
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-imx175.h"
+
+#define SENSOR_NAME "IMX175"
+
+static struct fimc_is_sensor_cfg config_imx175[] = {
+       /* 3280X2458@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 30, 14, 0),
+       /* 3280X1846@30fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 30, 11, 1),
+       /* 3280X2458@24fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 24, 11, 2),
+       /* 3280X1846@24fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 24, 8, 3),
+       /* 1640X924@60fps */
+       FIMC_IS_SENSOR_CFG(1640, 924, 60, 11, 4),
+       /* 816X460@120fps */
+       FIMC_IS_SENSOR_CFG(816, 460, 120, 11, 5),
+};
+
+static int sensor_imx175_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_imx175_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+int sensor_imx175_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_IMX175_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_IMX175;
+       module->subdev = subdev_module;
+       module->device = SENSOR_IMX175_INSTANCE;
+       module->ops = NULL;
+       module->client = client;
+       module->active_width = 3264;
+       module->active_height = 2448;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 120;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SONY";
+       module->sensor_name = "IMX175";
+       module->setfile_name = "setfile_imx175.bin";
+       module->cfgs = ARRAY_SIZE(config_imx175);
+       module->cfg = config_imx175;
+       module->ops = NULL;
+       module->private_data = NULL;
+
+       ext = &module->ext;
+       ext->mipi_lane_num = 4;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = 0;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x18;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7343;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel
+               = SENSOR_CONTROL_I2C0;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x18;
+
+       ext->flash_con.product_name = FLADRV_NAME_MAX77693;
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 0;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 1;
+
+       /* ext->from_con.product_name = FROMDRV_NAME_W25Q80BW; */
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+       ext->mclk = 0;
+       ext->mipi_lane_num = 0;
+       ext->mipi_speed = 0;
+       ext->fast_open_sensor = 0;
+       ext->self_calibration_mode = 0;
+       ext->I2CSclk = I2C_L0;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx175.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx175.h
new file mode 100644 (file)
index 0000000..2e04dcf
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_IMX175_H
+#define FIMC_IS_DEVICE_IMX175_H
+
+#define SENSOR_IMX175_INSTANCE 0
+#define SENSOR_IMX175_NAME     SENSOR_NAME_IMX175
+
+int sensor_imx175_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx219.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx219.c
new file mode 100644 (file)
index 0000000..e630244
--- /dev/null
@@ -0,0 +1,829 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-imx219.h"
+
+#define SENSOR_NAME "IMX219"
+#define DEFAULT_SENSOR_WIDTH   184
+#define DEFAULT_SENSOR_HEIGHT  104
+#define SENSOR_MEMSIZE DEFAULT_SENSOR_WIDTH * DEFAULT_SENSOR_HEIGHT
+
+#define SENSOR_REG_VIS_DURATION_MSB                    (0x6026)
+#define SENSOR_REG_VIS_DURATION_LSB                    (0x6027)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_MSB       (0x4340)
+#define SENSOR_REG_VIS_FRAME_LENGTH_LINE_ALV_LSB       (0x4341)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_MSB                (0x4342)
+#define SENSOR_REG_VIS_LINE_LENGTH_PCLK_ALV_LSB                (0x4343)
+#define SENSOR_REG_VIS_GAIN_RED                                (0x6029)
+#define SENSOR_REG_VIS_GAIN_GREEN                      (0x602A)
+#define SENSOR_REG_VIS_AE_TARGET                       (0x600A)
+#define SENSOR_REG_VIS_AE_SPEED                                (0x5034)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_MSB          (0x5030)
+#define SENSOR_REG_VIS_AE_NUMBER_OF_PIXEL_LSB          (0x5031)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x1_2          (0x6000)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_1x3_4          (0x6001)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x1_2          (0x6002)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_2x3_4          (0x6003)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x1_2          (0x6004)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_3x3_4          (0x6005)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x1_2          (0x6006)
+#define SENSOR_REG_VIS_AE_WINDOW_WEIGHT_4x3_4          (0x6007)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_MSB               (0x5039)
+#define SENSOR_REG_VIS_AE_MANUAL_EXP_LSB               (0x503A)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_MSB               (0x503B)
+#define SENSOR_REG_VIS_AE_MANUAL_ANG_LSB               (0x503C)
+#define SENSOR_REG_VIS_BIT_CONVERTING_MSB              (0x602B)
+#define SENSOR_REG_VIS_BIT_CONVERTING_LSB              (0x7203)
+#define SENSOR_REG_VIS_AE_OFF                          (0x5000)
+
+static u16 setfile_vision_imx219[][2] = {
+       {0x4200, 0x02},
+       {0x4201, 0xAE},
+       {0x4301, 0x04},
+       {0x4309, 0x04},
+       {0x4345, 0x08},
+       {0x4347, 0x08},
+       {0x4348, 0x0A},
+       {0x4349, 0x01},
+       {0x434A, 0x05},
+       {0x434B, 0xA0},
+       {0x434C, 0x01},
+       {0x434D, 0x40},
+       {0x434E, 0x00},
+       {0x434F, 0xB4},
+       {0x4381, 0x01},
+       {0x4383, 0x07},
+       {0x4385, 0x08},
+       {0x4387, 0x08},
+       {0x5004, 0x01},
+       {0x5005, 0x1E},
+       {0x5014, 0x11},
+       {0x5015, 0x9E},
+       {0x5016, 0x00},
+       {0x5017, 0x02},
+       {0x5030, 0x1C},
+       {0x5031, 0x20},
+       {0x5034, 0x00},
+       {0x5035, 0x02},
+       {0x5036, 0x00},
+       {0x5037, 0x06},
+       {0x5038, 0xC0},
+       {0x5039, 0x00},
+       {0x503A, 0x00},
+       {0x503B, 0x00},
+       {0x503C, 0x00},
+       {0x503D, 0x20},
+       {0x503E, 0x70},
+       {0x503F, 0x02},
+       {0x600A, 0x2A},
+       {0x600E, 0x05},
+       {0x6014, 0x27},
+       {0x6015, 0x1D},
+       {0x6018, 0x01},
+       {0x6026, 0x00},
+       {0x6027, 0x68},
+       {0x6029, 0x08},
+       {0x602A, 0x08},
+       {0x602B, 0x00},
+       {0x602C, 0x00},
+       {0x7008, 0x00},
+       {0x7009, 0x10},
+       {0x700A, 0x00},
+       {0x700B, 0x10},
+       {0x7014, 0x2B},
+       {0x7015, 0x91},
+       {0x7016, 0x82},
+       {0x701B, 0x16},
+       {0x701D, 0x0B},
+       {0x701F, 0x0B},
+       {0x7026, 0x1A},
+       {0x7027, 0x46},
+       {0x7029, 0x14},
+       {0x702A, 0x02},
+       {0x7038, 0x01},
+       {0x7039, 0x14},
+       {0x703A, 0x32},
+       {0x703B, 0x22},
+       {0x7040, 0x01},
+       {0x7041, 0x14},
+       {0x7042, 0x32},
+       {0x7043, 0x22},
+       {0x7050, 0x0A},
+       {0x7051, 0xA8},
+       {0x7052, 0x35},
+       {0x7053, 0x54},
+       {0x7054, 0x00},
+       {0x7055, 0x00},
+       {0x7056, 0x00},
+       {0x7057, 0x00},
+       {0x705E, 0x0E},
+       {0x705F, 0x10},
+       {0x7060, 0x01},
+       {0x7064, 0x05},
+       {0x7065, 0x3C},
+       {0x7066, 0x00},
+       {0x7067, 0x00},
+       {0x7068, 0x4A},
+       {0x706C, 0x01},
+       {0x7077, 0x88},
+       {0x7078, 0x88},
+       {0x7082, 0x90},
+       {0x7091, 0x05},
+       {0x7098, 0x00},
+       {0x7112, 0x01},
+       {0x720A, 0x06},
+       {0x720B, 0x80},
+       {0x7245, 0xC1},
+       {0x7301, 0x01},
+       {0x7305, 0x13},
+       {0x7306, 0x01},
+       {0x7323, 0x01},
+       {0x7339, 0x07},
+       {0x7351, 0x01},
+       {0x7352, 0x24},
+       {0x7405, 0x28},
+       {0x7406, 0x28},
+       {0x7407, 0xC0},
+       {0x7454, 0x01},
+       {0x7460, 0x01},
+       {0x7461, 0x20},
+       {0x7462, 0xC0},
+       {0x7463, 0x1E},
+       {0x7464, 0x02},
+       {0x7465, 0x4B},
+       {0x7467, 0x20},
+       {0x7468, 0x20},
+       {0x7469, 0x20},
+       {0x746A, 0x20},
+       {0x746B, 0x20},
+       {0x746C, 0x20},
+       {0x746D, 0x09},
+       {0x746E, 0xFF},
+       {0x746F, 0x01},
+       {0x7472, 0x00},
+       {0x7473, 0x02},
+       {0x7474, 0xC1},
+       {0x7475, 0x00},
+       {0x7476, 0x00},
+       {0x7477, 0x00},
+       {0x7478, 0x00},
+       {0x4100, 0x01},
+};
+
+static struct fimc_is_sensor_cfg config_imx219[] = {
+       /* 3280X2458@20fps */
+       FIMC_IS_SENSOR_CFG(3280, 2458, 20, 19, 0),
+       /* 3280X1846@20fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 20, 15, 1),
+       /* 1640X1228@24fps */
+       FIMC_IS_SENSOR_CFG(1640, 1228, 24, 12, 2),
+       /* 3280X1846@24fps */
+       FIMC_IS_SENSOR_CFG(3280, 1846, 24, 17, 3),
+};
+
+static int sensor_imx219_open(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_imx219_close(struct v4l2_subdev *sd,
+       struct v4l2_subdev_fh *fh)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+static int sensor_imx219_registered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+       return 0;
+}
+
+static void sensor_imx219_unregistered(struct v4l2_subdev *sd)
+{
+       pr_info("%s\n", __func__);
+}
+
+static const struct v4l2_subdev_internal_ops internal_ops = {
+       .open = sensor_imx219_open,
+       .close = sensor_imx219_close,
+       .registered = sensor_imx219_registered,
+       .unregistered = sensor_imx219_unregistered,
+};
+
+static int sensor_imx219_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int i, ret = 0;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_module_imx219 *module_imx219;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       module_imx219 = module->private_data;
+       client = module->client;
+
+       module_imx219->system_clock = 146 * 1000 * 1000;
+       module_imx219->line_length_pck = 146 * 1000 * 1000;
+
+       pr_info("%s\n", __func__);
+
+       /* sensor init */
+       for (i = 0; i < ARRAY_SIZE(setfile_vision_imx219); i++) {
+               fimc_is_sensor_write8(client, setfile_vision_imx219[i][0],
+                               (u8)setfile_vision_imx219[i][1]);
+       }
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_imx219_init
+};
+
+static int sensor_imx219_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (enable) {
+               ret = CALL_MOPS(sensor, stream_on, subdev);
+               if (ret < 0) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       } else {
+               ret = CALL_MOPS(sensor, stream_off, subdev);
+               if (ret < 0) {
+                       err("s_duration is fail(%d)", ret);
+                       goto p_err;
+               }
+       }
+
+p_err:
+       return 0;
+}
+
+static int sensor_imx219_s_param(struct v4l2_subdev *subdev, struct v4l2_streamparm *param)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct v4l2_captureparm *cp;
+       struct v4l2_fract *tpf;
+       u64 duration;
+
+       BUG_ON(!subdev);
+       BUG_ON(!param);
+
+       pr_info("%s\n", __func__);
+
+       cp = &param->parm.capture;
+       tpf = &cp->timeperframe;
+
+       if (!tpf->denominator) {
+               err("denominator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (!tpf->numerator) {
+               err("numerator is 0");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       duration = (u64)(tpf->numerator * 1000 * 1000 * 1000) /
+                                       (u64)(tpf->denominator);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (!sensor) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = CALL_MOPS(sensor, s_duration, subdev, duration);
+       if (ret) {
+               err("s_duration is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+static int sensor_imx219_s_format(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *fmt)
+{
+       /* TODO */
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = sensor_imx219_s_stream,
+       .s_parm = sensor_imx219_s_param,
+       .s_mbus_fmt = sensor_imx219_s_format
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops
+};
+
+int sensor_imx219_stream_on(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 1);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+int sensor_imx219_stream_off(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x4100, 0);
+       if (ret < 0) {
+               err("fimc_is_sensor_write8 is fail(%d)", ret);
+               goto p_err;
+       }
+
+p_err:
+       return ret;
+}
+
+/*
+ * @ brief
+ * frame duration time
+ * @ unit
+ * nano second
+ * @ remarks
+ */
+int sensor_imx219_s_duration(struct v4l2_subdev *subdev, u64 duration)
+{
+       int ret = 0;
+       u8 value[2];
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s\n", __func__);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /*
+        * forcely set 10fps for IMX219,
+        */
+       value[0] = 0x52;
+       value[1] = 0x0;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_MSB, value[1]);
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_DURATION_LSB, value[0]);
+
+p_err:
+       return ret;
+}
+
+int sensor_imx219_g_min_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_g_max_duration(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_s_exposure(struct v4l2_subdev *subdev, u64 exposure)
+{
+       int ret = 0;
+       u8 value;
+       struct fimc_is_module_enum *sensor;
+       struct i2c_client *client;
+
+       BUG_ON(!subdev);
+
+       pr_info("%s(%d)\n", __func__, (u32)exposure);
+
+       sensor = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+       if (unlikely(!sensor)) {
+               err("sensor is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       client = sensor->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       value = exposure & 0xFF;
+
+       fimc_is_sensor_write8(client, SENSOR_REG_VIS_AE_TARGET, value);
+
+p_err:
+       return ret;
+}
+
+int sensor_imx219_g_min_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_g_max_exposure(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_s_again(struct v4l2_subdev *subdev, u64 sensitivity)
+{
+       int ret = 0;
+
+       pr_info("%s\n", __func__);
+
+       return ret;
+}
+
+int sensor_imx219_g_min_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_g_max_again(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_s_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_g_min_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+int sensor_imx219_g_max_dgain(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       return ret;
+}
+
+struct fimc_is_sensor_ops module_imx219_ops = {
+       .stream_on      = sensor_imx219_stream_on,
+       .stream_off     = sensor_imx219_stream_off,
+       .s_duration     = sensor_imx219_s_duration,
+       .g_min_duration = sensor_imx219_g_min_duration,
+       .g_max_duration = sensor_imx219_g_max_duration,
+       .s_exposure     = sensor_imx219_s_exposure,
+       .g_min_exposure = sensor_imx219_g_min_exposure,
+       .g_max_exposure = sensor_imx219_g_max_exposure,
+       .s_again        = sensor_imx219_s_again,
+       .g_min_again    = sensor_imx219_g_min_again,
+       .g_max_again    = sensor_imx219_g_max_again,
+       .s_dgain        = sensor_imx219_s_dgain,
+       .g_min_dgain    = sensor_imx219_g_min_dgain,
+       .g_max_dgain    = sensor_imx219_g_max_dgain
+};
+
+#ifdef CONFIG_OF
+static int sensor_imx219_power_setpin(struct device *dev)
+{
+       int gpio_none = 0, gpio_reset = 0, gpio_standby = 0;
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       struct pinctrl *pinctrl_ch = NULL;
+
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       gpio_standby = of_get_named_gpio(dnode, "gpio_standby", 0);
+       if (!gpio_is_valid(gpio_standby)) {
+               dev_err(dev, "failed to get gpio_standby\n");
+       } else {
+               gpio_request_one(gpio_standby, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_standby);
+       }
+
+       /* initial - i2c off */
+       pinctrl_ch = devm_pinctrl_get_select(dev, "off1");
+       if (IS_ERR_OR_NULL(pinctrl_ch)) {
+               pr_err("%s: cam %s pins are not configured\n", __func__, "off1");
+       } else {
+               devm_pinctrl_put(pinctrl_ch);
+       }
+
+       /* FRONT CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* FRONT CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 1, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 2, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 3, gpio_none, 0, "VT_CAM_1.2V", 1000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 4, gpio_standby, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 5, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* VISION CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 0, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 2, gpio_standby, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 3, gpio_none, 0, "VT_CAM_1.2V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VT_CAM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 5, gpio_none, 0, "VT_CAM_1.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, 6, gpio_none, 0, NULL, 0, PIN_END);
+
+       return 0;
+}
+#endif
+
+int sensor_imx219_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+       static bool probe_retried = false;
+
+       if (!fimc_is_dev)
+               goto probe_defer;
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_IMX219_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       /* IMX219 */
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_IMX219_NAME;
+       module->subdev = subdev_module;
+       module->device = SENSOR_IMX219_INSTANCE;
+       module->ops = &module_imx219_ops;
+       module->client = client;
+       module->active_width = 3264;
+       module->active_height = 2448;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 24;
+       module->position = SENSOR_POSITION_FRONT;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_2;
+       module->sensor_maker = "SONY";
+       module->sensor_name = "IMX219";
+       module->setfile_name = "setfile_imx219.bin";
+       module->cfgs = ARRAY_SIZE(config_imx219);
+       module->cfg = config_imx219;
+       module->private_data = kzalloc(sizeof(struct fimc_is_module_imx219), GFP_KERNEL);
+       if (!module->private_data) {
+               err("private_data is NULL");
+               ret = -ENOMEM;
+               kfree(subdev_module);
+               goto p_err;
+       }
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_imx219_power_setpin;
+#endif
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+       ext->sensor_con.product_name = SENSOR_NAME_IMX219;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x34;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+
+       if (client) {
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+               subdev_module->internal_ops = &internal_ops;
+       } else {
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+       }
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+
+probe_defer:
+       if (probe_retried) {
+               err("probe has already been retried!!");
+               BUG();
+       }
+
+       probe_retried = true;
+       err("core device is not yet probed");
+       return -EPROBE_DEFER;
+}
+
+static int sensor_imx219_remove(struct i2c_client *client)
+{
+       int ret = 0;
+       return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_fimc_is_sensor_imx219_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-sensor-imx219",
+       },
+       {},
+};
+#endif
+
+static const struct i2c_device_id sensor_imx219_idt[] = {
+       { SENSOR_NAME, 0 },
+};
+
+static struct i2c_driver sensor_imx219_driver = {
+       .driver = {
+               .name   = SENSOR_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = exynos_fimc_is_sensor_imx219_match
+#endif
+       },
+       .probe  = sensor_imx219_probe,
+       .remove = sensor_imx219_remove,
+       .id_table = sensor_imx219_idt
+};
+
+static int __init sensor_imx219_load(void)
+{
+        return i2c_add_driver(&sensor_imx219_driver);
+}
+
+static void __exit sensor_imx219_unload(void)
+{
+        i2c_del_driver(&sensor_imx219_driver);
+}
+
+module_init(sensor_imx219_load);
+module_exit(sensor_imx219_unload);
+
+MODULE_AUTHOR("Gilyeon lim");
+MODULE_DESCRIPTION("Sensor IMX219 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx219.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx219.h
new file mode 100644 (file)
index 0000000..6772939
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_IMX219_H
+#define FIMC_IS_DEVICE_IMX219_H
+
+#define SENSOR_IMX219_INSTANCE 1
+#define SENSOR_IMX219_NAME     SENSOR_NAME_IMX219
+
+struct fimc_is_module_imx219 {
+       u16             vis_duration;
+       u16             frame_length_line;
+       u32             line_length_pck;
+       u32             system_clock;
+};
+
+int sensor_imx219_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx240.c b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx240.c
new file mode 100644 (file)
index 0000000..8728858
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_exynos_camera.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <mach/exynos-fimc-is-sensor.h>
+
+#include "../fimc-is-core.h"
+#include "../fimc-is-device-sensor.h"
+#include "../fimc-is-resourcemgr.h"
+#include "../fimc-is-hw.h"
+#include "fimc-is-device-imx240.h"
+
+#define SENSOR_NAME "IMX240"
+
+static struct fimc_is_sensor_cfg config_imx240[] = {
+       /* 5328x3000@30fps */
+       FIMC_IS_SENSOR_CFG(5328, 3000, 30, 30, 0),
+       /* 5328x3000@24fps */
+       FIMC_IS_SENSOR_CFG(5328, 3000, 24, 29, 1),
+       /* 4000X3000@30fps */
+       FIMC_IS_SENSOR_CFG(4000, 3000, 30, 23, 2),
+       /* 4000X3000@24fps */
+       FIMC_IS_SENSOR_CFG(4000, 3000, 24, 19, 3),
+       /* 3008X3000@30fps */
+       FIMC_IS_SENSOR_CFG(3008, 3000, 30, 19, 4),
+       /* 3008X3000@30fps */
+       FIMC_IS_SENSOR_CFG(3008, 3000, 24, 14, 5),
+       /* 2664X1500@60fps */
+       FIMC_IS_SENSOR_CFG(2664, 1500, 60, 15, 6),
+       /* 2664X1500@30fps */
+       FIMC_IS_SENSOR_CFG(2664, 1500, 30, 15, 7),
+       /* 1328X748@120fps */
+       FIMC_IS_SENSOR_CFG(1328, 748, 120, 13, 8),
+       /* 824X496@300fps */
+       //FIMC_IS_SENSOR_CFG(824, 496, 300, 13, 8),
+};
+
+static int sensor_imx240_init(struct v4l2_subdev *subdev, u32 val)
+{
+       int ret = 0;
+       struct fimc_is_module_enum *module;
+
+       BUG_ON(!subdev);
+
+       module = (struct fimc_is_module_enum *)v4l2_get_subdevdata(subdev);
+
+       pr_info("[MOD:D:%d] %s(%d)\n", module->id, __func__, val);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_imx240_init
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops
+};
+
+#ifdef CONFIG_OF
+#ifdef CONFIG_COMPANION_USE
+static int sensor_imx240_power_setpin(struct device *dev)
+{
+       struct exynos_platform_fimc_is_sensor *pdata;
+       struct device_node *dnode;
+       int gpio_comp_en = 0, gpio_comp_rst = 0;
+       int gpio_none = 0;
+       int gpio_reset = 0;
+       int gpios_cam_en = -EINVAL;
+#ifdef CONFIG_OIS_USE
+       int gpios_ois_en = 0;
+#endif
+       BUG_ON(!dev);
+       BUG_ON(!dev->platform_data);
+
+       dnode = dev->of_node;
+       pdata = dev->platform_data;
+
+       gpio_comp_en = of_get_named_gpio(dnode, "gpios_comp_en", 0);
+       if (!gpio_is_valid(gpio_comp_en)) {
+               dev_err(dev, "failed to get main comp en gpio\n");
+       } else {
+               gpio_request_one(gpio_comp_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_comp_en);
+       }
+
+       gpio_comp_rst = of_get_named_gpio(dnode, "gpios_comp_reset", 0);
+       if (!gpio_is_valid(gpio_comp_rst)) {
+               dev_err(dev, "failed to get main comp reset gpio\n");
+       } else {
+               gpio_request_one(gpio_comp_rst, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_comp_rst);
+       }
+
+       gpio_reset = of_get_named_gpio(dnode, "gpio_reset", 0);
+       if (!gpio_is_valid(gpio_reset)) {
+               dev_err(dev, "failed to get PIN_RESET\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_reset);
+       }
+
+       if (of_get_property(dnode, "gpios_cam_en", NULL)) {
+               gpios_cam_en = of_get_named_gpio(dnode, "gpios_cam_en", 0);
+               if (!gpio_is_valid(gpios_cam_en)) {
+                       dev_err(dev, "failed to get main cam en gpio\n");
+               } else {
+                       gpio_request_one(gpios_cam_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+                       gpio_free(gpios_cam_en);
+               }
+       }
+
+#ifdef CONFIG_OIS_USE
+       gpios_ois_en = of_get_named_gpio(dnode, "gpios_ois_en", 0);
+       pdata->pin_ois_en = gpios_ois_en;
+       if (!gpio_is_valid(gpios_ois_en)) {
+               dev_err(dev, "failed to get ois en gpio\n");
+       } else {
+               gpio_request_one(gpios_ois_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpios_ois_en);
+       }
+#endif
+
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 1, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 2, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+#ifdef CONFIG_OIS_USE
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 3, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 4, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_ON);
+#endif
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 5, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 6, gpio_none, 0, "VDDA_1.8V_COMP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 7, gpio_comp_en, 0, NULL, 150, PIN_OUTPUT_HIGH);
+       if (pdata->companion_use_pmic) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 8, gpio_none, 0, "VDD_MIPI_1.0V_COMP", 0, PIN_REGULATOR_ON);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 9, gpio_comp_rst, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 10, gpio_none, 0, "ch", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 11, gpio_none, 0, "af", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 12, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, 13, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* BACK CAMERA  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 1, gpio_none, 0, "off", 0, PIN_FUNCTION);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 2, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 3, gpio_comp_rst, 0, NULL, 0, PIN_OUTPUT_LOW);
+       if (pdata->companion_use_pmic) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "VDD_MIPI_1.0V_COMP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 5, gpio_comp_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 6, gpio_none, 0, "VDDA_1.8V_COMP", 0, PIN_REGULATOR_OFF);
+       if (gpio_is_valid(gpios_cam_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 7, gpios_cam_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 7, gpio_none, 0, "CAM_SEN_A2.8V_AP", 0, PIN_REGULATOR_OFF);
+       }
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 8, gpio_none, 0, "CAM_SEN_CORE_1.2V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 9, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+#ifdef CONFIG_OIS_USE
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 10, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 11, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_OFF);
+#endif
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, 12, gpio_none, 0, NULL, 0, PIN_END);
+
+#ifdef CONFIG_OIS_USE
+       /* OIS_FACTORY  - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 1, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 2, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 3, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_ON);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 4, gpio_reset, 0, NULL, 0, PIN_OUTPUT_HIGH);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, 5, gpio_none, 0, NULL, 0, PIN_END);
+
+       /* OIS_FACTORY  - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 0, gpio_none, 0, "CAM_AF_2.8V_AP", 2000, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 1, gpio_reset, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 2, gpio_none, 0, "CAM_IO_1.8V_AP", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 3, gpios_ois_en, 0, NULL, 0, PIN_OUTPUT_LOW);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 4, gpio_none, 0, "OIS_VM_2.8V", 0, PIN_REGULATOR_OFF);
+       SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, 5, gpio_none, 0, NULL, 0, PIN_END);
+#endif
+
+       return 0;
+}
+#else
+static int sensor_imx240_power_setpin(struct device *dev)
+{
+       return 0;
+}
+#endif /* CONFIG_COMPANION_USE */
+#endif /* CONFIG_OF */
+
+int sensor_imx240_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       struct fimc_is_core *core;
+       struct v4l2_subdev *subdev_module;
+       struct fimc_is_module_enum *module;
+       struct fimc_is_device_sensor *device;
+       struct sensor_open_extended *ext;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               err("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       device = &core->sensor[SENSOR_IMX240_INSTANCE];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       module = &device->module_enum[atomic_read(&core->resourcemgr.rsccount_module)];
+       atomic_inc(&core->resourcemgr.rsccount_module);
+       module->id = SENSOR_NAME_IMX240;
+       module->subdev = subdev_module;
+       module->device = SENSOR_IMX240_INSTANCE;
+       module->client = client;
+       module->active_width = 5312;
+       module->active_height = 2990;
+       module->pixel_width = module->active_width + 16;
+       module->pixel_height = module->active_height + 10;
+       module->max_framerate = 300;
+       module->position = SENSOR_POSITION_REAR;
+       module->mode = CSI_MODE_CH0_ONLY;
+       module->lanes = CSI_DATA_LANES_4;
+       module->sensor_maker = "SONY";
+       module->sensor_name = "IMX240";
+       module->setfile_name = "setfile_imx240.bin";
+       module->cfgs = ARRAY_SIZE(config_imx240);
+       module->cfg = config_imx240;
+       module->ops = NULL;
+       module->private_data = NULL;
+#ifdef CONFIG_OF
+       module->power_setpin = sensor_imx240_power_setpin;
+#endif
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = I2C_L0;
+
+       ext->sensor_con.product_name = SENSOR_NAME_IMX240;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C0;
+       ext->sensor_con.peri_setting.i2c.slave_address = 0x34;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       ext->actuator_con.product_name = ACTUATOR_NAME_AK7345;
+       ext->actuator_con.peri_type = SE_I2C;
+       ext->actuator_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->actuator_con.peri_setting.i2c.slave_address = 0x34;
+       ext->actuator_con.peri_setting.i2c.speed = 400000;
+
+#ifdef CONFIG_LEDS_MAX77804
+       ext->flash_con.product_name = FLADRV_NAME_MAX77693;
+#endif
+#ifdef CONFIG_LEDS_LM3560
+       ext->flash_con.product_name = FLADRV_NAME_LM3560;
+#endif
+#ifdef CONFIG_LEDS_SKY81296
+       ext->flash_con.product_name = FLADRV_NAME_SKY81296;
+#endif
+#ifdef CONFIG_LEDS_KTD2692
+       ext->flash_con.product_name = FLADRV_NAME_KTD2692;
+#endif
+       ext->flash_con.peri_type = SE_GPIO;
+       ext->flash_con.peri_setting.gpio.first_gpio_port_no = 1;
+       ext->flash_con.peri_setting.gpio.second_gpio_port_no = 2;
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+#ifdef CONFIG_COMPANION_USE
+       ext->companion_con.product_name = COMPANION_NAME_73C1;
+       ext->companion_con.peri_info0.valid = true;
+       ext->companion_con.peri_info0.peri_type = SE_SPI;
+       ext->companion_con.peri_info0.peri_setting.spi.channel = (int) core->companion_spi_channel;
+       ext->companion_con.peri_info1.valid = true;
+       ext->companion_con.peri_info1.peri_type = SE_I2C;
+       ext->companion_con.peri_info1.peri_setting.i2c.channel = 0;
+       ext->companion_con.peri_info1.peri_setting.i2c.slave_address = 0x7A;
+       ext->companion_con.peri_info1.peri_setting.i2c.speed = 400000;
+       ext->companion_con.peri_info2.valid = true;
+       ext->companion_con.peri_info2.peri_type = SE_FIMC_LITE;
+       ext->companion_con.peri_info2.peri_setting.fimc_lite.channel = FLITE_ID_D;
+#else
+       ext->companion_con.product_name = COMPANION_NAME_NOTHING;
+#endif
+
+#if defined(CONFIG_OIS_USE)
+       ext->ois_con.product_name = OIS_NAME_IDG2030;
+       ext->ois_con.peri_type = SE_I2C;
+       ext->ois_con.peri_setting.i2c.channel = SENSOR_CONTROL_I2C1;
+       ext->ois_con.peri_setting.i2c.slave_address = 0x48;
+       ext->ois_con.peri_setting.i2c.speed = 400000;
+#else
+       ext->ois_con.product_name = OIS_NAME_NOTHING;
+       ext->ois_con.peri_type = SE_NULL;
+#endif
+
+       if (client)
+               v4l2_i2c_subdev_init(subdev_module, client, &subdev_ops);
+       else
+               v4l2_subdev_init(subdev_module, &subdev_ops);
+
+       v4l2_set_subdevdata(subdev_module, module);
+       v4l2_set_subdev_hostdata(subdev_module, device);
+       snprintf(subdev_module->name, V4L2_SUBDEV_NAME_SIZE, "sensor-subdev.%d", module->id);
+
+p_err:
+       info("%s(%d)\n", __func__, ret);
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx240.h b/drivers/media/platform/exynos/fimc-is/sensor/fimc-is-device-imx240.h
new file mode 100644 (file)
index 0000000..8b26f65
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ *
+ * 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.
+ */
+
+#ifndef FIMC_IS_DEVICE_IMX240_H
+#define FIMC_IS_DEVICE_IMX240_H
+
+#define SENSOR_IMX240_INSTANCE 0
+#define SENSOR_IMX240_NAME             SENSOR_NAME_IMX240
+
+int sensor_imx240_probe(struct i2c_client *client,
+       const struct i2c_device_id *id);
+
+#endif