[7885] media: fimc-is2: sensor: Create base file for 2P6(code sync)
authorHyeonmyeong Choi <hyeon.choi@samsung.com>
Sat, 27 May 2017 05:11:52 +0000 (14:11 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Mon, 23 Jul 2018 08:05:32 +0000 (17:05 +0900)
PR JIRA ID : CPR-38

Change-Id: I7cf45a21af97a6c91b974af422408eec9a4cbe89
Signed-off-by: Hyeonmyeong Choi <hyeon.choi@samsung.com>
drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6-setA.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6.c [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6.h [new file with mode: 0644]
drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/Makefile
drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2p6.c [new file with mode: 0644]

diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6-setA.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6-setA.h
new file mode 100644 (file)
index 0000000..385833a
--- /dev/null
@@ -0,0 +1,896 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2016 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_CIS_3P8_SET_A_H
+#define FIMC_IS_CIS_3P8_SET_A_H
+
+#include "fimc-is-cis.h"
+#include "fimc-is-cis-3p8.h"
+
+/* Use "setfile_A" as Non-PDAF setting */
+/* Reference : S5K3P8SN_EVT1.0_Ver_0.8_20160909.xlsx */
+
+const u32 sensor_3p8_setfile_A_Global[] = {
+       /* this commented data is set to cis_init
+        * it is for reset -> 3ms delay
+        * 0xFCFC, 0x4000, 0x2,
+        * 0x6010, 0x0001, 0x2,
+        */
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x3074, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0449, 0x02,
+       0x6F12, 0x0348, 0x02,
+       0x6F12, 0x0860, 0x02,
+       0x6F12, 0xCA8D, 0x02,
+       0x6F12, 0x101A, 0x02,
+       0x6F12, 0x8880, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x52B8, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x31B8, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x1E80, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x70B5, 0x02,
+       0x6F12, 0x0646, 0x02,
+       0x6F12, 0x2C48, 0x02,
+       0x6F12, 0x0022, 0x02,
+       0x6F12, 0x0168, 0x02,
+       0x6F12, 0x0C0C, 0x02,
+       0x6F12, 0x8DB2, 0x02,
+       0x6F12, 0x2946, 0x02,
+       0x6F12, 0x2046, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x61F8, 0x02,
+       0x6F12, 0x3046, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x63F8, 0x02,
+       0x6F12, 0x2748, 0x02,
+       0x6F12, 0x284A, 0x02,
+       0x6F12, 0x0188, 0x02,
+       0x6F12, 0x1180, 0x02,
+       0x6F12, 0x911C, 0x02,
+       0x6F12, 0x4088, 0x02,
+       0x6F12, 0x0880, 0x02,
+       0x6F12, 0x2946, 0x02,
+       0x6F12, 0x2046, 0x02,
+       0x6F12, 0xBDE8, 0x02,
+       0x6F12, 0x7040, 0x02,
+       0x6F12, 0x0122, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x50B8, 0x02,
+       0x6F12, 0x2DE9, 0x02,
+       0x6F12, 0xF041, 0x02,
+       0x6F12, 0x8046, 0x02,
+       0x6F12, 0x1E48, 0x02,
+       0x6F12, 0x1446, 0x02,
+       0x6F12, 0x0F46, 0x02,
+       0x6F12, 0x4068, 0x02,
+       0x6F12, 0x0022, 0x02,
+       0x6F12, 0x85B2, 0x02,
+       0x6F12, 0x060C, 0x02,
+       0x6F12, 0x2946, 0x02,
+       0x6F12, 0x3046, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x42F8, 0x02,
+       0x6F12, 0x1B48, 0x02,
+       0x6F12, 0x408C, 0x02,
+       0x6F12, 0x70B1, 0x02,
+       0x6F12, 0x94F8, 0x02,
+       0x6F12, 0x6B00, 0x02,
+       0x6F12, 0x4021, 0x02,
+       0x6F12, 0xB1FB, 0x02,
+       0x6F12, 0xF0F0, 0x02,
+       0x6F12, 0x1849, 0x02,
+       0x6F12, 0x194A, 0x02,
+       0x6F12, 0x098B, 0x02,
+       0x6F12, 0x5288, 0x02,
+       0x6F12, 0x891A, 0x02,
+       0x6F12, 0x0901, 0x02,
+       0x6F12, 0x91FB, 0x02,
+       0x6F12, 0xF0F0, 0x02,
+       0x6F12, 0x84B2, 0x02,
+       0x6F12, 0x05E0, 0x02,
+       0x6F12, 0x2246, 0x02,
+       0x6F12, 0x3946, 0x02,
+       0x6F12, 0x4046, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x35F8, 0x02,
+       0x6F12, 0x0446, 0x02,
+       0x6F12, 0x0122, 0x02,
+       0x6F12, 0x2946, 0x02,
+       0x6F12, 0x3046, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x25F8, 0x02,
+       0x6F12, 0x2046, 0x02,
+       0x6F12, 0xBDE8, 0x02,
+       0x6F12, 0xF081, 0x02,
+       0x6F12, 0x10B5, 0x02,
+       0x6F12, 0x0022, 0x02,
+       0x6F12, 0xAFF2, 0x02,
+       0x6F12, 0x9B01, 0x02,
+       0x6F12, 0x0C48, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x2AF8, 0x02,
+       0x6F12, 0x054C, 0x02,
+       0x6F12, 0x0022, 0x02,
+       0x6F12, 0xAFF2, 0x02,
+       0x6F12, 0x6F01, 0x02,
+       0x6F12, 0x2060, 0x02,
+       0x6F12, 0x0948, 0x02,
+       0x6F12, 0x00F0, 0x02,
+       0x6F12, 0x22F8, 0x02,
+       0x6F12, 0x6060, 0x02,
+       0x6F12, 0x10BD, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x31B0, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x4A00, 0x02,
+       0x6F12, 0x4000, 0x02,
+       0x6F12, 0x950C, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x2F10, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x1B10, 0x02,
+       0x6F12, 0x2000, 0x02,
+       0x6F12, 0x2F40, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x15E9, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x9ECD, 0x02,
+       0x6F12, 0x40F2, 0x02,
+       0x6F12, 0xA37C, 0x02,
+       0x6F12, 0xC0F2, 0x02,
+       0x6F12, 0x000C, 0x02,
+       0x6F12, 0x6047, 0x02,
+       0x6F12, 0x41F2, 0x02,
+       0x6F12, 0xE95C, 0x02,
+       0x6F12, 0xC0F2, 0x02,
+       0x6F12, 0x000C, 0x02,
+       0x6F12, 0x6047, 0x02,
+       0x6F12, 0x49F6, 0x02,
+       0x6F12, 0xCD6C, 0x02,
+       0x6F12, 0xC0F2, 0x02,
+       0x6F12, 0x000C, 0x02,
+       0x6F12, 0x6047, 0x02,
+       0x6F12, 0x4DF6, 0x02,
+       0x6F12, 0x1B0C, 0x02,
+       0x6F12, 0xC0F2, 0x02,
+       0x6F12, 0x000C, 0x02,
+       0x6F12, 0x6047, 0x02,
+       0x6F12, 0x3108, 0x02,
+       0x6F12, 0x021C, 0x02,
+       0x6F12, 0x0000, 0x02,
+       0x6F12, 0x0005, 0x02,
+       0x602A, 0x4A00, 0x02,
+       0x6F12, 0x0088, 0x02,
+       0x6F12, 0x0D70, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+       0x602A, 0x164C, 0x02,
+       0x6F12, 0x5555, 0x02,
+       0x602A, 0x164E, 0x02,
+       0x6F12, 0x5500, 0x02,
+       0x602A, 0x166C, 0x02,
+       0x6F12, 0x4040, 0x02,
+       0x602A, 0x166E, 0x02,
+       0x6F12, 0x4040, 0x02,
+       0xFCFC, 0x4000, 0x02,
+       0xF496, 0x0048, 0x02,
+       0xF470, 0x0008, 0x02,
+       0xF43A, 0x0015, 0x02,
+       0xF484, 0x0006, 0x02,
+       0xF442, 0x44C6, 0x02,
+       0xF408, 0xFFF7, 0x02,
+       0xF494, 0x0010, 0x02,
+       0xF4D4, 0x0038, 0x02,
+       0xF4D6, 0x0039, 0x02,
+       0xF4D8, 0x0034, 0x02,
+       0xF4DA, 0x0035, 0x02,
+       0xF4DC, 0x0038, 0x02,
+       0xF4DE, 0x0039, 0x02,
+       0xF47C, 0x001F, 0x02,
+       0xF62E, 0x00C5, 0x02,
+       0xF630, 0x00CD, 0x02,
+       0xF632, 0x00DD, 0x02,
+       0xF634, 0x00E5, 0x02,
+       0xF636, 0x00F5, 0x02,
+       0xF638, 0x00FD, 0x02,
+       0xF63A, 0x010D, 0x02,
+       0xF63C, 0x0115, 0x02,
+       0xF63E, 0x0125, 0x02,
+       0xF640, 0x012D, 0x02,
+       0x3070, 0x0000, 0x02,
+       0x31C0, 0x00C8, 0x02,
+       0x31A4, 0x0102, 0x02,
+};
+
+/* 4:3 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_4624x3466_30fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x0010, 0x02,
+       0x034A, 0x0D9F, 0x02,
+       0x034C, 0x1210, 0x02,
+       0x034E, 0x0D8A, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x0E3B, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0011, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0001, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0001, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x0130, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+/* 16:9 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_4624x2602_30fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x01C0, 0x02,
+       0x034A, 0x0BEF, 0x02,
+       0x034C, 0x1210, 0x02,
+       0x034E, 0x0A2A, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x0E3B, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0011, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0001, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0001, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x0130, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+/* 4:3 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_2312x1732_60fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x0010, 0x02,
+       0x034A, 0x0D9F, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x06C4, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x071E, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0122, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0003, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0003, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+#if defined(USE_SMART_BINNING_FRONT)
+/* 4:3 16x10 margin, EXTCLK 26Mhz */
+/* smart binning 2 mode setting */
+const u32 sensor_3p8_setfile_A_2312x1732_30fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x0010, 0x02,
+       0x034A, 0x0D9F, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x06C4, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x0E3B, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0011, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0001, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0001, 0x02,
+       0x0400, 0x0002, 0x02,
+       0x0404, 0x0020, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0xA060, 0x02,
+};
+#else  /*original binning*/
+/* 4:3 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_2312x1732_30fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x0010, 0x02,
+       0x034A, 0x0D9F, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x06C4, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x0E3B, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0122, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0003, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0003, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+#endif
+
+/* 4:3 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_2312x1732_15fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x0010, 0x02,
+       0x034A, 0x0D97, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x06C4, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x1C76, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0122, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0003, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0003, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+/* 16:9 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_2312x1300_60fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x01C0, 0x02,
+       0x034A, 0x0BEF, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x0514, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x071E, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0122, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0003, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0003, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+#if defined(USE_SMART_BINNING_FRONT)
+/* 16:9 16x10 margin, EXTCLK 26Mhz */
+/* smart binning 2 mode setting */
+const u32 sensor_3p8_setfile_A_2312x1300_30fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x01C0, 0x02,
+       0x034A, 0x0BEF, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x0514, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x0E3B, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0011, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0001, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0001, 0x02,
+       0x0400, 0x0002, 0x02,
+       0x0404, 0x0020, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0xA060, 0x02,
+};
+#else /*original binning*/
+/* 16:9 16x10 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_2312x1300_30fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0010, 0x02,
+       0x0348, 0x121F, 0x02,
+       0x0346, 0x01C0, 0x02,
+       0x034A, 0x0BEF, 0x02,
+       0x034C, 0x0908, 0x02,
+       0x034E, 0x0514, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x0E3B, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0122, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0003, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0003, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0001, 0x02,
+       0x1006, 0x0002, 0x02,
+       0xF440, 0x002F, 0x02,
+       0x3664, 0x0019, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x00A0, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+#endif
+
+/* 4:3 4x4 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_1152x864_120fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0018, 0x02,
+       0x0348, 0x1217, 0x02,
+       0x0346, 0x0010, 0x02,
+       0x034A, 0x0D8F, 0x02,
+       0x034C, 0x0480, 0x02,
+       0x034E, 0x0360, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x038F, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0144, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0007, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0007, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0000, 0x02,
+       0x1006, 0x0003, 0x02,
+       0xF440, 0x00AF, 0x02,
+       0x3664, 0x0011, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x0007, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+/* 16:9 4x4 margin, EXTCLK 26Mhz */
+const u32 sensor_3p8_setfile_A_1152x648_120fps[] = {
+       0xFCFC, 0x4000, 0x02,
+       0x6214, 0x7971, 0x02,
+       0x6218, 0x7150, 0x02,
+       0x0136, 0x1A00, 0x02,
+       0x0300, 0x0003, 0x02,
+       0x0304, 0x0007, 0x02,
+       0x0306, 0x0071, 0x02,
+       0x030E, 0x0070, 0x02,
+       0x3004, 0x0003, 0x02,
+       0x0344, 0x0018, 0x02,
+       0x0348, 0x1217, 0x02,
+       0x0346, 0x01C8, 0x02,
+       0x034A, 0x0BE7, 0x02,
+       0x034C, 0x0480, 0x02,
+       0x034E, 0x0288, 0x02,
+       0x0342, 0x1400, 0x02,
+       0x0340, 0x038F, 0x02,
+       0x0202, 0x0200, 0x02,
+       0x0200, 0x0618, 0x02,
+       0x021E, 0x0300, 0x02,
+       0x021C, 0x0000, 0x02,
+       0x0900, 0x0144, 0x02,
+       0x0380, 0x0001, 0x02,
+       0x0382, 0x0007, 0x02,
+       0x0384, 0x0001, 0x02,
+       0x0386, 0x0007, 0x02,
+       0x0400, 0x0000, 0x02,
+       0x0404, 0x0010, 0x02,
+       0x3604, 0x0002, 0x02,
+       0x3606, 0x0103, 0x02,
+       0x0216, 0x0000, 0x02,
+       0x3000, 0x0000, 0x02,
+       0x1006, 0x0003, 0x02,
+       0xF440, 0x00AF, 0x02,
+       0x3664, 0x0011, 0x02,
+       0x3058, 0x0000, 0x02,
+       0x317A, 0x0007, 0x02,
+       0x6028, 0x2000, 0x02,
+       0x602A, 0x162C, 0x02,
+       0x6F12, 0x8080, 0x02,
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_4624x3466_30fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x0E3B, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_4624x2602_30fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x0E3B, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_2312x1732_60fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x071E, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_2312x1732_30fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x0E3B, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_2312x1732_15fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x1C76, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_2312x1300_60fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x071E, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_2312x1300_30fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x0E3B, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_1152x864_120fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x038F, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+const struct sensor_pll_info sensor_3p8_pllinfo_A_1152x648_120fps = {
+       EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */
+       0x03, /* vt_pix_clk_div (0x0300) */
+       0x01, /* vt_sys_clk_div (0x0302) */
+       0x07, /* pre_pll_clk_div(0x0304) */
+       0x71, /* pll_multiplier (0x0306) */
+       0x08, /* op_pix_clk_div (0x0308) */
+       0x01, /* op_sys_clk_div (0x030A) */
+
+       0x04, /* secnd_pre_pll_clk_div(0x030C) */
+       0x70, /* secnd_pll_multiplier   (0x030E) */
+       0x038F, /* frame_length_lines   (0x0340) */
+       0x1400, /* line_length_pck              (0x0342) */
+};
+
+
+static const u32 *sensor_3p8_setfiles_A[] = {
+       /* 16x12 margin */
+       sensor_3p8_setfile_A_4624x3466_30fps,
+       sensor_3p8_setfile_A_4624x2602_30fps,
+       sensor_3p8_setfile_A_2312x1732_60fps,
+       sensor_3p8_setfile_A_2312x1732_30fps,
+       sensor_3p8_setfile_A_2312x1732_15fps,
+       sensor_3p8_setfile_A_2312x1300_60fps,
+       sensor_3p8_setfile_A_2312x1300_30fps,
+       sensor_3p8_setfile_A_1152x864_120fps,
+       sensor_3p8_setfile_A_1152x648_120fps,
+};
+
+static const u32 sensor_3p8_setfile_A_sizes[] = {
+       /* 16x12 margin */
+       sizeof(sensor_3p8_setfile_A_4624x3466_30fps) / sizeof(sensor_3p8_setfile_A_4624x3466_30fps[0]),
+       sizeof(sensor_3p8_setfile_A_4624x2602_30fps) / sizeof(sensor_3p8_setfile_A_4624x2602_30fps[0]),
+       sizeof(sensor_3p8_setfile_A_2312x1732_60fps) / sizeof(sensor_3p8_setfile_A_2312x1732_60fps[0]),
+       sizeof(sensor_3p8_setfile_A_2312x1732_30fps) / sizeof(sensor_3p8_setfile_A_2312x1732_30fps[0]),
+       sizeof(sensor_3p8_setfile_A_2312x1732_15fps) / sizeof(sensor_3p8_setfile_A_2312x1732_15fps[0]),
+       sizeof(sensor_3p8_setfile_A_2312x1300_60fps) / sizeof(sensor_3p8_setfile_A_2312x1300_60fps[0]),
+       sizeof(sensor_3p8_setfile_A_2312x1300_30fps) / sizeof(sensor_3p8_setfile_A_2312x1300_30fps[0]),
+       sizeof(sensor_3p8_setfile_A_1152x864_120fps) / sizeof(sensor_3p8_setfile_A_1152x864_120fps[0]),
+       sizeof(sensor_3p8_setfile_A_1152x648_120fps) / sizeof(sensor_3p8_setfile_A_1152x648_120fps[0]),
+};
+
+static const struct sensor_pll_info *sensor_3p8_pllinfos_A[] = {
+       /* 16x12 margin */
+       &sensor_3p8_pllinfo_A_4624x3466_30fps,
+       &sensor_3p8_pllinfo_A_4624x2602_30fps,
+       &sensor_3p8_pllinfo_A_2312x1732_60fps,
+       &sensor_3p8_pllinfo_A_2312x1732_30fps,
+       &sensor_3p8_pllinfo_A_2312x1732_15fps,
+       &sensor_3p8_pllinfo_A_2312x1300_60fps,
+       &sensor_3p8_pllinfo_A_2312x1300_30fps,
+       &sensor_3p8_pllinfo_A_1152x864_120fps,
+       &sensor_3p8_pllinfo_A_1152x648_120fps,
+};
+
+#endif
diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6.c b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6.c
new file mode 100644 (file)
index 0000000..55d3a3e
--- /dev/null
@@ -0,0 +1,1867 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2016 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 <linux/of_gpio.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include <exynos-fimc-is-sensor.h>
+#include "fimc-is-hw.h"
+#include "fimc-is-core.h"
+#include "fimc-is-param.h"
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-device-sensor-peri.h"
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-dt.h"
+#include "fimc-is-cis-3p8.h"
+#include "fimc-is-cis-3p8-setA.h"
+#include "fimc-is-cis-3p8-setB.h"
+
+#include "fimc-is-helper-i2c.h"
+
+#define SENSOR_NAME "S5K3P8"
+/* #define DEBUG_3P8_PLL */
+
+static const struct v4l2_subdev_ops subdev_ops;
+
+static const u32 *sensor_3p8_global;
+static u32 sensor_3p8_global_size;
+static const u32 **sensor_3p8_setfiles;
+static const u32 *sensor_3p8_setfile_sizes;
+static u32 sensor_3p8_max_setfile_num;
+static const struct sensor_pll_info **sensor_3p8_pllinfos;
+
+/* variables of pdaf setting */
+static const u32 *sensor_3p8_pdaf_global;
+static u32 sensor_3p8_pdaf_global_size;
+static const u32 **sensor_3p8_pdaf_setfiles;
+static const u32 *sensor_3p8_pdaf_setfile_sizes;
+static u32 sensor_3p8_pdaf_max_setfile_num;
+static const struct sensor_pll_info **sensor_3p8_pdaf_pllinfos;
+
+static void sensor_3p8_cis_data_calculation(const struct sensor_pll_info *pll_info, cis_shared_data *cis_data)
+{
+       u32 pll_voc_a = 0, vt_pix_clk_hz = 0;
+       u32 frame_rate = 0, max_fps = 0, frame_valid_us = 0;
+
+       BUG_ON(!pll_info);
+
+       /* 1. mipi data rate calculation (Mbps/Lane) */
+       /* ToDo: using output Pixel Clock Divider Value */
+       /* pll_voc_b = pll_info->ext_clk / pll_info->secnd_pre_pll_clk_div * pll_info->secnd_pll_multiplier * 2;
+       op_sys_clk_hz = pll_voc_b / pll_info->op_sys_clk_div;
+       if(gpsSensorExInfo) {
+               gpsSensorExInfo->uiMIPISpeedBps = op_sys_clk_hz;
+               gpsSensorExInfo->uiMCLK = sensorInfo.ext_clk;
+       } */
+
+       /* 2. pixel rate calculation (Mpps) */
+       pll_voc_a = pll_info->ext_clk / pll_info->pre_pll_clk_div * pll_info->pll_multiplier;
+       vt_pix_clk_hz = (pll_voc_a / pll_info->vt_pix_clk_div) * 4;
+
+       dbg_sensor(1, "ext_clock(%d) / pre_pll_clk_div(%d) * pll_multiplier(%d) = pll_voc_a(%d)\n",
+                                               pll_info->ext_clk, pll_info->pre_pll_clk_div,
+                                               pll_info->pll_multiplier, pll_voc_a);
+       dbg_sensor(1, "pll_voc_a(%d) / (vt_sys_clk_div(%d) * vt_pix_clk_div(%d)) = pixel clock (%d hz)\n",
+                                               pll_voc_a, pll_info->vt_sys_clk_div,
+                                               pll_info->vt_pix_clk_div, vt_pix_clk_hz);
+
+       /* 3. the time of processing one frame calculation (us) */
+       cis_data->min_frame_us_time = (pll_info->frame_length_lines * pll_info->line_length_pck
+                                       / (vt_pix_clk_hz / (1000 * 1000)));
+       cis_data->cur_frame_us_time = cis_data->min_frame_us_time;
+
+       /* 4. FPS calculation */
+       frame_rate = vt_pix_clk_hz / (pll_info->frame_length_lines * pll_info->line_length_pck);
+       dbg_sensor(1, "frame_rate (%d) = vt_pix_clk_hz(%d) / "
+               KERN_CONT "(pll_info->frame_length_lines(%d) * pll_info->line_length_pck(%d))\n",
+               frame_rate, vt_pix_clk_hz, pll_info->frame_length_lines, pll_info->line_length_pck);
+
+       /* calculate max fps */
+       max_fps = (vt_pix_clk_hz * 10) / (pll_info->frame_length_lines * pll_info->line_length_pck);
+       max_fps = (max_fps % 10 >= 5 ? frame_rate + 1 : frame_rate);
+
+       cis_data->pclk = vt_pix_clk_hz;
+       cis_data->max_fps = max_fps;
+       cis_data->frame_length_lines = pll_info->frame_length_lines;
+       cis_data->line_length_pck = pll_info->line_length_pck;
+       cis_data->line_readOut_time = sensor_cis_do_div64((u64)cis_data->line_length_pck * (u64)(1000 * 1000 * 1000), cis_data->pclk);
+       cis_data->rolling_shutter_skew = (cis_data->cur_height - 1) * cis_data->line_readOut_time;
+       cis_data->stream_on = false;
+
+       /* Frame valid time calcuration */
+       frame_valid_us = sensor_cis_do_div64((u64)cis_data->cur_height * (u64)cis_data->line_length_pck * (u64)(1000 * 1000), cis_data->pclk);
+       cis_data->frame_valid_us_time = (int)frame_valid_us;
+
+       dbg_sensor(1, "%s\n", __func__);
+       dbg_sensor(1, "Sensor size(%d x %d) setting: SUCCESS!\n",
+                                       cis_data->cur_width, cis_data->cur_height);
+       dbg_sensor(1, "Frame Valid(us): %d\n", frame_valid_us);
+       dbg_sensor(1, "rolling_shutter_skew: %lld\n", cis_data->rolling_shutter_skew);
+
+       dbg_sensor(1, "Fps: %d, max fps(%d)\n", frame_rate, cis_data->max_fps);
+       dbg_sensor(1, "min_frame_time(%d us)\n", cis_data->min_frame_us_time);
+       dbg_sensor(1, "Pixel rate(Mbps): %d\n", cis_data->pclk / 1000000);
+       /* dbg_sensor(1, "Mbps/lane : %d Mbps\n", pll_voc_b / pll_info->op_sys_clk_div / 1000 / 1000); */
+
+       /* Frame period calculation */
+       cis_data->frame_time = (cis_data->line_readOut_time * cis_data->cur_height / 1000);
+       cis_data->rolling_shutter_skew = (cis_data->cur_height - 1) * cis_data->line_readOut_time;
+
+       dbg_sensor(1, "[%s] frame_time(%d), rolling_shutter_skew(%lld)\n", __func__,
+               cis_data->frame_time, cis_data->rolling_shutter_skew);
+
+       /* Constant values */
+       cis_data->min_fine_integration_time = SENSOR_3P8_FINE_INTEGRATION_TIME_MIN;
+       cis_data->max_fine_integration_time = SENSOR_3P8_FINE_INTEGRATION_TIME_MAX;
+       cis_data->min_coarse_integration_time = SENSOR_3P8_COARSE_INTEGRATION_TIME_MIN;
+       cis_data->max_margin_coarse_integration_time = SENSOR_3P8_COARSE_INTEGRATION_TIME_MAX_MARGIN;
+}
+
+static int sensor_3p8_wait_stream_off_status(cis_shared_data *cis_data)
+{
+       int ret = 0;
+       u32 timeout = 0;
+
+       BUG_ON(!cis_data);
+
+#define STREAM_OFF_WAIT_TIME 250
+       while (timeout < STREAM_OFF_WAIT_TIME) {
+               if (cis_data->is_active_area == false &&
+                               cis_data->stream_on == false) {
+                       pr_debug("actual stream off\n");
+                       break;
+               }
+               timeout++;
+       }
+
+       if (timeout == STREAM_OFF_WAIT_TIME) {
+               pr_err("actual stream off wait timeout\n");
+               ret = -1;
+       }
+
+       return ret;
+}
+
+/* CIS OPS */
+int sensor_3p8_cis_init(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       u32 setfile_index = 0;
+       cis_setting_info setinfo;
+       setinfo.param = NULL;
+       setinfo.return_value = 0;
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+       if (!cis) {
+               err("cis is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       BUG_ON(!cis->cis_data);
+       memset(cis->cis_data, 0, sizeof(cis_shared_data));
+       cis->rev_flag = false;
+
+       ret = sensor_cis_check_rev(cis);
+       if (ret < 0) {
+               warn("sensor_3p8_check_rev is fail when cis init");
+               cis->rev_flag = true;
+               ret = 0;
+       }
+
+       cis->cis_data->cur_width = SENSOR_3P8_MAX_WIDTH;
+       cis->cis_data->cur_height = SENSOR_3P8_MAX_HEIGHT;
+       cis->cis_data->low_expo_start = 33000;
+       cis->need_mode_change = false;
+
+       sensor_3p8_cis_data_calculation(sensor_3p8_pllinfos[setfile_index], cis->cis_data);
+
+       setinfo.return_value = 0;
+       CALL_CISOPS(cis, cis_get_min_exposure_time, subdev, &setinfo.return_value);
+       dbg_sensor(1, "[%s] min exposure time : %d\n", __func__, setinfo.return_value);
+       setinfo.return_value = 0;
+       CALL_CISOPS(cis, cis_get_max_exposure_time, subdev, &setinfo.return_value);
+       dbg_sensor(1, "[%s] max exposure time : %d\n", __func__, setinfo.return_value);
+       setinfo.return_value = 0;
+       CALL_CISOPS(cis, cis_get_min_analog_gain, subdev, &setinfo.return_value);
+       dbg_sensor(1, "[%s] min again : %d\n", __func__, setinfo.return_value);
+       setinfo.return_value = 0;
+       CALL_CISOPS(cis, cis_get_max_analog_gain, subdev, &setinfo.return_value);
+       dbg_sensor(1, "[%s] max again : %d\n", __func__, setinfo.return_value);
+       setinfo.return_value = 0;
+       CALL_CISOPS(cis, cis_get_min_digital_gain, subdev, &setinfo.return_value);
+       dbg_sensor(1, "[%s] min dgain : %d\n", __func__, setinfo.return_value);
+       setinfo.return_value = 0;
+       CALL_CISOPS(cis, cis_get_max_digital_gain, subdev, &setinfo.return_value);
+       dbg_sensor(1, "[%s] max dgain : %d\n", __func__, setinfo.return_value);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_log_status(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client = NULL;
+       u8 data8 = 0;
+       u16 data16 = 0;
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+       if (!cis) {
+               err("cis is NULL");
+               ret = -ENODEV;
+               goto p_err;
+       }
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -ENODEV;
+               goto p_err;
+       }
+
+       pr_err("[SEN:DUMP] *******************************\n");
+       ret = fimc_is_sensor_read16(client, 0x0000, &data16);
+       if (unlikely(!ret)) printk("[SEN:DUMP] model_id(%x)\n", data16);
+       ret = fimc_is_sensor_read8(client, 0x0002, &data8);
+       if (unlikely(!ret)) printk("[SEN:DUMP] revision_number(%x)\n", data8);
+       ret = fimc_is_sensor_read8(client, 0x0005, &data8);
+       if (unlikely(!ret)) printk("[SEN:DUMP] frame_count(%x)\n", data8);
+       ret = fimc_is_sensor_read8(client, 0x0100, &data8);
+       if (unlikely(!ret)) printk("[SEN:DUMP] mode_select(%x)\n", data8);
+
+       if (cis->use_pdaf == true) {
+               sensor_cis_dump_registers(subdev, sensor_3p8_pdaf_setfiles[0], sensor_3p8_pdaf_setfile_sizes[0]);
+       } else {
+               sensor_cis_dump_registers(subdev, sensor_3p8_setfiles[0], sensor_3p8_setfile_sizes[0]);
+       }
+
+       pr_err("[SEN:DUMP] *******************************\n");
+
+p_err:
+       return ret;
+}
+
+#if USE_GROUP_PARAM_HOLD
+static int sensor_3p8_cis_group_param_hold_func(struct v4l2_subdev *subdev, unsigned int hold)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis = NULL;
+       struct i2c_client *client = NULL;
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if (hold == cis->cis_data->group_param_hold) {
+               pr_debug("already group_param_hold (%d)\n", cis->cis_data->group_param_hold);
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write8(client, 0x0104, hold);
+       if (ret < 0)
+               goto p_err;
+
+       cis->cis_data->group_param_hold = hold;
+       ret = 1;
+p_err:
+       return ret;
+}
+#else
+static inline int sensor_3p8_cis_group_param_hold_func(struct v4l2_subdev *subdev, unsigned int hold)
+{ return 0; }
+#endif
+
+/* Input
+ *     hold : true - hold, flase - no hold
+ * Output
+ *      return: 0 - no effect(already hold or no hold)
+ *             positive - setted by request
+ *             negative - ERROR value
+ */
+int sensor_3p8_cis_group_param_hold(struct v4l2_subdev *subdev, bool hold)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis = NULL;
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       ret = sensor_3p8_cis_group_param_hold_func(subdev, hold);
+       if (ret < 0)
+               goto p_err;
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_set_global_setting(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis = NULL;
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+       BUG_ON(!cis);
+
+       /* ARM start */
+       ret = fimc_is_sensor_write16(cis->client, 0xFCFC, 0x4000);
+       ret = fimc_is_sensor_write16(cis->client, 0x6010, 0x0001);
+       /* 3ms delay to operate sensor FW */
+       usleep_range(3000, 3000);
+
+       /* setfile global setting is at camera entrance */
+       if (cis->use_pdaf == true) {
+               ret = sensor_cis_set_registers(subdev, sensor_3p8_pdaf_global, sensor_3p8_pdaf_global_size);
+       } else {
+               ret = sensor_cis_set_registers(subdev, sensor_3p8_global, sensor_3p8_global_size);
+       }
+
+       if (ret < 0) {
+               err("sensor_3p8_set_registers fail!!");
+               goto p_err;
+       }
+
+       dbg_sensor(1, "[%s] global setting done\n", __func__);
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_mode_change(struct v4l2_subdev *subdev, u32 mode)
+{
+       int ret = 0;
+       u32 max_setfile_num = 0;
+       struct fimc_is_cis *cis = NULL;
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       if (cis->use_pdaf == true) {
+               max_setfile_num = sensor_3p8_pdaf_max_setfile_num;
+       } else {
+               max_setfile_num = sensor_3p8_max_setfile_num;
+       }
+
+       if (mode > max_setfile_num) {
+               err("invalid mode(%d)!!", mode);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* If check_rev fail when cis_init, one more check_rev in mode_change */
+       if (cis->rev_flag == true) {
+               cis->rev_flag = false;
+               ret = sensor_cis_check_rev(cis);
+               if (ret < 0) {
+                       err("sensor_3p8_check_rev is fail");
+                       goto p_err;
+               }
+       }
+
+       if (cis->use_pdaf == true) {
+               sensor_3p8_cis_data_calculation(sensor_3p8_pdaf_pllinfos[mode], cis->cis_data);
+               ret = sensor_cis_set_registers(subdev, sensor_3p8_pdaf_setfiles[mode], sensor_3p8_pdaf_setfile_sizes[mode]);
+       } else {
+               sensor_3p8_cis_data_calculation(sensor_3p8_pllinfos[mode], cis->cis_data);
+               ret = sensor_cis_set_registers(subdev, sensor_3p8_setfiles[mode], sensor_3p8_setfile_sizes[mode]);
+       }
+
+       if (ret < 0) {
+               err("sensor_3p8_set_registers fail!!");
+               goto p_err;
+       }
+
+       if (cis->use_pdaf == true) {
+#if defined(S5K3P8_PDAF_DISABLE)
+               /* TEMP : PDAF disable */
+               ret = fimc_is_sensor_write16(cis->client, 0xFCFC, 0x4000);
+               ret = fimc_is_sensor_write8(cis->client, 0x3059, 0x00);
+               info("[%s] S5K3P8_PDAF_DISABLE\n", __func__);
+#endif
+
+#if defined(S5K3P8_TAIL_DISABLE)
+               /* TEMP : Tail mode disable */
+               ret = fimc_is_sensor_write16(cis->client, 0x6028, 0x2000);
+               ret = fimc_is_sensor_write16(cis->client, 0x602A, 0x19E0);
+               ret = fimc_is_sensor_write16(cis->client, 0x6F12, 0x0001);
+
+               ret = fimc_is_sensor_write16(cis->client, 0xFCFC, 0x4000);
+               ret = fimc_is_sensor_write16(cis->client, 0x30E2, 0x0000);
+               info("[%s] S5K3P8_TAIL_DISABLE\n", __func__);
+#endif
+
+#if defined(S5K3P8_BPC_DISABLE)
+               /* TEMP : BPC disable */
+               ret = fimc_is_sensor_write16(cis->client, 0xFCFC, 0x4000);
+               ret = fimc_is_sensor_write8(cis->client, 0x0B0E, 0x00);
+               info("[%s] S5K3P8_BPC_DISABLE\n", __func__);
+#endif
+       }
+
+       dbg_sensor(1, "[%s] mode changed(%d)\n", __func__, mode);
+
+p_err:
+       return ret;
+}
+
+/* TODO: Sensor set size sequence(sensor done, sensor stop, 3AA done in FW case */
+int sensor_3p8_cis_set_size(struct v4l2_subdev *subdev, cis_shared_data *cis_data)
+{
+       int ret = 0;
+       bool binning = false;
+       u32 ratio_w = 0, ratio_h = 0, start_x = 0, start_y = 0, end_x = 0, end_y = 0;
+       u32 even_x= 0, odd_x = 0, even_y = 0, odd_y = 0;
+       struct i2c_client *client = NULL;
+       struct fimc_is_cis *cis = NULL;
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+       BUG_ON(!cis);
+
+       dbg_sensor(1, "[MOD:D:%d] %s\n", cis->id, __func__);
+
+       if (unlikely(!cis_data)) {
+               err("cis data is NULL");
+               if (unlikely(!cis->cis_data)) {
+                       ret = -EINVAL;
+                       goto p_err;
+               } else {
+                       cis_data = cis->cis_data;
+               }
+       }
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* Wait actual stream off */
+       ret = sensor_3p8_wait_stream_off_status(cis_data);
+       if (ret) {
+               err("Must stream off\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       binning = cis_data->binning;
+       if (binning) {
+               ratio_w = (SENSOR_3P8_MAX_WIDTH / cis_data->cur_width);
+               ratio_h = (SENSOR_3P8_MAX_HEIGHT / cis_data->cur_height);
+       } else {
+               ratio_w = 1;
+               ratio_h = 1;
+       }
+
+       if (((cis_data->cur_width * ratio_w) > SENSOR_3P8_MAX_WIDTH) ||
+               ((cis_data->cur_height * ratio_h) > SENSOR_3P8_MAX_HEIGHT)) {
+               err("Config max sensor size over~!!\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       /* 1. page_select */
+       ret = fimc_is_sensor_write16(client, 0x6028, 0x2000);
+       if (ret < 0)
+                goto p_err;
+
+       /* 2. pixel address region setting */
+       start_x = ((SENSOR_3P8_MAX_WIDTH - cis_data->cur_width * ratio_w) / 2) & (~0x1);
+       start_y = ((SENSOR_3P8_MAX_HEIGHT - cis_data->cur_height * ratio_h) / 2) & (~0x1);
+       end_x = start_x + (cis_data->cur_width * ratio_w - 1);
+       end_y = start_y + (cis_data->cur_height * ratio_h - 1);
+
+       if (!(end_x & (0x1)) || !(end_y & (0x1))) {
+               err("Sensor pixel end address must odd\n");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write16(client, 0x0344, start_x);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x0346, start_y);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x0348, end_x);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x034A, end_y);
+       if (ret < 0)
+                goto p_err;
+
+       /* 3. output address setting */
+       ret = fimc_is_sensor_write16(client, 0x034C, cis_data->cur_width);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x034E, cis_data->cur_height);
+       if (ret < 0)
+                goto p_err;
+
+       /* If not use to binning, sensor image should set only crop */
+       if (!binning) {
+               dbg_sensor(1, "Sensor size set is not binning\n");
+               goto p_err;
+       }
+
+       /* 4. sub sampling setting */
+       even_x = 1;     /* 1: not use to even sampling */
+       even_y = 1;
+       odd_x = (ratio_w * 2) - even_x;
+       odd_y = (ratio_h * 2) - even_y;
+
+       ret = fimc_is_sensor_write16(client, 0x0380, even_x);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x0382, odd_x);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x0384, even_y);
+       if (ret < 0)
+                goto p_err;
+       ret = fimc_is_sensor_write16(client, 0x0386, odd_y);
+       if (ret < 0)
+                goto p_err;
+
+       /* 5. binnig setting */
+       ret = fimc_is_sensor_write8(client, 0x0900, binning);   /* 1:  binning enable, 0: disable */
+       if (ret < 0)
+               goto p_err;
+       ret = fimc_is_sensor_write8(client, 0x0901, (ratio_w << 4) | ratio_h);
+       if (ret < 0)
+               goto p_err;
+
+       /* 6. scaling setting: but not use */
+       /* scaling_mode (0: No scaling, 1: Horizontal, 2: Full) */
+       ret = fimc_is_sensor_write16(client, 0x0400, 0x0000);
+       if (ret < 0)
+               goto p_err;
+       /* down_scale_m: 1 to 16 upwards (scale_n: 16(fixed))
+       down scale factor = down_scale_m / down_scale_n */
+       ret = fimc_is_sensor_write16(client, 0x0404, 0x0010);
+       if (ret < 0)
+               goto p_err;
+
+       cis_data->frame_time = (cis_data->line_readOut_time * cis_data->cur_height / 1000);
+       cis->cis_data->rolling_shutter_skew = (cis->cis_data->cur_height - 1) * cis->cis_data->line_readOut_time;
+       dbg_sensor(1, "[%s] frame_time(%d), rolling_shutter_skew(%lld)\n", __func__,
+               cis->cis_data->frame_time, cis->cis_data->rolling_shutter_skew);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec) * 1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_stream_on(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       dbg_sensor(1, "[MOD:D:%d] %s\n", cis->id, __func__);
+
+       ret = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+       if (ret < 0)
+               err("[%s] sensor_3p8_cis_group_param_hold_func fail\n", __func__);
+
+#ifdef DEBUG_3P8_PLL
+       {
+       u16 pll;
+       ret = fimc_is_sensor_read16(client, 0x0300, &pll);
+       dbg_sensor(1, "______ vt_pix_clk_div(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x0302, &pll);
+       dbg_sensor(1, "______ vt_sys_clk_div(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x0304, &pll);
+       dbg_sensor(1, "______ pre_pll_clk_div(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x0306, &pll);
+       dbg_sensor(1, "______ pll_multiplier(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x0308, &pll);
+       dbg_sensor(1, "______ op_pix_clk_div(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x030a, &pll);
+       dbg_sensor(1, "______ op_sys_clk_div(%x)\n", pll);
+
+       ret = fimc_is_sensor_read16(client, 0x030c, &pll);
+       dbg_sensor(1, "______ secnd_pre_pll_clk_div(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x030e, &pll);
+       dbg_sensor(1, "______ secnd_pll_multiplier(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x0340, &pll);
+       dbg_sensor(1, "______ frame_length_lines(%x)\n", pll);
+       ret = fimc_is_sensor_read16(client, 0x0342, &pll);
+       dbg_sensor(1, "______ line_length_pck(%x)\n", pll);
+       }
+#endif
+
+       /* Sensor stream on */
+       ret = fimc_is_sensor_write16(client, 0x6028, 0x4000);
+       if (ret < 0)
+               err("i2c transfer fail addr(%x), val(%x), ret = %d\n", 0x6028, 0x4000, ret);
+       ret = fimc_is_sensor_write16(client, 0x0100, 0x0100);
+       if (ret < 0)
+               err("i2c transfer fail addr(%x), val(%x), ret = %d\n", 0x0100, 0x0100, ret);
+
+       cis_data->stream_on = true;
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_stream_off(struct v4l2_subdev *subdev)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       dbg_sensor(1, "[MOD:D:%d] %s\n", cis->id, __func__);
+
+       ret = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+       if (ret < 0)
+               err("[%s] sensor_3p8_cis_group_param_hold_func fail\n", __func__);
+
+       /* Sensor stream off */
+       ret = fimc_is_sensor_write16(client, 0x6028, 0x4000);
+       if (ret < 0)
+               err("i2c transfer fail addr(%x), val(%x), ret = %d\n", 0x6028, 0x4000, ret);
+       ret = fimc_is_sensor_write16(client, 0x0100, 0x0000);
+       if (ret < 0)
+               err("i2c transfer fail addr(%x), val(%x), ret = %d\n", 0x0100, 0x00, ret);
+
+       cis_data->stream_on = false;
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_set_exposure_time(struct v4l2_subdev *subdev, struct ae_param *target_exposure)
+{
+       int ret = 0;
+       int hold = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+       u32 vt_pic_clk_freq_mhz = 0;
+       u16 long_coarse_int = 0;
+       u16 short_coarse_int = 0;
+       u32 line_length_pck = 0;
+       u32 min_fine_int = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!target_exposure);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       if ((target_exposure->long_val <= 0) || (target_exposure->short_val <= 0)) {
+               err("[%s] invalid target exposure(%d, %d)\n", __func__,
+                               target_exposure->long_val, target_exposure->short_val);
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), target long(%d), short(%d)\n", cis->id, __func__,
+                       cis_data->sen_vsync_count, target_exposure->long_val, target_exposure->short_val);
+
+       vt_pic_clk_freq_mhz = cis_data->pclk / (1000 * 1000);
+       line_length_pck = cis_data->line_length_pck;
+       min_fine_int = cis_data->min_fine_integration_time;
+
+       long_coarse_int = ((target_exposure->long_val * vt_pic_clk_freq_mhz) - min_fine_int) / line_length_pck;
+       short_coarse_int = ((target_exposure->short_val * vt_pic_clk_freq_mhz) - min_fine_int) / line_length_pck;
+
+       if (long_coarse_int > cis_data->max_coarse_integration_time) {
+               dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), long coarse(%d) max(%d)\n", cis->id, __func__,
+                       cis_data->sen_vsync_count, long_coarse_int, cis_data->max_coarse_integration_time);
+               long_coarse_int = cis_data->max_coarse_integration_time;
+       }
+
+       if (short_coarse_int > cis_data->max_coarse_integration_time) {
+               dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), short coarse(%d) max(%d)\n", cis->id, __func__,
+                       cis_data->sen_vsync_count, short_coarse_int, cis_data->max_coarse_integration_time);
+               short_coarse_int = cis_data->max_coarse_integration_time;
+       }
+
+       if (long_coarse_int < cis_data->min_coarse_integration_time) {
+               dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), long coarse(%d) min(%d)\n", cis->id, __func__,
+                       cis_data->sen_vsync_count, long_coarse_int, cis_data->min_coarse_integration_time);
+               long_coarse_int = cis_data->min_coarse_integration_time;
+       }
+
+       if (short_coarse_int < cis_data->min_coarse_integration_time) {
+               dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), short coarse(%d) min(%d)\n", cis->id, __func__,
+                       cis_data->sen_vsync_count, short_coarse_int, cis_data->min_coarse_integration_time);
+               short_coarse_int = cis_data->min_coarse_integration_time;
+       }
+
+       hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x01);
+       if (hold < 0) {
+               ret = hold;
+               goto p_err;
+       }
+
+       /* Short exposure */
+       ret = fimc_is_sensor_write16(client, 0x0202, short_coarse_int);
+       if (ret < 0)
+               goto p_err;
+
+       /* Long exposure */
+       if (cis_data->companion_data.enable_wdr == true) {
+               ret = fimc_is_sensor_write16(client, 0x021E, long_coarse_int);
+               if (ret < 0)
+                       goto p_err;
+       }
+
+       dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), vt_pic_clk_freq_mhz (%d),"
+               KERN_CONT "line_length_pck(%d), min_fine_int (%d)\n", cis->id, __func__,
+               cis_data->sen_vsync_count, vt_pic_clk_freq_mhz, line_length_pck, min_fine_int);
+       dbg_sensor(1, "[MOD:D:%d] %s, vsync_cnt(%d), frame_length_lines(%#x),"
+               KERN_CONT "long_coarse_int %#x, short_coarse_int %#x\n", cis->id, __func__,
+               cis_data->sen_vsync_count, cis_data->frame_length_lines, long_coarse_int, short_coarse_int);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       if (hold > 0) {
+               hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+               if (hold < 0)
+                       ret = hold;
+       }
+
+       return ret;
+}
+
+int sensor_3p8_cis_get_min_exposure_time(struct v4l2_subdev *subdev, u32 *min_expo)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis = NULL;
+       cis_shared_data *cis_data = NULL;
+       u32 min_integration_time = 0;
+       u32 min_coarse = 0;
+       u32 min_fine = 0;
+       u32 vt_pic_clk_freq_mhz = 0;
+       u32 line_length_pck = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!min_expo);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       vt_pic_clk_freq_mhz = cis_data->pclk / (1000 * 1000);
+       if (vt_pic_clk_freq_mhz == 0) {
+               pr_err("[MOD:D:%d] %s, Invalid vt_pic_clk_freq_mhz(%d)\n", cis->id, __func__, vt_pic_clk_freq_mhz);
+               goto p_err;
+       }
+       line_length_pck = cis_data->line_length_pck;
+       min_coarse = cis_data->min_coarse_integration_time;
+       min_fine = cis_data->min_fine_integration_time;
+
+       min_integration_time = ((line_length_pck * min_coarse) + min_fine) / vt_pic_clk_freq_mhz;
+       *min_expo = min_integration_time;
+
+       dbg_sensor(1, "[%s] min integration time %d\n", __func__, min_integration_time);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_get_max_exposure_time(struct v4l2_subdev *subdev, u32 *max_expo)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       cis_shared_data *cis_data;
+       u32 max_integration_time = 0;
+       u32 max_coarse_margin = 0;
+       u32 max_fine_margin = 0;
+       u32 max_coarse = 0;
+       u32 max_fine = 0;
+       u32 vt_pic_clk_freq_mhz = 0;
+       u32 line_length_pck = 0;
+       u32 frame_length_lines = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!max_expo);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       vt_pic_clk_freq_mhz = cis_data->pclk / (1000 * 1000);
+       if (vt_pic_clk_freq_mhz == 0) {
+               pr_err("[MOD:D:%d] %s, Invalid vt_pic_clk_freq_mhz(%d)\n", cis->id, __func__, vt_pic_clk_freq_mhz);
+               goto p_err;
+       }
+       line_length_pck = cis_data->line_length_pck;
+       frame_length_lines = cis_data->frame_length_lines;
+
+       max_coarse_margin = cis_data->max_margin_coarse_integration_time;
+       max_fine_margin = line_length_pck - cis_data->min_fine_integration_time;
+       max_coarse = frame_length_lines - max_coarse_margin;
+       max_fine = cis_data->max_fine_integration_time;
+
+       max_integration_time = ((line_length_pck * max_coarse) + max_fine) / vt_pic_clk_freq_mhz;
+
+       *max_expo = max_integration_time;
+
+       /* TODO: Is this values update hear? */
+       cis_data->max_margin_fine_integration_time = max_fine_margin;
+       cis_data->max_coarse_integration_time = max_coarse;
+
+       dbg_sensor(1, "[%s] max integration time %d, max margin fine integration %d, max coarse integration %d\n",
+                       __func__, max_integration_time, cis_data->max_margin_fine_integration_time, cis_data->max_coarse_integration_time);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_adjust_frame_duration(struct v4l2_subdev *subdev,
+                                               u32 input_exposure_time,
+                                               u32 *target_duration)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       cis_shared_data *cis_data;
+
+       u32 vt_pic_clk_freq_mhz = 0;
+       u32 line_length_pck = 0;
+       u32 frame_length_lines = 0;
+       u32 frame_duration = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!target_duration);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       vt_pic_clk_freq_mhz = cis_data->pclk / (1000 * 1000);
+       line_length_pck = cis_data->line_length_pck;
+       frame_length_lines = ((vt_pic_clk_freq_mhz * input_exposure_time) / line_length_pck);
+       frame_length_lines += cis_data->max_margin_coarse_integration_time;
+
+       frame_duration = (frame_length_lines * line_length_pck) / vt_pic_clk_freq_mhz;
+
+       dbg_sensor(1, "[%s](vsync cnt = %d) input exp(%d), adj duration, frame duraion(%d), min_frame_us(%d)\n",
+                       __func__, cis_data->sen_vsync_count, input_exposure_time, frame_duration, cis_data->min_frame_us_time);
+       dbg_sensor(1, "[%s](vsync cnt = %d) adj duration, frame duraion(%d), min_frame_us(%d)\n",
+                       __func__, cis_data->sen_vsync_count, frame_duration, cis_data->min_frame_us_time);
+
+       *target_duration = MAX(frame_duration, cis_data->min_frame_us_time);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+       return ret;
+}
+
+int sensor_3p8_cis_set_frame_duration(struct v4l2_subdev *subdev, u32 frame_duration)
+{
+       int ret = 0;
+       int hold = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+       u32 vt_pic_clk_freq_mhz = 0;
+       u32 line_length_pck = 0;
+       u16 frame_length_lines = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       if (frame_duration < cis_data->min_frame_us_time) {
+               dbg_sensor(1, "frame duration is less than min(%d)\n", frame_duration);
+               frame_duration = cis_data->min_frame_us_time;
+       }
+
+       vt_pic_clk_freq_mhz = cis_data->pclk / (1000 * 1000);
+       line_length_pck = cis_data->line_length_pck;
+
+       frame_length_lines = (u16)((vt_pic_clk_freq_mhz * frame_duration) / line_length_pck);
+
+       dbg_sensor(1, "[MOD:D:%d] %s, vt_pic_clk_freq_mhz(%#x) frame_duration = %d us,"
+               KERN_CONT "(line_length_pck%#x), frame_length_lines(%#x)\n",
+               cis->id, __func__, vt_pic_clk_freq_mhz, frame_duration, line_length_pck, frame_length_lines);
+
+       hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x01);
+       if (hold < 0) {
+               ret = hold;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write16(client, 0x0340, frame_length_lines);
+       if (ret < 0)
+               goto p_err;
+
+       cis_data->cur_frame_us_time = frame_duration;
+       cis_data->frame_length_lines = frame_length_lines;
+       cis_data->max_coarse_integration_time = cis_data->frame_length_lines - cis_data->max_margin_coarse_integration_time;
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       if (hold > 0) {
+               hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+               if (hold < 0)
+                       ret = hold;
+       }
+
+       return ret;
+}
+
+int sensor_3p8_cis_set_frame_rate(struct v4l2_subdev *subdev, u32 min_fps)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       cis_shared_data *cis_data;
+
+       u32 frame_duration = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       if (min_fps > cis_data->max_fps) {
+               err("[MOD:D:%d] %s, request FPS is too high(%d), set to max(%d)\n",
+                       cis->id, __func__, min_fps, cis_data->max_fps);
+               min_fps = cis_data->max_fps;
+       }
+
+       if (min_fps == 0) {
+               err("[MOD:D:%d] %s, request FPS is 0, set to min FPS(1)\n",
+                       cis->id, __func__);
+               min_fps = 1;
+       }
+
+       frame_duration = (1 * 1000 * 1000) / min_fps;
+
+       dbg_sensor(1, "[MOD:D:%d] %s, set FPS(%d), frame duration(%d)\n",
+                       cis->id, __func__, min_fps, frame_duration);
+
+       ret = sensor_3p8_cis_set_frame_duration(subdev, frame_duration);
+       if (ret < 0) {
+               err("[MOD:D:%d] %s, set frame duration is fail(%d)\n",
+                       cis->id, __func__, ret);
+               goto p_err;
+       }
+
+       cis_data->min_frame_us_time = frame_duration;
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+
+       return ret;
+}
+
+int sensor_3p8_cis_adjust_analog_gain(struct v4l2_subdev *subdev, u32 input_again, u32 *target_permile)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       cis_shared_data *cis_data;
+
+       u32 again_code = 0;
+       u32 again_permile = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!target_permile);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       again_code = sensor_cis_calc_again_code(input_again);
+
+       if (again_code > cis_data->max_analog_gain[0]) {
+               again_code = cis_data->max_analog_gain[0];
+       } else if (again_code < cis_data->min_analog_gain[0]) {
+               again_code = cis_data->min_analog_gain[0];
+       }
+
+       again_permile = sensor_cis_calc_again_permile(again_code);
+
+       dbg_sensor(1, "[%s] min again(%d), max(%d), input_again(%d), code(%d), permile(%d)\n", __func__,
+                       cis_data->max_analog_gain[0],
+                       cis_data->min_analog_gain[0],
+                       input_again,
+                       again_code,
+                       again_permile);
+
+       *target_permile = again_permile;
+
+       return ret;
+}
+
+int sensor_3p8_cis_set_analog_gain(struct v4l2_subdev *subdev, struct ae_param *again)
+{
+       int ret = 0;
+       int hold = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+
+       u16 analog_gain = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!again);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       analog_gain = (u16)sensor_cis_calc_again_code(again->val);
+
+       if (analog_gain < cis->cis_data->min_analog_gain[0]) {
+               analog_gain = cis->cis_data->min_analog_gain[0];
+       }
+
+       if (analog_gain > cis->cis_data->max_analog_gain[0]) {
+               analog_gain = cis->cis_data->max_analog_gain[0];
+       }
+
+       dbg_sensor(1, "[MOD:D:%d] %s(vsync cnt = %d), input_again = %d us, analog_gain(%#x)\n",
+               cis->id, __func__, cis->cis_data->sen_vsync_count, again->val, analog_gain);
+
+       hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x01);
+       if (hold < 0) {
+               ret = hold;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_write16(client, 0x0204, analog_gain);
+       if (ret < 0)
+               goto p_err;
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       if (hold > 0) {
+               hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+               if (hold < 0)
+                       ret = hold;
+       }
+
+       return ret;
+}
+
+int sensor_3p8_cis_get_analog_gain(struct v4l2_subdev *subdev, u32 *again)
+{
+       int ret = 0;
+       int hold = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+
+       u16 analog_gain = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!again);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x01);
+       if (hold < 0) {
+               ret = hold;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_read16(client, 0x0204, &analog_gain);
+       if (ret < 0)
+               goto p_err;
+
+       *again = sensor_cis_calc_again_permile(analog_gain);
+
+       dbg_sensor(1, "[MOD:D:%d] %s, cur_again = %d us, analog_gain(%#x)\n",
+                       cis->id, __func__, *again, analog_gain);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       if (hold > 0) {
+               hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+               if (hold < 0)
+                       ret = hold;
+       }
+
+       return ret;
+}
+
+int sensor_3p8_cis_get_min_analog_gain(struct v4l2_subdev *subdev, u32 *min_again)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+       u16 read_value = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!min_again);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       ret = fimc_is_sensor_read16(client, 0x0084, &read_value);
+       if (ret < 0)
+               err("i2c transfer fail addr(%x), val(%x), ret = %d\n", 0x0084, read_value, ret);
+
+       cis_data->min_analog_gain[0] = read_value;
+
+       cis_data->min_analog_gain[1] = sensor_cis_calc_again_permile(read_value);
+
+       *min_again = cis_data->min_analog_gain[1];
+
+       dbg_sensor(1, "[%s] code %d, permile %d\n", __func__,
+               cis_data->min_analog_gain[0], cis_data->min_analog_gain[1]);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_get_max_analog_gain(struct v4l2_subdev *subdev, u32 *max_again)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+       u16 read_value = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!max_again);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       ret = fimc_is_sensor_read16(client, 0x0086, &read_value);
+       if (ret < 0)
+               err("i2c transfer fail addr(%x), val(%x), ret = %d\n", 0x0086, read_value, ret);
+
+       cis_data->max_analog_gain[0] = read_value;
+
+       cis_data->max_analog_gain[1] = sensor_cis_calc_again_permile(read_value);
+
+       *max_again = cis_data->max_analog_gain[1];
+
+       dbg_sensor(1, "[%s] code %d, permile %d\n", __func__,
+               cis_data->max_analog_gain[0], cis_data->max_analog_gain[1]);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       return ret;
+}
+
+int sensor_3p8_cis_set_digital_gain(struct v4l2_subdev *subdev, struct ae_param *dgain)
+{
+       int ret = 0;
+       int hold = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+       cis_shared_data *cis_data;
+
+       u16 long_gain = 0;
+       u16 short_gain = 0;
+       u16 dgains[4] = {0};
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!dgain);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       cis_data = cis->cis_data;
+
+       long_gain = (u16)sensor_cis_calc_dgain_code(dgain->long_val);
+       short_gain = (u16)sensor_cis_calc_dgain_code(dgain->short_val);
+
+       if (long_gain < cis->cis_data->min_digital_gain[0]) {
+               long_gain = cis->cis_data->min_digital_gain[0];
+       }
+       if (long_gain > cis->cis_data->max_digital_gain[0]) {
+               long_gain = cis->cis_data->max_digital_gain[0];
+       }
+
+       if (short_gain < cis->cis_data->min_digital_gain[0]) {
+               short_gain = cis->cis_data->min_digital_gain[0];
+       }
+       if (short_gain > cis->cis_data->max_digital_gain[0]) {
+               short_gain = cis->cis_data->max_digital_gain[0];
+       }
+
+       dbg_sensor(1, "[MOD:D:%d] %s(vsync cnt = %d), input_dgain = %d/%d us, long_gain(%#x), short_gain(%#x)\n",
+                       cis->id, __func__, cis->cis_data->sen_vsync_count, dgain->long_val, dgain->short_val, long_gain, short_gain);
+
+       hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x01);
+       if (hold < 0) {
+               ret = hold;
+               goto p_err;
+       }
+
+       dgains[0] = dgains[1] = dgains[2] = dgains[3] = short_gain;
+       /* Short digital gain */
+       ret = fimc_is_sensor_write16_array(client, 0x020E, dgains, 4);
+       if (ret < 0)
+               goto p_err;
+
+       /* Long digital gain */
+       if (cis_data->companion_data.enable_wdr == true) {
+               dgains[0] = dgains[1] = dgains[2] = dgains[3] = long_gain;
+               ret = fimc_is_sensor_write16_array(client, 0x3062, dgains, 4);
+               if (ret < 0)
+                       goto p_err;
+       }
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       if (hold > 0) {
+               hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+               if (hold < 0)
+                       ret = hold;
+       }
+
+       return ret;
+}
+
+int sensor_3p8_cis_get_digital_gain(struct v4l2_subdev *subdev, u32 *dgain)
+{
+       int ret = 0;
+       int hold = 0;
+       struct fimc_is_cis *cis;
+       struct i2c_client *client;
+
+       u16 digital_gain = 0;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!dgain);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+
+       client = cis->client;
+       if (unlikely(!client)) {
+               err("client is NULL");
+               ret = -EINVAL;
+               goto p_err;
+       }
+
+       hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x01);
+       if (hold < 0) {
+               ret = hold;
+               goto p_err;
+       }
+
+       ret = fimc_is_sensor_read16(client, 0x020E, &digital_gain);
+       if (ret < 0)
+               goto p_err;
+
+       *dgain = sensor_cis_calc_dgain_permile(digital_gain);
+
+       dbg_sensor(1, "[MOD:D:%d] %s, cur_dgain = %d us, digital_gain(%#x)\n",
+                       cis->id, __func__, *dgain, digital_gain);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+p_err:
+       if (hold > 0) {
+               hold = sensor_3p8_cis_group_param_hold_func(subdev, 0x00);
+               if (hold < 0)
+                       ret = hold;
+       }
+
+       return ret;
+}
+
+int sensor_3p8_cis_get_min_digital_gain(struct v4l2_subdev *subdev, u32 *min_dgain)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       cis_shared_data *cis_data;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!min_dgain);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       /* 3P8 cannot read min/max digital gain */
+       cis_data->min_digital_gain[0] = 0x0100;
+
+       cis_data->min_digital_gain[1] = 1000;
+
+       *min_dgain = cis_data->min_digital_gain[1];
+
+       dbg_sensor(1, "[%s] code %d, permile %d\n", __func__,
+               cis_data->min_digital_gain[0], cis_data->min_digital_gain[1]);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+       return ret;
+}
+
+int sensor_3p8_cis_get_max_digital_gain(struct v4l2_subdev *subdev, u32 *max_dgain)
+{
+       int ret = 0;
+       struct fimc_is_cis *cis;
+       cis_shared_data *cis_data;
+
+#ifdef DEBUG_SENSOR_TIME
+       struct timeval st, end;
+       do_gettimeofday(&st);
+#endif
+
+       BUG_ON(!subdev);
+       BUG_ON(!max_dgain);
+
+       cis = (struct fimc_is_cis *)v4l2_get_subdevdata(subdev);
+
+       BUG_ON(!cis);
+       BUG_ON(!cis->cis_data);
+
+       cis_data = cis->cis_data;
+
+       /* 3P8 cannot read min/max digital gain */
+       cis_data->max_digital_gain[0] = 0x1000;
+
+       cis_data->max_digital_gain[1] = 16000;
+
+       *max_dgain = cis_data->max_digital_gain[1];
+
+       dbg_sensor(1, "[%s] code %d, permile %d\n", __func__,
+               cis_data->max_digital_gain[0], cis_data->max_digital_gain[1]);
+
+#ifdef DEBUG_SENSOR_TIME
+       do_gettimeofday(&end);
+       dbg_sensor(1, "[%s] time %lu us\n", __func__, (end.tv_sec - st.tv_sec)*1000000 + (end.tv_usec - st.tv_usec));
+#endif
+
+       return ret;
+}
+
+static struct fimc_is_cis_ops cis_ops = {
+       .cis_init = sensor_3p8_cis_init,
+       .cis_log_status = sensor_3p8_cis_log_status,
+       .cis_group_param_hold = sensor_3p8_cis_group_param_hold,
+       .cis_set_global_setting = sensor_3p8_cis_set_global_setting,
+       .cis_mode_change = sensor_3p8_cis_mode_change,
+       .cis_set_size = sensor_3p8_cis_set_size,
+       .cis_stream_on = sensor_3p8_cis_stream_on,
+       .cis_stream_off = sensor_3p8_cis_stream_off,
+       .cis_set_exposure_time = sensor_3p8_cis_set_exposure_time,
+       .cis_get_min_exposure_time = sensor_3p8_cis_get_min_exposure_time,
+       .cis_get_max_exposure_time = sensor_3p8_cis_get_max_exposure_time,
+       .cis_adjust_frame_duration = sensor_3p8_cis_adjust_frame_duration,
+       .cis_set_frame_duration = sensor_3p8_cis_set_frame_duration,
+       .cis_set_frame_rate = sensor_3p8_cis_set_frame_rate,
+       .cis_adjust_analog_gain = sensor_3p8_cis_adjust_analog_gain,
+       .cis_set_analog_gain = sensor_3p8_cis_set_analog_gain,
+       .cis_get_analog_gain = sensor_3p8_cis_get_analog_gain,
+       .cis_get_min_analog_gain = sensor_3p8_cis_get_min_analog_gain,
+       .cis_get_max_analog_gain = sensor_3p8_cis_get_max_analog_gain,
+       .cis_set_digital_gain = sensor_3p8_cis_set_digital_gain,
+       .cis_get_digital_gain = sensor_3p8_cis_get_digital_gain,
+       .cis_get_min_digital_gain = sensor_3p8_cis_get_min_digital_gain,
+       .cis_get_max_digital_gain = sensor_3p8_cis_get_max_digital_gain,
+       .cis_compensate_gain_for_extremely_br = sensor_cis_compensate_gain_for_extremely_br,
+       .cis_wait_streamoff = sensor_cis_wait_streamoff,
+       .cis_wait_streamon = sensor_cis_wait_streamon,
+};
+
+int cis_3p8_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       int ret = 0;
+       bool use_pdaf = false;
+
+       struct fimc_is_core *core = NULL;
+       struct v4l2_subdev *subdev_cis = NULL;
+       struct fimc_is_cis *cis = NULL;
+       struct fimc_is_device_sensor *device = NULL;
+       struct fimc_is_device_sensor_peri *sensor_peri = NULL;
+       u32 sensor_id = 0;
+       char const *setfile;
+       struct device *dev;
+       struct device_node *dnode;
+
+       BUG_ON(!client);
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               probe_info("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       dev = &client->dev;
+       dnode = dev->of_node;
+
+       if (of_property_read_bool(dnode, "use_pdaf")) {
+               use_pdaf = true;
+       }
+
+       ret = of_property_read_u32(dnode, "id", &sensor_id);
+       if (ret) {
+               err("sensor id read is fail(%d)\n", ret);
+               goto p_err;
+       }
+
+       probe_info("%s sensor id %d\n", __func__, sensor_id);
+
+       device = &core->sensor[sensor_id];
+
+       sensor_peri = find_peri_by_cis_id(device, SENSOR_NAME_S5K3P8);
+       if (!sensor_peri) {
+               probe_info("sensor peri is net yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       cis = &sensor_peri->cis;
+       if (!cis) {
+               err("cis is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       subdev_cis = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_cis) {
+               probe_err("subdev_cis is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+       sensor_peri->subdev_cis = subdev_cis;
+
+       cis->id = SENSOR_NAME_S5K3P8;
+       cis->subdev = subdev_cis;
+       cis->device = 0;
+       cis->client = client;
+       sensor_peri->module->client = cis->client;
+       cis->ctrl_delay = N_PLUS_TWO_FRAME;
+
+       cis->cis_data = kzalloc(sizeof(cis_shared_data), GFP_KERNEL);
+       if (!cis->cis_data) {
+               err("cis_data is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+       cis->cis_ops = &cis_ops;
+
+       /* belows are depend on sensor cis. MUST check sensor spec */
+       cis->bayer_order = OTF_INPUT_ORDER_BAYER_GR_BG;
+
+       if (of_property_read_bool(dnode, "sensor_f_number")) {
+               ret = of_property_read_u32(dnode, "sensor_f_number", &cis->aperture_num);
+               if (ret) {
+                       warn("f-number read is fail(%d)",ret);
+               }
+       } else {
+               cis->aperture_num = F1_9;
+       }
+
+       probe_info("%s f-number %d\n", __func__, cis->aperture_num);
+
+       cis->use_dgain = true;
+       cis->hdr_ctrl_by_again = false;
+
+       if (use_pdaf == true) {
+               cis->use_pdaf = true;
+       } else {
+               cis->use_pdaf = false;
+       }
+
+       ret = of_property_read_string(dnode, "setfile", &setfile);
+       if (ret) {
+               err("setfile index read fail(%d), take default setfile!!", ret);
+               setfile = "default";
+       }
+
+       if (strcmp(setfile, "default") == 0 ||
+                       strcmp(setfile, "setA") == 0) {
+               probe_info("%s : setfile_A for Non-PDAF\n", __func__);
+               sensor_3p8_global = sensor_3p8_setfile_A_Global;
+               sensor_3p8_global_size = sizeof(sensor_3p8_setfile_A_Global) / sizeof(sensor_3p8_setfile_A_Global[0]);
+               sensor_3p8_setfiles = sensor_3p8_setfiles_A;
+               sensor_3p8_setfile_sizes = sensor_3p8_setfile_A_sizes;
+               sensor_3p8_max_setfile_num = sizeof(sensor_3p8_setfiles_A) / sizeof(sensor_3p8_setfiles_A[0]);
+               sensor_3p8_pllinfos = sensor_3p8_pllinfos_A;
+       } else if (strcmp(setfile, "setB") == 0) {
+               probe_info("%s setfile_B for PDAF\n", __func__);
+               sensor_3p8_pdaf_global = sensor_3p8_setfile_B_Global;
+               sensor_3p8_pdaf_global_size = sizeof(sensor_3p8_setfile_B_Global) / sizeof(sensor_3p8_setfile_B_Global[0]);
+               sensor_3p8_pdaf_setfiles = sensor_3p8_setfiles_B;
+               sensor_3p8_pdaf_setfile_sizes = sensor_3p8_setfile_B_sizes;
+               sensor_3p8_pdaf_max_setfile_num = sizeof(sensor_3p8_setfiles_B) / sizeof(sensor_3p8_setfiles_B[0]);
+               sensor_3p8_pdaf_pllinfos = sensor_3p8_pllinfos_B;
+       } else {
+               err("%s setfile index out of bound, take default (setfile_A)", __func__);
+               sensor_3p8_global = sensor_3p8_setfile_A_Global;
+               sensor_3p8_global_size = sizeof(sensor_3p8_setfile_A_Global) / sizeof(sensor_3p8_setfile_A_Global[0]);
+               sensor_3p8_setfiles = sensor_3p8_setfiles_A;
+               sensor_3p8_setfile_sizes = sensor_3p8_setfile_A_sizes;
+               sensor_3p8_max_setfile_num = sizeof(sensor_3p8_setfiles_A) / sizeof(sensor_3p8_setfiles_A[0]);
+               sensor_3p8_pllinfos = sensor_3p8_pllinfos_A;
+       }
+
+       v4l2_i2c_subdev_init(subdev_cis, client, &subdev_ops);
+       v4l2_set_subdevdata(subdev_cis, cis);
+       v4l2_set_subdev_hostdata(subdev_cis, device);
+       snprintf(subdev_cis->name, V4L2_SUBDEV_NAME_SIZE, "cis-subdev.%d", cis->id);
+
+       probe_info("%s done\n", __func__);
+
+p_err:
+       return ret;
+}
+
+static int cis_3p8_remove(struct i2c_client *client)
+{
+       int ret = 0;
+       return ret;
+}
+
+static const struct of_device_id exynos_fimc_is_cis_3p8_match[] = {
+       {
+               .compatible = "samsung,exynos5-fimc-is-cis-3p8",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_fimc_is_cis_3p8_match);
+
+static const struct i2c_device_id cis_3p8_idt[] = {
+       { SENSOR_NAME, 0 },
+       {},
+};
+
+static struct i2c_driver cis_3p8_driver = {
+       .driver = {
+               .name   = SENSOR_NAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = exynos_fimc_is_cis_3p8_match
+       },
+       .probe  = cis_3p8_probe,
+       .remove = cis_3p8_remove,
+       .id_table = cis_3p8_idt
+};
+module_i2c_driver(cis_3p8_driver);
diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2p6.h
new file mode 100644 (file)
index 0000000..ea97c7d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2016 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_CIS_3P8_H
+#define FIMC_IS_CIS_3P8_H
+
+#include "fimc-is-cis.h"
+
+#define EXT_CLK_Mhz (26)
+
+#define SENSOR_3P8_MAX_WIDTH           (4608 + 16)
+#define SENSOR_3P8_MAX_HEIGHT          (3456 + 10)
+
+/* TODO: Check below values are valid */
+#define SENSOR_3P8_FINE_INTEGRATION_TIME_MIN                0x0618
+#define SENSOR_3P8_FINE_INTEGRATION_TIME_MAX                0x0618
+#define SENSOR_3P8_COARSE_INTEGRATION_TIME_MIN              0x07
+#define SENSOR_3P8_COARSE_INTEGRATION_TIME_MAX_MARGIN       0x08
+
+#define USE_GROUP_PARAM_HOLD   (0)
+
+#endif
+
index 6ac3218f2ddce8d6f3c63496d3451d5aabda11a5..cfc6dc7f60367a46913a0e9fd26e3cfc3db308af 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_CAMERA_CIS_5E3_OBJ) += fimc-is-device-module-5e3.o
 obj-$(CONFIG_CAMERA_CIS_4H5YC_OBJ) += fimc-is-device-module-4h5yc.o
 obj-$(CONFIG_CAMERA_CIS_4H5_OBJ) += fimc-is-device-module-4h5.o
 obj-$(CONFIG_CAMERA_CIS_2P2_OBJ) += fimc-is-device-module-2p2.o
+obj-$(CONFIG_CAMERA_CIS_2P6_OBJ) += fimc-is-device-module-2p6.o
 obj-$(CONFIG_CAMERA_CIS_2P8_OBJ) += fimc-is-device-module-2p8.o
 obj-$(CONFIG_CAMERA_CIS_3P3_OBJ) += fimc-is-device-module-3p3.o
 obj-$(CONFIG_CAMERA_CIS_3L2_OBJ) += fimc-is-device-module-3l2.o
diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2p6.c b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2p6.c
new file mode 100644 (file)
index 0000000..e638000
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+ * Samsung Exynos5 SoC series Sensor driver
+ *
+ *
+ * Copyright (c) 2016 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 <linux/of_gpio.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include <exynos-fimc-is-sensor.h>
+#include "fimc-is-hw.h"
+#include "fimc-is-core.h"
+#include "fimc-is-device-sensor.h"
+#include "fimc-is-device-sensor-peri.h"
+#include "fimc-is-resourcemgr.h"
+#include "fimc-is-dt.h"
+
+#include "fimc-is-device-module-base.h"
+
+#define MAX_2P6_SETPIN_CNT 2
+
+enum sensor_module_2p6_actuator {
+       SENSOR_MODULE_2P6_WITHOUT_ACTUATOR = 0,
+       SENSOR_MODULE_2P6_WITH_ACTUATOR = 1,
+};
+
+enum sensor_module_2p6_position {
+       SENSOR_MODULE_2P6_REAR = 0,
+       SENSOR_MODULE_2P6_FRONT = 1,
+};
+
+static struct fimc_is_sensor_cfg config_module_2p6[] = {
+       /* 4624x3468@30fps */
+       FIMC_IS_SENSOR_CFG_EXT(4624, 3468, 30, 32, 0, CSI_DATA_LANES_4, 0, SET_VC(VC_TAIL_MODE_PDAF, 144, 864), 0, 0),
+       /* 4624x2624@30fps */
+       FIMC_IS_SENSOR_CFG_EXT(4624, 2624, 30, 32, 1, CSI_DATA_LANES_4, 0, SET_VC(VC_TAIL_MODE_PDAF, 144, 640), 0, 0),
+       /* 2312x1734@30fps */
+       FIMC_IS_SENSOR_CFG(2312, 1734, 30, 32, 3, CSI_DATA_LANES_4),
+       /* 2312x1734@15fps */
+       FIMC_IS_SENSOR_CFG(2312, 1734, 15, 32, 4, CSI_DATA_LANES_4),
+       /* 2312x1312@30fps */
+       FIMC_IS_SENSOR_CFG(2312, 1312, 30, 32, 6, CSI_DATA_LANES_4),
+       /* 1156x864@120fps */
+       FIMC_IS_SENSOR_CFG(1156, 864, 120, 32, 7, CSI_DATA_LANES_4),
+       /* 1156x656@120fps */
+       FIMC_IS_SENSOR_CFG(1156, 656, 120, 32, 8, CSI_DATA_LANES_4),
+};
+
+static struct fimc_is_vci vci_module_2p6[] = {
+       {
+               .pixelformat = V4L2_PIX_FMT_SBGGR10,
+               .config = {{0, HW_FORMAT_RAW10}, {1, HW_FORMAT_RAW10}, {2, HW_FORMAT_USER}, {3, 0}}
+       }, {
+               .pixelformat = V4L2_PIX_FMT_SBGGR12,
+               .config = {{0, HW_FORMAT_RAW10}, {1, HW_FORMAT_RAW10}, {2, HW_FORMAT_USER}, {3, 0}}
+       }, {
+               .pixelformat = V4L2_PIX_FMT_SBGGR16,
+               .config = {{0, HW_FORMAT_RAW10}, {1, HW_FORMAT_RAW10}, {2, HW_FORMAT_USER}, {3, 0}}
+       }
+};
+
+static const struct v4l2_subdev_core_ops core_ops = {
+       .init = sensor_module_init,
+       .g_ctrl = sensor_module_g_ctrl,
+       .s_ctrl = sensor_module_s_ctrl,
+       .g_ext_ctrls = sensor_module_g_ext_ctrls,
+       .s_ext_ctrls = sensor_module_s_ext_ctrls,
+       .ioctl = sensor_module_ioctl,
+       .log_status = sensor_module_log_status,
+};
+
+static const struct v4l2_subdev_video_ops video_ops = {
+       .s_stream = sensor_module_s_stream,
+       .s_mbus_fmt = sensor_module_s_format,
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &core_ops,
+       .video = &video_ops,
+};
+
+static int sensor_module_2p6_power_setpin_with_af(struct platform_device *pdev,
+       struct exynos_platform_fimc_is_module *pdata)
+{
+       struct device *dev;
+       struct device_node *dnode;
+       int gpio_reset = 0;
+       int gpio_mclk = 0;
+       int gpio_none = 0;
+       int gpio_core_en = 0;
+       int gpio_cam_avdd_en = 0;
+       int gpio_cam_af_en = 0;
+       int gpio_cam_io_en = 0;
+
+#if defined (CONFIG_OIS_USE)
+       int gpio_ois_reset = 0;
+       int gpio_ois_core_en = 0;
+       int gpio_ois_io_en = 0;
+#endif
+
+       BUG_ON(!pdev);
+
+       dev = &pdev->dev;
+       dnode = dev->of_node;
+
+       dev_info(dev, "%s E v4\n", __func__);
+
+       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_core_en = of_get_named_gpio(dnode, "gpio_core_en", 0);
+       if (!gpio_is_valid(gpio_core_en)) {
+               dev_err(dev, "failed to get gpio_core_en\n");
+       } else {
+               gpio_request_one(gpio_core_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_core_en);
+       }
+
+       gpio_mclk = of_get_named_gpio(dnode, "gpio_mclk", 0);
+       if (!gpio_is_valid(gpio_mclk)) {
+               dev_err(dev, "failed to get gpio_mclk\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_mclk, GPIOF_OUT_INIT_LOW, "CAM_MCLK_OUTPUT_LOW");
+               gpio_free(gpio_mclk);
+       }
+
+       gpio_cam_avdd_en = of_get_named_gpio(dnode, "gpio_cam_avdd_en", 0);
+       if (!gpio_is_valid(gpio_cam_avdd_en)) {
+               dev_err(dev, "failed to get gpio_cam_avdd_en\n");
+       } else {
+               gpio_request_one(gpio_cam_avdd_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_cam_avdd_en);
+       }
+
+       gpio_cam_af_en = of_get_named_gpio(dnode, "gpio_cam_af_en", 0);
+       if (!gpio_is_valid(gpio_cam_af_en)) {
+               dev_err(dev,"failed to get gpio_cam_af_en\n");
+       } else {
+               gpio_request_one(gpio_cam_af_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_cam_af_en);
+       }
+
+       gpio_cam_io_en = of_get_named_gpio(dnode, "gpio_cam_io_en", 0);
+       if (!gpio_is_valid(gpio_cam_io_en)) {
+               dev_err(dev, "failed to get gpio_cam_io_en\n");
+       } else {
+               gpio_request_one(gpio_cam_io_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_cam_io_en);
+       }
+
+#if defined (CONFIG_OIS_USE)
+       gpio_ois_reset = of_get_named_gpio(dnode, "gpio_ois_reset", 0);
+       if (!gpio_is_valid(gpio_ois_reset)) {
+               dev_err(dev, "failed to get gpio_ois_reset\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_ois_reset, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_ois_reset);
+       }
+
+       gpio_ois_core_en = of_get_named_gpio(dnode, "gpio_ois_core_en", 0);
+       if (!gpio_is_valid(gpio_ois_core_en)) {
+               dev_err(dev, "failed to get gpio_ois_core_en\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_ois_core_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_ois_core_en);
+       }
+
+       gpio_ois_io_en = of_get_named_gpio(dnode, "gpio_ois_io_en", 0);
+       if (!gpio_is_valid(gpio_ois_io_en)) {
+               dev_err(dev, "failed to get gpio_ois_io_en\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_ois_io_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_ois_io_en);
+       }
+#endif
+
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON);
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF);
+
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON);
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF);
+
+#if defined (CONFIG_OIS_USE)
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON);
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF);
+#endif
+
+       /* BACK CAMERA - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_reset, "pdaf sen_rst low", PIN_OUTPUT, 0, 0);
+
+       if (gpio_is_valid(gpio_cam_avdd_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_cam_avdd_en, "pdaf gpio_cam_avdd_en", PIN_OUTPUT, 1, 200);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDA_2.8V_CAM", PIN_REGULATOR, 1, 200);
+       }
+
+#if defined (CONFIG_OIS_USE)
+       if (gpio_is_valid(gpio_ois_core_en)) {  /* VDD_OIS_2P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_ois_core_en, "pdaf gpio_ois_core_en", PIN_OUTPUT, 1, 0);
+       }
+       if (gpio_is_valid(gpio_ois_io_en)) {  /* VDD_OIS_IO_1P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_ois_io_en, "pdaf gpio_ois_io_en", PIN_OUTPUT, 1, 2000);
+       }
+#endif
+
+       if (gpio_is_valid(gpio_core_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_core_en, "pdaf gpio_core_en", PIN_OUTPUT, 1, 200);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDD_1.2V_CAM", PIN_REGULATOR, 1, 200);
+       }
+
+       if (gpio_is_valid(gpio_cam_af_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_cam_af_en, "pdaf gpio_cam_af_en", PIN_OUTPUT, 1, 7000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDD_CAM_AF_2P8", PIN_REGULATOR, 1, 7000);
+       }
+
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_cam_io_en, "pdaf gpio_cam_io_en", PIN_OUTPUT, 1, 3000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 1, 3000);
+       }
+
+#if defined (CONFIG_OIS_USE)
+       if (gpio_is_valid(gpio_ois_reset)) {  /* OIS_RESET */
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_ois_reset, "pdaf gpio_ois_reset", PIN_OUTPUT, 1, 0);
+       }
+#endif
+
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_reset, "pdaf sen_rst high", PIN_OUTPUT, 1, 500);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "pin", PIN_FUNCTION, 2, 0);
+
+       /* BACK CAEMRA - POWER OFF */
+       if (gpio_is_valid(gpio_cam_af_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_cam_af_en, "pdaf gpio_cam_af_en", PIN_OUTPUT, 0, 200);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDAF_2.8V_CAM", PIN_REGULATOR, 0, 200);
+       }
+
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "pin", PIN_FUNCTION, 1, 0);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "pin_none", PIN_NONE, 1, 500);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_reset, "pdaf sen_rst", PIN_OUTPUT, 0, 200);
+
+#if defined (CONFIG_OIS_USE)
+       if (gpio_is_valid(gpio_ois_reset)) {  /* OIS_RESET */
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_ois_reset, "pdaf gpio_ois_reset", PIN_OUTPUT, 0, 0);
+       }
+#endif
+
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_cam_io_en, "pdaf gpio_cam_io_en", PIN_OUTPUT, 0, 100);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 0, 100);
+       }
+
+#if defined (CONFIG_OIS_USE)
+       if (gpio_is_valid(gpio_ois_core_en)) {  /* VDD_OIS_2P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_ois_core_en, "pdaf gpio_ois_core_en", PIN_OUTPUT, 0, 0);
+       }
+       if (gpio_is_valid(gpio_ois_io_en)) {  /* VDD_OIS_IO_1P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_ois_io_en, "pdaf gpio_ois_io_en", PIN_OUTPUT, 0, 0);
+       }
+#endif
+
+       if (gpio_is_valid(gpio_core_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_core_en, "pdaf gpio_core_en", PIN_OUTPUT, 0, 100);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDD_1.2V_CAM", PIN_REGULATOR, 0, 100);
+       }
+
+       if (gpio_is_valid(gpio_cam_avdd_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_cam_avdd_en, "pdaf gpio_cam_avdd_en", PIN_OUTPUT, 0, 100);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDA_2.8V_CAM", PIN_REGULATOR, 0, 100);
+       }
+
+       /* READ_ROM - POWER ON */
+#if defined(USE_AF_PWR_READ_EEPROM)
+       if (gpio_is_valid(gpio_cam_af_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_cam_af_en, "pdaf gpio_cam_af_en", PIN_OUTPUT, 1, 2000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_none, "VDD_CAM_AF_2P8", PIN_REGULATOR, 1, 2000);
+       }
+#endif
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_cam_io_en, "pdaf gpio_cam_io_en", PIN_OUTPUT, 1, 2000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 1, 2000);
+       }
+
+#if defined (CONFIG_OIS_USE)
+       if (gpio_is_valid(gpio_ois_core_en)) {  /* VDD_OIS_2P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_ois_core_en, "pdaf gpio_ois_core_en", PIN_OUTPUT, 1, 0);
+       }
+       if (gpio_is_valid(gpio_ois_io_en)) {  /* VDD_OIS_IO_1P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_ois_io_en, "pdaf gpio_ois_io_en", PIN_OUTPUT, 1, 2000);
+       }
+       if (gpio_is_valid(gpio_ois_reset)) {  /* OIS_RESET */
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_ois_reset, "pdaf gpio_ois_reset", PIN_OUTPUT, 1, 2000);
+       }
+#endif
+
+       /* READ_ROM - POWER OFF */
+#if defined(USE_AF_PWR_READ_EEPROM)
+       if (gpio_is_valid(gpio_cam_af_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_cam_af_en, "pdaf gpio_cam_af_en", PIN_OUTPUT, 0, 10);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_none, "VDD_CAM_AF_2P8", PIN_REGULATOR, 0, 10);
+       }
+#endif
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_cam_io_en, "pdaf gpio_cam_io_en", PIN_OUTPUT, 0, 0);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 0, 0);
+       }
+
+#if defined (CONFIG_OIS_USE)
+       if (gpio_is_valid(gpio_ois_reset)) {  /* OIS_RESET */
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_ois_reset, "pdaf gpio_ois_reset", PIN_OUTPUT, 0, 10);
+       }
+       if (gpio_is_valid(gpio_ois_core_en)) {  /* VDD_OIS_2P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_ois_core_en, "pdaf gpio_ois_core_en", PIN_OUTPUT, 0, 0);
+       }
+       if (gpio_is_valid(gpio_ois_io_en)) {  /* VDD_OIS_IO_1P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_ois_io_en, "pdaf gpio_ois_io_en", PIN_OUTPUT, 0, 10);
+       }
+#endif
+
+#if defined(CONFIG_OIS_USE)
+       /* BACK CAMERA - OIS FACTORY ON */
+       if (gpio_is_valid(gpio_ois_core_en)) {  /* VDD_OIS_2P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_ois_core_en, "pdaf gpio_ois_core_en", PIN_OUTPUT, 1, 0);
+       }
+
+       if (gpio_is_valid(gpio_ois_io_en)) {  /* VDD_OIS_IO_1P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_ois_io_en, "pdaf gpio_ois_io_en", PIN_OUTPUT, 1, 2000);
+       }
+
+       if (gpio_is_valid(gpio_cam_af_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_cam_af_en, "pdaf gpio_cam_af_en", PIN_OUTPUT, 1, 2000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_none, "VDD_CAM_AF_2P8", PIN_REGULATOR, 1, 2000);
+       }
+
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_cam_io_en, "pdaf gpio_cam_io_en", PIN_OUTPUT, 1, 2000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 1, 2000);
+       }
+
+       if (gpio_is_valid(gpio_ois_reset)) {  /* OIS_RESET */
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_ON, gpio_ois_reset, "pdaf gpio_ois_reset", PIN_OUTPUT, 1, 2000);
+       }
+
+       /* BACK CAMERA - OIS FACTORY OFF */
+       if (gpio_is_valid(gpio_cam_af_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_cam_af_en, "pdaf gpio_cam_af_en", PIN_OUTPUT, 0, 10);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_none, "VDD_CAM_AF_2P8", PIN_REGULATOR, 0, 10);
+       }
+
+       if (gpio_is_valid(gpio_ois_reset)) {  /* OIS_RESET */
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_ois_reset, "pdaf gpio_ois_reset", PIN_OUTPUT, 0, 10);
+       }
+
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_cam_io_en, "pdaf gpio_cam_io_en", PIN_OUTPUT, 0, 2000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 0, 2000);
+       }
+
+       if (gpio_is_valid(gpio_ois_core_en)) {  /* VDD_OIS_2P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_ois_core_en, "pdaf gpio_ois_core_en", PIN_OUTPUT, 0, 0);
+       }
+       if (gpio_is_valid(gpio_ois_io_en)) {  /* VDD_OIS_IO_1P8 */
+               SET_PIN(pdata, SENSOR_SCENARIO_OIS_FACTORY, GPIO_SCENARIO_OFF, gpio_ois_io_en, "pdaf gpio_ois_io_en", PIN_OUTPUT, 0, 10);
+       }
+#endif
+
+       dev_info(dev, "%s X v4\n", __func__);
+
+       return 0;
+}
+
+static int sensor_module_2p6_power_setpin(struct platform_device *pdev,
+       struct exynos_platform_fimc_is_module *pdata)
+{
+       struct device *dev;
+       struct device_node *dnode;
+       int gpio_reset = 0;
+       int gpio_mclk = 0;
+       int gpio_none = 0;
+       int gpio_core_en = 0;
+       int gpio_cam_avdd_en = 0;
+       int gpio_cam_io_en = 0;
+
+       BUG_ON(!pdev);
+
+       dev = &pdev->dev;
+       dnode = dev->of_node;
+
+       dev_info(dev, "%s E v4\n", __func__);
+
+       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_core_en = of_get_named_gpio(dnode, "gpio_core_en", 0);
+       if (!gpio_is_valid(gpio_core_en)) {
+               dev_err(dev, "failed to get gpio_core_en\n");
+       } else {
+               gpio_request_one(gpio_core_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_core_en);
+       }
+
+       gpio_mclk = of_get_named_gpio(dnode, "gpio_mclk", 0);
+       if (!gpio_is_valid(gpio_mclk)) {
+               dev_err(dev, "failed to get gpio_mclk\n");
+               return -EINVAL;
+       } else {
+               gpio_request_one(gpio_mclk, GPIOF_OUT_INIT_LOW, "CAM_MCLK_OUTPUT_LOW");
+               gpio_free(gpio_mclk);
+       }
+
+       gpio_cam_avdd_en = of_get_named_gpio(dnode, "gpio_cam_avdd_en", 0);
+       if (!gpio_is_valid(gpio_cam_avdd_en)) {
+               dev_err(dev, "failed to get gpio_cam_avdd_en\n");
+       } else {
+               gpio_request_one(gpio_cam_avdd_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_cam_avdd_en);
+       }
+
+       gpio_cam_io_en = of_get_named_gpio(dnode, "gpio_cam_io_en", 0);
+       if (!gpio_is_valid(gpio_cam_io_en)) {
+               dev_err(dev, "failed to get gpio_cam_io_en\n");
+       } else {
+               gpio_request_one(gpio_cam_io_en, GPIOF_OUT_INIT_LOW, "CAM_GPIO_OUTPUT_LOW");
+               gpio_free(gpio_cam_io_en);
+       }
+
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON);
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF);
+
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON);
+       SET_PIN_INIT(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF);
+
+       /* BACK CAMERA - POWER ON */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_reset, "sen_rst low", PIN_OUTPUT, 0, 0);
+
+       if (gpio_is_valid(gpio_cam_avdd_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_cam_avdd_en, "gpio_cam_avdd_en", PIN_OUTPUT, 1, 200);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDA_2.8V_CAM", PIN_REGULATOR, 1, 200);
+       }
+
+       if (gpio_is_valid(gpio_core_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_core_en, "gpio_core_en", PIN_OUTPUT, 1, 200);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDD_1.2V_CAM", PIN_REGULATOR, 1, 200);
+       }
+
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_cam_io_en, "gpio_cam_io_en", PIN_OUTPUT, 1, 1000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 1, 1000);
+       }
+
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_reset, "sen_rst high", PIN_OUTPUT, 1, 500);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "pin", PIN_FUNCTION, 2, 0);
+
+       /* BACK CAEMRA - POWER OFF */
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "pin", PIN_FUNCTION, 1, 0);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "pin_none", PIN_NONE, 1, 500);
+       SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_reset, "sen_rst", PIN_OUTPUT, 0, 200);
+
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_cam_io_en, "gpio_cam_io_en", PIN_OUTPUT, 0, 100);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 0, 100);
+       }
+
+       if (gpio_is_valid(gpio_core_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_core_en, "gpio_core_en", PIN_OUTPUT, 0, 100);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDD_1.2V_CAM", PIN_REGULATOR, 0, 100);
+       }
+
+       if (gpio_is_valid(gpio_cam_avdd_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_cam_avdd_en, "gpio_cam_avdd_en", PIN_OUTPUT, 0, 100);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDA_2.8V_CAM", PIN_REGULATOR, 0, 100);
+       }
+
+       /* READ_ROM - POWER ON */
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_cam_io_en, "gpio_cam_io_en", PIN_OUTPUT, 1, 2000);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 1, 2000);
+       }
+
+       /* READ_ROM - POWER OFF */
+       if (gpio_is_valid(gpio_cam_io_en)) {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_cam_io_en, "gpio_cam_io_en", PIN_OUTPUT, 0, 0);
+       } else {
+               SET_PIN(pdata, SENSOR_SCENARIO_READ_ROM, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM", PIN_REGULATOR, 0, 0);
+       }
+
+       dev_info(dev, "%s X v4\n", __func__);
+
+       return 0;
+}
+
+static int (* module_2p6_power_setpin[MAX_2P6_SETPIN_CNT])(struct platform_device *pdev,
+       struct exynos_platform_fimc_is_module *pdata) = {
+       sensor_module_2p6_power_setpin,
+       sensor_module_2p6_power_setpin_with_af
+};
+
+int sensor_module_2p6_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       bool use_pdaf = false;
+       u8 exist_actuator = 0;
+       int ch;
+       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;
+       struct exynos_platform_fimc_is_module *pdata;
+       struct device *dev;
+       struct device_node *af_np;
+
+       BUG_ON(!fimc_is_dev);
+
+       core = (struct fimc_is_core *)dev_get_drvdata(fimc_is_dev);
+       if (!core) {
+               probe_info("core device is not yet probed");
+               return -EPROBE_DEFER;
+       }
+
+       dev = &pdev->dev;
+
+       if (of_property_read_bool(dev->of_node, "use_pdaf")) {
+               use_pdaf = true;
+       }
+
+       probe_info("%s use_pdaf(%d)\n", __func__, use_pdaf);
+
+       af_np = of_find_node_by_name(dev->of_node, "af");
+       if (!af_np)
+               exist_actuator = SENSOR_MODULE_2P6_WITHOUT_ACTUATOR;
+       else
+               exist_actuator = SENSOR_MODULE_2P6_WITH_ACTUATOR;
+
+       probe_info("%s exist_actuator(%d)\n", __func__, exist_actuator);
+
+       fimc_is_sensor_module_parse_dt(pdev, module_2p6_power_setpin[exist_actuator]);
+
+       pdata = dev_get_platdata(dev);
+       device = &core->sensor[pdata->id];
+
+       subdev_module = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       if (!subdev_module) {
+               probe_err("subdev_module is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+
+       probe_info("%s pdta->id(%d), module_enum id = %d \n", __func__, pdata->id, atomic_read(&device->module_count));
+       module = &device->module_enum[atomic_read(&device->module_count)];
+       atomic_inc(&device->module_count);
+       clear_bit(FIMC_IS_MODULE_GPIO_ON, &module->state);
+       module->pdata = pdata;
+       module->dev = dev;
+       module->sensor_id = SENSOR_NAME_S5K2P6;
+       module->subdev = subdev_module;
+       module->device = pdata->id;
+       module->client = NULL;
+       module->active_width = 4608 + 16;
+       module->active_height = 3456 + 12;
+       module->margin_left = 0;
+       module->margin_right = 0;
+       module->margin_top = 0;
+       module->margin_bottom = 0;
+       module->pixel_width = module->active_width;
+       module->pixel_height = module->active_height;
+       module->max_framerate = 120;
+       module->position = pdata->position;
+       module->mode = CSI_MODE_VC_DT;
+       module->lanes = CSI_DATA_LANES_4;
+       module->bitwidth = 10;
+       module->vcis = ARRAY_SIZE(vci_module_2p6);
+       module->vci = vci_module_2p6;
+       module->sensor_maker = "SLSI";
+       module->sensor_name = "S5K2P6";
+       if (pdata->position == SENSOR_MODULE_2P6_REAR) {
+               module->setfile_name = "setfile_2p6.bin";
+       } else if (pdata->position == SENSOR_MODULE_2P6_FRONT) {
+               module->setfile_name = "setfile_2p6_front.bin";
+       }
+       module->cfgs = ARRAY_SIZE(config_module_2p6);
+       module->cfg = config_module_2p6;
+       module->ops = NULL;
+       for (ch = 1; ch < CSI_VIRTUAL_CH_MAX; ch++)
+               module->internal_vc[ch] = pdata->internal_vc[ch];
+       /* Sensor peri */
+       module->private_data = kzalloc(sizeof(struct fimc_is_device_sensor_peri), GFP_KERNEL);
+       if (!module->private_data) {
+               probe_err("fimc_is_device_sensor_peri is NULL");
+               ret = -ENOMEM;
+               goto p_err;
+       }
+       fimc_is_sensor_peri_probe((struct fimc_is_device_sensor_peri*)module->private_data);
+       PERI_SET_MODULE(module);
+
+       ext = &module->ext;
+       ext->mipi_lane_num = module->lanes;
+       ext->I2CSclk = 0;
+
+       ext->sensor_con.product_name = module->sensor_id;
+       ext->sensor_con.peri_type = SE_I2C;
+       ext->sensor_con.peri_setting.i2c.channel = pdata->sensor_i2c_ch;
+       ext->sensor_con.peri_setting.i2c.slave_address = pdata->sensor_i2c_addr;
+       ext->sensor_con.peri_setting.i2c.speed = 400000;
+
+       if (pdata->af_product_name !=  ACTUATOR_NAME_NOTHING) {
+               ext->actuator_con.product_name = pdata->af_product_name;
+               ext->actuator_con.peri_type = SE_I2C;
+               ext->actuator_con.peri_setting.i2c.channel = pdata->af_i2c_ch;
+               ext->actuator_con.peri_setting.i2c.slave_address = pdata->af_i2c_addr;
+               ext->actuator_con.peri_setting.i2c.speed = 400000;
+       }
+
+       if (pdata->flash_product_name != FLADRV_NAME_NOTHING) {
+               ext->flash_con.product_name = pdata->flash_product_name;
+               ext->flash_con.peri_type = SE_GPIO;
+               ext->flash_con.peri_setting.gpio.first_gpio_port_no = pdata->flash_first_gpio;
+               ext->flash_con.peri_setting.gpio.second_gpio_port_no = pdata->flash_second_gpio;
+       }
+
+       ext->from_con.product_name = FROMDRV_NAME_NOTHING;
+
+       if (pdata->preprocessor_product_name != PREPROCESSOR_NAME_NOTHING) {
+               ext->preprocessor_con.product_name = pdata->preprocessor_product_name;
+               ext->preprocessor_con.peri_info0.valid = true;
+               ext->preprocessor_con.peri_info0.peri_type = SE_SPI;
+               ext->preprocessor_con.peri_info0.peri_setting.spi.channel = pdata->preprocessor_spi_channel;
+               ext->preprocessor_con.peri_info1.valid = true;
+               ext->preprocessor_con.peri_info1.peri_type = SE_I2C;
+               ext->preprocessor_con.peri_info1.peri_setting.i2c.channel = pdata->preprocessor_i2c_ch;
+               ext->preprocessor_con.peri_info1.peri_setting.i2c.slave_address = pdata->preprocessor_i2c_addr;
+               ext->preprocessor_con.peri_info1.peri_setting.i2c.speed = 400000;
+               ext->preprocessor_con.peri_info2.valid = true;
+               ext->preprocessor_con.peri_info2.peri_type = SE_DMA;
+               ext->preprocessor_con.peri_info2.peri_setting.dma.channel = FLITE_ID_D;
+       } else {
+               ext->preprocessor_con.product_name = pdata->preprocessor_product_name;
+       }
+
+       if (pdata->ois_product_name != OIS_NAME_NOTHING) {
+               ext->ois_con.product_name = pdata->ois_product_name;
+               ext->ois_con.peri_type = SE_I2C;
+               ext->ois_con.peri_setting.i2c.channel = pdata->ois_i2c_ch;
+               ext->ois_con.peri_setting.i2c.slave_address = pdata->ois_i2c_addr;
+               ext->ois_con.peri_setting.i2c.speed = 400000;
+       } else {
+               ext->ois_con.product_name = pdata->ois_product_name;
+               ext->ois_con.peri_type = SE_NULL;
+       }
+
+       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->sensor_id);
+
+       probe_info("%s done\n", __func__);
+
+p_err:
+       return ret;
+}
+
+static int sensor_module_2p6_remove(struct platform_device *pdev)
+{
+        int ret = 0;
+
+        info("%s\n", __func__);
+
+        return ret;
+}
+
+static const struct of_device_id exynos_fimc_is_sensor_module_2p6_match[] = {
+       {
+               .compatible = "samsung,sensor-module-2p6",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_fimc_is_sensor_module_2p6_match);
+
+static struct platform_driver sensor_module_2p6_driver = {
+       .probe  = sensor_module_2p6_probe,
+       .remove = sensor_module_2p6_remove,
+       .driver = {
+               .name   = "FIMC-IS-SENSOR-MODULE-2P6",
+               .owner  = THIS_MODULE,
+               .of_match_table = exynos_fimc_is_sensor_module_2p6_match,
+       }
+};
+
+module_platform_driver(sensor_module_2p6_driver);