From 79e12fd4b41b9a7dc3bf8df3420be154c9d75200 Mon Sep 17 00:00:00 2001 From: Eunyoung Lee Date: Mon, 22 Jan 2018 15:38:39 +0900 Subject: [PATCH] [COMMON] fimc-is2: Add S5K2T7SX sensor files Change-Id: Ie3e67a9fd9fb8da0564f6018f91c9068e54d5c78 Signed-off-by: Eunyoung Lee --- .../sensor/module_framework/cis/Kconfig | 8 + .../sensor/module_framework/cis/Makefile | 1 + .../cis/fimc-is-cis-2t7sx-setA.h | 806 ++++++++ .../cis/fimc-is-cis-2t7sx-setB.h | 806 ++++++++ .../module_framework/cis/fimc-is-cis-2t7sx.c | 1825 +++++++++++++++++ .../module_framework/cis/fimc-is-cis-2t7sx.h | 31 + .../sensor/module_framework/modules/Makefile | 1 + .../modules/fimc-is-device-module-2t7sx.c | 356 ++++ 8 files changed, 3834 insertions(+) create mode 100644 drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setA.h create mode 100644 drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setB.h create mode 100644 drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.c create mode 100644 drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.h create mode 100644 drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2t7sx.c diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Kconfig b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Kconfig index 67d570ab92ac..27dc15771c8b 100644 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Kconfig +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Kconfig @@ -171,6 +171,14 @@ config CAMERA_CIS_2P7SQ_OBJ help Use to build 2P7SQ camera sensor. +config CAMERA_CIS_2T7SX_OBJ + bool "Use 2T7SX camera cis" + depends on USE_DIRECT_IS_CONTROL + depends on CAMERA_CIS_SELECT + default n + help + Use to build 2T7SX camera sensor. + config CAMERA_CIS_2L2_OBJ bool "Use 2L2 camera cis" depends on USE_DIRECT_IS_CONTROL diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Makefile b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Makefile index 1a041ea678b9..af7396b7ad01 100644 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Makefile +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_CAMERA_CIS_3P8SP_OBJ) += fimc-is-cis-3p8sp.o obj-$(CONFIG_CAMERA_CIS_2P7SX_OBJ) += fimc-is-cis-2p7sx.o obj-$(CONFIG_CAMERA_CIS_RPB_OBJ) += fimc-is-cis-rpb.o obj-$(CONFIG_CAMERA_CIS_2P7SQ_OBJ) += fimc-is-cis-2p7sq.o +obj-$(CONFIG_CAMERA_CIS_2T7SX_OBJ) += fimc-is-cis-2t7sx.o obj-$(CONFIG_CAMERA_CIS_2L2_OBJ) += fimc-is-cis-2l2.o obj-$(CONFIG_CAMERA_CIS_2L3_OBJ) += fimc-is-cis-2l3.o obj-$(CONFIG_CAMERA_CIS_IMX260_OBJ) += fimc-is-cis-imx260.o diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setA.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setA.h new file mode 100644 index 000000000000..c35a657a554b --- /dev/null +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setA.h @@ -0,0 +1,806 @@ +/* + * 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_2T7SX_SET_A_H +#define FIMC_IS_CIS_2T7SX_SET_A_H + +#include "fimc-is-cis.h" +#include "fimc-is-cis-2t7sx.h" + +const u32 sensor_2t7sx_setfile_A_Global[] = { + 0x6028, 0x4000, 0x02, + 0x6010, 0x0001, 0x02, + I2C_MODE_DELAY, 0x3000, 0x00, + 0x6214, 0x7970, 0x02, + 0x6218, 0x7150, 0x02, + + 0x6028, 0x2000, 0x02, + 0x602A, 0x3FE4, 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, 0x044A, 0x02, + 0x6F12, 0x4860, 0x02, + 0x6F12, 0x101A, 0x02, + 0x6F12, 0x0881, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x2BB9, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x43CE, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x2120, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x9C00, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x2DE9, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0xA648, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x0068, 0x02, + 0x6F12, 0x85B2, 0x02, + 0x6F12, 0x040C, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x69F9, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x6CF9, 0x02, + 0x6F12, 0xA14E, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xA149, 0x02, + 0x6F12, 0x1036, 0x02, + 0x6F12, 0x01EB, 0x02, + 0x6F12, 0x8203, 0x02, + 0x6F12, 0x02F0, 0x02, + 0x6F12, 0x0307, 0x02, + 0x6F12, 0x03F5, 0x02, + 0x6F12, 0xD960, 0x02, + 0x6F12, 0xD3F8, 0x02, + 0x6F12, 0xC836, 0x02, + 0x6F12, 0x36F8, 0x02, + 0x6F12, 0x1770, 0x02, + 0x6F12, 0x521C, 0x02, + 0x6F12, 0x7B43, 0x02, + 0x6F12, 0x03F5, 0x02, + 0x6F12, 0x0063, 0x02, + 0x6F12, 0x1B0B, 0x02, + 0x6F12, 0x0360, 0x02, + 0x6F12, 0x082A, 0x02, + 0x6F12, 0xEDD3, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x4AB9, 0x02, + 0x6F12, 0x10B5, 0x02, + 0x6F12, 0x4FF4, 0x02, + 0x6F12, 0x8041, 0x02, + 0x6F12, 0x0F20, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x4EF9, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x1040, 0x02, + 0x6F12, 0x0121, 0x02, + 0x6F12, 0x4FF2, 0x02, + 0x6F12, 0xA040, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x3CB9, 0x02, + 0x6F12, 0x10B5, 0x02, + 0x6F12, 0x0446, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x47F9, 0x02, + 0x6F12, 0x8A49, 0x02, + 0x6F12, 0x91F8, 0x02, + 0x6F12, 0x4423, 0x02, + 0x6F12, 0x012A, 0x02, + 0x6F12, 0x05D1, 0x02, + 0x6F12, 0x94F8, 0x02, + 0x6F12, 0xA500, 0x02, + 0x6F12, 0x10B1, 0x02, + 0x6F12, 0x874A, 0x02, + 0x6F12, 0x0120, 0x02, + 0x6F12, 0x1080, 0x02, + 0x6F12, 0x8448, 0x02, + 0x6F12, 0x91F8, 0x02, + 0x6F12, 0xBE11, 0x02, + 0x6F12, 0x1030, 0x02, + 0x6F12, 0x007A, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x40EA, 0x02, + 0x6F12, 0x4120, 0x02, + 0x6F12, 0x8349, 0x02, + 0x6F12, 0x0880, 0x02, + 0x6F12, 0x8349, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x5510, 0x02, + 0x6F12, 0x8880, 0x02, + 0x6F12, 0x43F6, 0x02, + 0x6F12, 0xFF73, 0x02, + 0x6F12, 0x0422, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x5F01, 0x02, + 0x6F12, 0x0F20, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x2BF9, 0x02, + 0x6F12, 0x7A48, 0x02, + 0x6F12, 0xB0F8, 0x02, + 0x6F12, 0xE214, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x1040, 0x02, + 0x6F12, 0x4FF2, 0x02, + 0x6F12, 0x1400, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x27B9, 0x02, + 0x6F12, 0x7948, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x7610, 0x02, + 0x6F12, 0x7948, 0x02, + 0x6F12, 0x0229, 0x02, + 0x6F12, 0x04D1, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x9C10, 0x02, + 0x6F12, 0x09B1, 0x02, + 0x6F12, 0x0120, 0x02, + 0x6F12, 0x7047, 0x02, + 0x6F12, 0x0168, 0x02, + 0x6F12, 0xC0F8, 0x02, + 0x6F12, 0xD410, 0x02, + 0x6F12, 0x0020, 0x02, + 0x6F12, 0x7047, 0x02, + 0x6F12, 0x70B5, 0x02, + 0x6F12, 0x0446, 0x02, + 0x6F12, 0x6B48, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x4168, 0x02, + 0x6F12, 0x0D0C, 0x02, + 0x6F12, 0x8EB2, 0x02, + 0x6F12, 0x3146, 0x02, + 0x6F12, 0x2846, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xF3F8, 0x02, + 0x6F12, 0x6007, 0x02, + 0x6F12, 0x05D5, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x1146, 0x02, + 0x6F12, 0x4FF2, 0x02, + 0x6F12, 0xA040, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xEBF8, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x06F9, 0x02, + 0x6F12, 0x3146, 0x02, + 0x6F12, 0x2846, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x7040, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xE1B8, 0x02, + 0x6F12, 0x70B5, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x01F9, 0x02, + 0x6F12, 0xE0B3, 0x02, + 0x6F12, 0x49F2, 0x02, + 0x6F12, 0x3430, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x01F9, 0x02, + 0x6F12, 0x6149, 0x02, + 0x6F12, 0x0A88, 0x02, + 0x6F12, 0x614D, 0x02, + 0x6F12, 0xB0FB, 0x02, + 0x6F12, 0xF2F0, 0x02, + 0x6F12, 0xB5F8, 0x02, + 0x6F12, 0x4A10, 0x02, + 0x6F12, 0x401A, 0x02, + 0x6F12, 0x0021, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xFBF8, 0x02, + 0x6F12, 0x5D4C, 0x02, + 0x6F12, 0x5A4E, 0x02, + 0x6F12, 0x00B2, 0x02, + 0x6F12, 0xA081, 0x02, + 0x6F12, 0xF17A, 0x02, + 0x6F12, 0x11F0, 0x02, + 0x6F12, 0x060F, 0x02, + 0x6F12, 0x0DD0, 0x02, + 0x6F12, 0x0020, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xF5F8, 0x02, + 0x6F12, 0xF07A, 0x02, + 0x6F12, 0x5C35, 0x02, + 0x6F12, 0xC0F3, 0x02, + 0x6F12, 0x4003, 0x02, + 0x6F12, 0x6A78, 0x02, + 0x6F12, 0x2978, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0C00, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xF0F8, 0x02, + 0x6F12, 0x07E0, 0x02, + 0x6F12, 0x4949, 0x02, + 0x6F12, 0x1031, 0x02, + 0x6F12, 0x4A89, 0x02, + 0x6F12, 0x8989, 0x02, + 0x6F12, 0x5043, 0x02, + 0x6F12, 0x01EB, 0x02, + 0x6F12, 0x2030, 0x02, + 0x6F12, 0xA081, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0800, 0x02, + 0x6F12, 0x0028, 0x02, + 0x6F12, 0x0AD0, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0C20, 0x02, + 0x6F12, 0x6168, 0x02, + 0x6F12, 0xC1EB, 0x02, + 0x6F12, 0x0221, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0A20, 0x02, + 0x6F12, 0x5143, 0x02, + 0x6F12, 0x91FB, 0x02, + 0x6F12, 0xF0F0, 0x02, + 0x6F12, 0x2080, 0x02, + 0x6F12, 0x70BD, 0x02, + 0x6F12, 0xFFE7, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x7040, 0x02, + 0x6F12, 0x0021, 0x02, + 0x6F12, 0x3820, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xD5B8, 0x02, + 0x6F12, 0x2DE9, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0x3948, 0x02, + 0x6F12, 0x1E46, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xC068, 0x02, + 0x6F12, 0x85B2, 0x02, + 0x6F12, 0x040C, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x8DF8, 0x02, + 0x6F12, 0x3E4A, 0x02, + 0x6F12, 0x3346, 0x02, + 0x6F12, 0xA2F5, 0x02, + 0x6F12, 0x0C71, 0x02, + 0x6F12, 0x01F5, 0x02, + 0x6F12, 0x6B70, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xC6F8, 0x02, + 0x6F12, 0x3148, 0x02, + 0x6F12, 0x2F4E, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x3D03, 0x02, + 0x6F12, 0x1036, 0x02, + 0x6F12, 0x0428, 0x02, + 0x6F12, 0x02D0, 0x02, + 0x6F12, 0x3749, 0x02, + 0x6F12, 0x708D, 0x02, + 0x6F12, 0x8881, 0x02, + 0x6F12, 0x2C48, 0x02, + 0x6F12, 0xF189, 0x02, + 0x6F12, 0xB0F8, 0x02, + 0x6F12, 0x0806, 0x02, + 0x6F12, 0xC008, 0x02, + 0x6F12, 0x8142, 0x02, + 0x6F12, 0x01D3, 0x02, + 0x6F12, 0x0020, 0x02, + 0x6F12, 0x03E0, 0x02, + 0x6F12, 0x318A, 0x02, + 0x6F12, 0x8142, 0x02, + 0x6F12, 0x01D8, 0x02, + 0x6F12, 0x0220, 0x02, + 0x6F12, 0xB085, 0x02, + 0x6F12, 0xB08D, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x1227, 0x02, + 0x6F12, 0x8119, 0x02, + 0x6F12, 0x08E0, 0x02, + 0x6F12, 0x07EB, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x03F1, 0x02, + 0x6F12, 0x8043, 0x02, + 0x6F12, 0x085A, 0x02, + 0x6F12, 0x1880, 0x02, + 0x6F12, 0x521C, 0x02, + 0x6F12, 0x042A, 0x02, + 0x6F12, 0x06D2, 0x02, + 0x6F12, 0x02EB, 0x02, + 0x6F12, 0x4200, 0x02, + 0x6F12, 0x06EB, 0x02, + 0x6F12, 0x4003, 0x02, + 0x6F12, 0xDB8A, 0x02, + 0x6F12, 0x002B, 0x02, + 0x6F12, 0xEFD1, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x51B8, 0x02, + 0x6F12, 0x10B5, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x4B21, 0x02, + 0x6F12, 0x2048, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x124C, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0xE711, 0x02, + 0x6F12, 0x2060, 0x02, + 0x6F12, 0x1D48, 0x02, + 0x6F12, 0x8164, 0x02, + 0x6F12, 0x0021, 0x02, + 0x6F12, 0x4163, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x9B11, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x0163, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x8311, 0x02, + 0x6F12, 0x1948, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x7FF8, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x5511, 0x02, + 0x6F12, 0x6060, 0x02, + 0x6F12, 0x1748, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x78F8, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0xD101, 0x02, + 0x6F12, 0xA060, 0x02, + 0x6F12, 0x1448, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x71F8, 0x02, + 0x6F12, 0x1449, 0x02, + 0x6F12, 0xE060, 0x02, + 0x6F12, 0x4FF6, 0x02, + 0x6F12, 0xA330, 0x02, + 0x6F12, 0x0968, 0x02, + 0x6F12, 0x4883, 0x02, + 0x6F12, 0x10BD, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x4390, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x2240, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0xF410, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0xF192, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x9000, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x0900, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x2120, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x9338, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x1880, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x3280, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x25E8, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0xB000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x303B, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x08B0, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x4F0B, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x9D6F, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x57FD, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x0510, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0xAF2C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x43F2, 0x02, + 0x6F12, 0x3B0C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x3B4C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x45F6, 0x02, + 0x6F12, 0x8D7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0xA54C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0xD12C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x44F6, 0x02, + 0x6F12, 0x0B7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x0F7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0xC32C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0x0D2C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x45F6, 0x02, + 0x6F12, 0x5D3C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x41F2, 0x02, + 0x6F12, 0x370C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x9F3C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x45F2, 0x02, + 0x6F12, 0xFD7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0xE51C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x0000, 0x02, + + 0x6028, 0x2000, 0x02, + 0x602A, 0x130C, 0x02, + 0x6F12, 0x0001, 0x02, + 0x602A, 0x13BA, 0x02, + 0x6F12, 0x0C48, 0x02, + 0x602A, 0x1390, 0x02, + 0x6F12, 0x0015, 0x02, + 0x602A, 0x139E, 0x02, + 0x6F12, 0x0050, 0x02, + 0x602A, 0x139C, 0x02, + 0x6F12, 0x02AF, 0x02, + 0x602A, 0x139A, 0x02, + 0x6F12, 0x7086, 0x02, + 0x602A, 0x13A2, 0x02, + 0x6F12, 0x0430, 0x02, + 0x602A, 0x13BC, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x12AA, 0x02, + 0x6F12, 0x0300, 0x02, + 0x6F12, 0x0307, 0x02, + 0x602A, 0x0A18, 0x02, + 0x6F12, 0x0440, 0x02, + 0x602A, 0x0A28, 0x02, + 0x6F12, 0x0007, 0x02, + 0x602A, 0x0A58, 0x02, + 0x6F12, 0x0008, 0x02, + 0x602A, 0x0A78, 0x02, + 0x6F12, 0x00E8, 0x02, + 0x602A, 0x0A80, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x0A88, 0x02, + 0x6F12, 0x00E6, 0x02, + 0x602A, 0x0A90, 0x02, + 0x6F12, 0x0116, 0x02, + 0x602A, 0x0A98, 0x02, + 0x6F12, 0x011D, 0x02, + 0x602A, 0x0AA0, 0x02, + 0x6F12, 0x00F7, 0x02, + 0x602A, 0x0AB8, 0x02, + 0x6F12, 0x0116, 0x02, + 0x602A, 0x0AC0, 0x02, + 0x6F12, 0x00FE, 0x02, + 0x602A, 0x0AF0, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0AF8, 0x02, + 0x6F12, 0x02B5, 0x02, + 0x602A, 0x0B00, 0x02, + 0x6F12, 0x00E8, 0x02, + 0x602A, 0x0B08, 0x02, + 0x6F12, 0x02B3, 0x02, + 0x602A, 0x0B20, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0B28, 0x02, + 0x6F12, 0x0126, 0x02, + 0x602A, 0x0B80, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0B88, 0x02, + 0x6F12, 0x0011, 0x02, + 0x602A, 0x0B90, 0x02, + 0x6F12, 0x0015, 0x02, + 0x602A, 0x0B98, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x0BA0, 0x02, + 0x6F12, 0x012A, 0x02, + 0x602A, 0x0BB8, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x0BC0, 0x02, + 0x6F12, 0x0118, 0x02, + 0x602A, 0x0BF0, 0x02, + 0x6F12, 0x02B1, 0x02, + 0x602A, 0x0C80, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0C88, 0x02, + 0x6F12, 0x0184, 0x02, + 0x602A, 0x0C90, 0x02, + 0x6F12, 0x02B1, 0x02, + 0x602A, 0x0C98, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0CA0, 0x02, + 0x6F12, 0x0104, 0x02, + 0x602A, 0x0CA8, 0x02, + 0x6F12, 0x00F4, 0x02, + 0x602A, 0x0CB0, 0x02, + 0x6F12, 0x010C, 0x02, + 0x602A, 0x0CB8, 0x02, + 0x6F12, 0x00FC, 0x02, + 0x602A, 0x0CC0, 0x02, + 0x6F12, 0x010C, 0x02, + 0x602A, 0x0CC8, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0CD0, 0x02, + 0x6F12, 0x00EF, 0x02, + 0x602A, 0x0CE8, 0x02, + 0x6F12, 0x00F4, 0x02, + 0x602A, 0x0CF0, 0x02, + 0x6F12, 0x010C, 0x02, + 0x602A, 0x0D08, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0D10, 0x02, + 0x6F12, 0x00EF, 0x02, + 0x602A, 0x0D20, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x602A, 0x0D28, 0x02, + 0x6F12, 0x0182, 0x02, + 0x602A, 0x0D30, 0x02, + 0x6F12, 0x02B3, 0x02, + 0x602A, 0x0D58, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0D60, 0x02, + 0x6F12, 0x0107, 0x02, + 0x602A, 0x0D78, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0D80, 0x02, + 0x6F12, 0x00EF, 0x02, + 0x602A, 0x0DA0, 0x02, + 0x6F12, 0x02B7, 0x02, + 0x602A, 0x0DB8, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x602A, 0x0DC0, 0x02, + 0x6F12, 0x00EA, 0x02, + 0x602A, 0x0DC8, 0x02, + 0x6F12, 0x02B3, 0x02, + 0x602A, 0x0DD0, 0x02, + 0x6F12, 0x02B6, 0x02, + 0x602A, 0x0DD8, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x602A, 0x0DE8, 0x02, + 0x6F12, 0x00F1, 0x02, + 0x602A, 0x0DF0, 0x02, + 0x6F12, 0x0012, 0x02, + 0x602A, 0x0F00, 0x02, + 0x6F12, 0x0001, 0x02, + 0x602A, 0x09BE, 0x02, + 0x6F12, 0x0080, 0x02, + 0x602A, 0x1382, 0x02, + 0x6F12, 0x3CFC, 0x02, + 0x602A, 0x1E80, 0x02, + 0x6F12, 0x0100, 0x02, + 0x6F12, 0x003F, 0x02, + 0x6F12, 0x003F, 0x02, + 0x6F12, 0x0004, 0x02, + 0x6F12, 0x0006, 0x02, + 0x6F12, 0xF48E, 0x02, + 0x6F12, 0x0004, 0x02, + 0x6F12, 0x0006, 0x02, + 0x6F12, 0xF490, 0x02, + 0x6F12, 0x0005, 0x02, + 0x6F12, 0x0004, 0x02, + 0x6F12, 0xF488, 0x02, + 0x602A, 0x43AE, 0x02, + 0x6F12, 0x0170, 0x02, + 0x6F12, 0x017F, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x6F12, 0x02B2, 0x02, + 0x6F12, 0xF5E8, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x0220, 0x0000, 0x02, + 0x6028, 0x2000, 0x02, + 0x602A, 0x0990, 0x02, + 0x6F12, 0x0001, 0x02, + 0x602A, 0x1C7E, 0x02, + 0x6F12, 0x001A, 0x02, + 0x0B04, 0x0101, 0x02, + 0x6028, 0x2000, 0x02, + 0x602A, 0x1E5C, 0x02, + 0x6F12, 0x0100, 0x02, + 0x302A, 0x0CA0, 0x02, + 0x300E, 0x0100, 0x02, + 0x0138, 0x0100, 0x02, + 0x6028, 0x2000, 0x02, + 0x602A, 0x18DE, 0x02, + 0x6F12, 0x0F28, 0x02, + 0x602A, 0x1952, 0x02, + 0x6F12, 0x000A, 0x02, + 0x602A, 0x43A0, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x0410, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x602A, 0x18DA, 0x02, + 0x6F12, 0x2850, 0x02, + 0x602A, 0x1A74, 0x02, + 0x6F12, 0x0100, 0x02, +}; + +/* + * [Mode Information] + * 0: [MCLK:26,Width:5184,Height:3880,Format:MIPI_RAW10,mipi_lane:4,mipi_datarate:1500,pvi_pclk_inverse:0] + */ + +const u32 sensor_2t7sx_setfile_A_5184x3880_30fps[] = { + 0x6028, 0x2000, 0x02, + 0x0344, 0x0008, 0x02, + 0x0346, 0x0008, 0x02, + 0x0348, 0x1447, 0x02, + 0x034A, 0x0F2F, 0x02, + 0x034C, 0x1440, 0x02, + 0x034E, 0x0F28, 0x02, + 0x0408, 0x0000, 0x02, + 0x040A, 0x0000, 0x02, + 0x0900, 0x0011, 0x02, + 0x0380, 0x0001, 0x02, + 0x0382, 0x0001, 0x02, + 0x0384, 0x0001, 0x02, + 0x0386, 0x0001, 0x02, + 0x0400, 0x0000, 0x02, + 0x0404, 0x0010, 0x02, + 0x301E, 0x0110, 0x02, + 0x0110, 0x0002, 0x02, + 0x0114, 0x0300, 0x02, + 0x0136, 0x1A00, 0x02, + 0x0300, 0x0005, 0x02, + 0x0302, 0x0001, 0x02, + 0x0304, 0x0006, 0x02, + 0x0306, 0x00C3, 0x02, + 0x0308, 0x0008, 0x02, + 0x030A, 0x0001, 0x02, + 0x030C, 0x0004, 0x02, + 0x030E, 0x0082, 0x02, + 0x0310, 0x0100, 0x02, + 0x0312, 0x0000, 0x02, + 0x0340, 0x0FA8, 0x02, + 0x0342, 0x1608, 0x02, + 0x602A, 0x1C78, 0x02, + 0x6F12, 0x8100, 0x02, + 0x602A, 0x43CA, 0x02, + 0x6F12, 0x0020, 0x02, + 0x602A, 0x13E4, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6226, 0x0001, 0x02, + 0x9400, 0x0001, 0x02, + 0x9402, 0x0028, 0x02, + 0x9404, 0x000A, 0x02, + 0x9406, 0x0000, 0x02, + 0x9408, 0x0000, 0x02, + 0x940A, 0x0000, 0x02, + 0x940C, 0x0000, 0x02, + 0x940E, 0x1400, 0x02, + 0x9410, 0x0780, 0x02, + 0x9412, 0x0000, 0x02, + 0x9414, 0x0000, 0x02, + 0x9416, 0x0000, 0x02, + 0x9418, 0x0001, 0x02, + 0x941A, 0x0082, 0x02, + 0x941C, 0x0186, 0x02, + 0x941E, 0x0082, 0x02, + 0x9420, 0x0186, 0x02, + 0x9422, 0x0141, 0x02, + 0x9424, 0x0141, 0x02, + 0x9426, 0x0141, 0x02, + 0x9428, 0x0141, 0x02, + 0x942A, 0x0008, 0x02, + 0x942C, 0x0008, 0x02, + 0x942E, 0x0004, 0x02, + 0x9430, 0x0004, 0x02, + 0x9432, 0x5500, 0x02, + 0x9434, 0x5500, 0x02, + 0x6226, 0x0000, 0x02, + 0x602A, 0x1E76, 0x02, + 0x6F12, 0x0100, 0x02, + 0x6F12, 0x0000, 0x02, +}; + +const struct sensor_pll_info_compact sensor_2t7sx_pllinfo_A_5184x3880_30fps = { + EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */ + 1690000000, /* mipi_datarate */ + 676000000, /* pclk = VT pix CLK (this value is different by cis) */ + 0x0FA8, /* frame_length_lines (0x0340) */ + 0x1608, /* line_length_pck (0x0342) */ +}; + +static const u32 *sensor_2t7sx_setfiles_A[] = { + sensor_2t7sx_setfile_A_5184x3880_30fps, +}; + +static const u32 sensor_2t7sx_setfile_A_sizes[] = { + ARRAY_SIZE(sensor_2t7sx_setfile_A_5184x3880_30fps), +}; + +static const struct sensor_pll_info_compact *sensor_2t7sx_pllinfos_A[] = { + &sensor_2t7sx_pllinfo_A_5184x3880_30fps, +}; +#endif diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setB.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setB.h new file mode 100644 index 000000000000..a504c3e65c42 --- /dev/null +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx-setB.h @@ -0,0 +1,806 @@ +/* + * 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_2T7SX_SET_B_H +#define FIMC_IS_CIS_2T7SX_SET_B_H + +#include "fimc-is-cis.h" +#include "fimc-is-cis-2t7sx.h" + +const u32 sensor_2t7sx_setfile_B_Global[] = { + 0x6028, 0x4000, 0x02, + 0x6010, 0x0001, 0x02, + I2C_MODE_DELAY, 0x3000, 0x00, + 0x6214, 0x7970, 0x02, + 0x6218, 0x7150, 0x02, + + 0x6028, 0x2000, 0x02, + 0x602A, 0x3FE4, 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, 0x044A, 0x02, + 0x6F12, 0x4860, 0x02, + 0x6F12, 0x101A, 0x02, + 0x6F12, 0x0881, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x2BB9, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x43CE, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x2120, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x9C00, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x2DE9, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0xA648, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x0068, 0x02, + 0x6F12, 0x85B2, 0x02, + 0x6F12, 0x040C, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x69F9, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x6CF9, 0x02, + 0x6F12, 0xA14E, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xA149, 0x02, + 0x6F12, 0x1036, 0x02, + 0x6F12, 0x01EB, 0x02, + 0x6F12, 0x8203, 0x02, + 0x6F12, 0x02F0, 0x02, + 0x6F12, 0x0307, 0x02, + 0x6F12, 0x03F5, 0x02, + 0x6F12, 0xD960, 0x02, + 0x6F12, 0xD3F8, 0x02, + 0x6F12, 0xC836, 0x02, + 0x6F12, 0x36F8, 0x02, + 0x6F12, 0x1770, 0x02, + 0x6F12, 0x521C, 0x02, + 0x6F12, 0x7B43, 0x02, + 0x6F12, 0x03F5, 0x02, + 0x6F12, 0x0063, 0x02, + 0x6F12, 0x1B0B, 0x02, + 0x6F12, 0x0360, 0x02, + 0x6F12, 0x082A, 0x02, + 0x6F12, 0xEDD3, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x4AB9, 0x02, + 0x6F12, 0x10B5, 0x02, + 0x6F12, 0x4FF4, 0x02, + 0x6F12, 0x8041, 0x02, + 0x6F12, 0x0F20, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x4EF9, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x1040, 0x02, + 0x6F12, 0x0121, 0x02, + 0x6F12, 0x4FF2, 0x02, + 0x6F12, 0xA040, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x3CB9, 0x02, + 0x6F12, 0x10B5, 0x02, + 0x6F12, 0x0446, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x47F9, 0x02, + 0x6F12, 0x8A49, 0x02, + 0x6F12, 0x91F8, 0x02, + 0x6F12, 0x4423, 0x02, + 0x6F12, 0x012A, 0x02, + 0x6F12, 0x05D1, 0x02, + 0x6F12, 0x94F8, 0x02, + 0x6F12, 0xA500, 0x02, + 0x6F12, 0x10B1, 0x02, + 0x6F12, 0x874A, 0x02, + 0x6F12, 0x0120, 0x02, + 0x6F12, 0x1080, 0x02, + 0x6F12, 0x8448, 0x02, + 0x6F12, 0x91F8, 0x02, + 0x6F12, 0xBE11, 0x02, + 0x6F12, 0x1030, 0x02, + 0x6F12, 0x007A, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x40EA, 0x02, + 0x6F12, 0x4120, 0x02, + 0x6F12, 0x8349, 0x02, + 0x6F12, 0x0880, 0x02, + 0x6F12, 0x8349, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x5510, 0x02, + 0x6F12, 0x8880, 0x02, + 0x6F12, 0x43F6, 0x02, + 0x6F12, 0xFF73, 0x02, + 0x6F12, 0x0422, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x5F01, 0x02, + 0x6F12, 0x0F20, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x2BF9, 0x02, + 0x6F12, 0x7A48, 0x02, + 0x6F12, 0xB0F8, 0x02, + 0x6F12, 0xE214, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x1040, 0x02, + 0x6F12, 0x4FF2, 0x02, + 0x6F12, 0x1400, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x27B9, 0x02, + 0x6F12, 0x7948, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x7610, 0x02, + 0x6F12, 0x7948, 0x02, + 0x6F12, 0x0229, 0x02, + 0x6F12, 0x04D1, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x9C10, 0x02, + 0x6F12, 0x09B1, 0x02, + 0x6F12, 0x0120, 0x02, + 0x6F12, 0x7047, 0x02, + 0x6F12, 0x0168, 0x02, + 0x6F12, 0xC0F8, 0x02, + 0x6F12, 0xD410, 0x02, + 0x6F12, 0x0020, 0x02, + 0x6F12, 0x7047, 0x02, + 0x6F12, 0x70B5, 0x02, + 0x6F12, 0x0446, 0x02, + 0x6F12, 0x6B48, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x4168, 0x02, + 0x6F12, 0x0D0C, 0x02, + 0x6F12, 0x8EB2, 0x02, + 0x6F12, 0x3146, 0x02, + 0x6F12, 0x2846, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xF3F8, 0x02, + 0x6F12, 0x6007, 0x02, + 0x6F12, 0x05D5, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x1146, 0x02, + 0x6F12, 0x4FF2, 0x02, + 0x6F12, 0xA040, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xEBF8, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x06F9, 0x02, + 0x6F12, 0x3146, 0x02, + 0x6F12, 0x2846, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x7040, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xE1B8, 0x02, + 0x6F12, 0x70B5, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x01F9, 0x02, + 0x6F12, 0xE0B3, 0x02, + 0x6F12, 0x49F2, 0x02, + 0x6F12, 0x3430, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x01F9, 0x02, + 0x6F12, 0x6149, 0x02, + 0x6F12, 0x0A88, 0x02, + 0x6F12, 0x614D, 0x02, + 0x6F12, 0xB0FB, 0x02, + 0x6F12, 0xF2F0, 0x02, + 0x6F12, 0xB5F8, 0x02, + 0x6F12, 0x4A10, 0x02, + 0x6F12, 0x401A, 0x02, + 0x6F12, 0x0021, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xFBF8, 0x02, + 0x6F12, 0x5D4C, 0x02, + 0x6F12, 0x5A4E, 0x02, + 0x6F12, 0x00B2, 0x02, + 0x6F12, 0xA081, 0x02, + 0x6F12, 0xF17A, 0x02, + 0x6F12, 0x11F0, 0x02, + 0x6F12, 0x060F, 0x02, + 0x6F12, 0x0DD0, 0x02, + 0x6F12, 0x0020, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xF5F8, 0x02, + 0x6F12, 0xF07A, 0x02, + 0x6F12, 0x5C35, 0x02, + 0x6F12, 0xC0F3, 0x02, + 0x6F12, 0x4003, 0x02, + 0x6F12, 0x6A78, 0x02, + 0x6F12, 0x2978, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0C00, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xF0F8, 0x02, + 0x6F12, 0x07E0, 0x02, + 0x6F12, 0x4949, 0x02, + 0x6F12, 0x1031, 0x02, + 0x6F12, 0x4A89, 0x02, + 0x6F12, 0x8989, 0x02, + 0x6F12, 0x5043, 0x02, + 0x6F12, 0x01EB, 0x02, + 0x6F12, 0x2030, 0x02, + 0x6F12, 0xA081, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0800, 0x02, + 0x6F12, 0x0028, 0x02, + 0x6F12, 0x0AD0, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0C20, 0x02, + 0x6F12, 0x6168, 0x02, + 0x6F12, 0xC1EB, 0x02, + 0x6F12, 0x0221, 0x02, + 0x6F12, 0xB4F9, 0x02, + 0x6F12, 0x0A20, 0x02, + 0x6F12, 0x5143, 0x02, + 0x6F12, 0x91FB, 0x02, + 0x6F12, 0xF0F0, 0x02, + 0x6F12, 0x2080, 0x02, + 0x6F12, 0x70BD, 0x02, + 0x6F12, 0xFFE7, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0x7040, 0x02, + 0x6F12, 0x0021, 0x02, + 0x6F12, 0x3820, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xD5B8, 0x02, + 0x6F12, 0x2DE9, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0x3948, 0x02, + 0x6F12, 0x1E46, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xC068, 0x02, + 0x6F12, 0x85B2, 0x02, + 0x6F12, 0x040C, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x8DF8, 0x02, + 0x6F12, 0x3E4A, 0x02, + 0x6F12, 0x3346, 0x02, + 0x6F12, 0xA2F5, 0x02, + 0x6F12, 0x0C71, 0x02, + 0x6F12, 0x01F5, 0x02, + 0x6F12, 0x6B70, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0xC6F8, 0x02, + 0x6F12, 0x3148, 0x02, + 0x6F12, 0x2F4E, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x3D03, 0x02, + 0x6F12, 0x1036, 0x02, + 0x6F12, 0x0428, 0x02, + 0x6F12, 0x02D0, 0x02, + 0x6F12, 0x3749, 0x02, + 0x6F12, 0x708D, 0x02, + 0x6F12, 0x8881, 0x02, + 0x6F12, 0x2C48, 0x02, + 0x6F12, 0xF189, 0x02, + 0x6F12, 0xB0F8, 0x02, + 0x6F12, 0x0806, 0x02, + 0x6F12, 0xC008, 0x02, + 0x6F12, 0x8142, 0x02, + 0x6F12, 0x01D3, 0x02, + 0x6F12, 0x0020, 0x02, + 0x6F12, 0x03E0, 0x02, + 0x6F12, 0x318A, 0x02, + 0x6F12, 0x8142, 0x02, + 0x6F12, 0x01D8, 0x02, + 0x6F12, 0x0220, 0x02, + 0x6F12, 0xB085, 0x02, + 0x6F12, 0xB08D, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x1227, 0x02, + 0x6F12, 0x8119, 0x02, + 0x6F12, 0x08E0, 0x02, + 0x6F12, 0x07EB, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x03F1, 0x02, + 0x6F12, 0x8043, 0x02, + 0x6F12, 0x085A, 0x02, + 0x6F12, 0x1880, 0x02, + 0x6F12, 0x521C, 0x02, + 0x6F12, 0x042A, 0x02, + 0x6F12, 0x06D2, 0x02, + 0x6F12, 0x02EB, 0x02, + 0x6F12, 0x4200, 0x02, + 0x6F12, 0x06EB, 0x02, + 0x6F12, 0x4003, 0x02, + 0x6F12, 0xDB8A, 0x02, + 0x6F12, 0x002B, 0x02, + 0x6F12, 0xEFD1, 0x02, + 0x6F12, 0x2946, 0x02, + 0x6F12, 0x2046, 0x02, + 0x6F12, 0xBDE8, 0x02, + 0x6F12, 0xF041, 0x02, + 0x6F12, 0x0122, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x51B8, 0x02, + 0x6F12, 0x10B5, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x4B21, 0x02, + 0x6F12, 0x2048, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x90F8, 0x02, + 0x6F12, 0x124C, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0xE711, 0x02, + 0x6F12, 0x2060, 0x02, + 0x6F12, 0x1D48, 0x02, + 0x6F12, 0x8164, 0x02, + 0x6F12, 0x0021, 0x02, + 0x6F12, 0x4163, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x9B11, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0x0163, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x8311, 0x02, + 0x6F12, 0x1948, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x7FF8, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0x5511, 0x02, + 0x6F12, 0x6060, 0x02, + 0x6F12, 0x1748, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x78F8, 0x02, + 0x6F12, 0x0022, 0x02, + 0x6F12, 0xAFF2, 0x02, + 0x6F12, 0xD101, 0x02, + 0x6F12, 0xA060, 0x02, + 0x6F12, 0x1448, 0x02, + 0x6F12, 0x00F0, 0x02, + 0x6F12, 0x71F8, 0x02, + 0x6F12, 0x1449, 0x02, + 0x6F12, 0xE060, 0x02, + 0x6F12, 0x4FF6, 0x02, + 0x6F12, 0xA330, 0x02, + 0x6F12, 0x0968, 0x02, + 0x6F12, 0x4883, 0x02, + 0x6F12, 0x10BD, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x4390, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x2240, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0xF410, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0xF192, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x9000, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x0900, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x2120, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0x9338, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x1880, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x3280, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x25E8, 0x02, + 0x6F12, 0x4000, 0x02, + 0x6F12, 0xB000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x303B, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x08B0, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x4F0B, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x9D6F, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x57FD, 0x02, + 0x6F12, 0x2000, 0x02, + 0x6F12, 0x0510, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0xAF2C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x43F2, 0x02, + 0x6F12, 0x3B0C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x3B4C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x45F6, 0x02, + 0x6F12, 0x8D7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0xA54C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0xD12C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x44F6, 0x02, + 0x6F12, 0x0B7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x0F7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0xC32C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F6, 0x02, + 0x6F12, 0x0D2C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x45F6, 0x02, + 0x6F12, 0x5D3C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x41F2, 0x02, + 0x6F12, 0x370C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0x9F3C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x45F2, 0x02, + 0x6F12, 0xFD7C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x40F2, 0x02, + 0x6F12, 0xE51C, 0x02, + 0x6F12, 0xC0F2, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x6047, 0x02, + 0x6F12, 0x0000, 0x02, + + 0x6028, 0x2000, 0x02, + 0x602A, 0x130C, 0x02, + 0x6F12, 0x0001, 0x02, + 0x602A, 0x13BA, 0x02, + 0x6F12, 0x0C48, 0x02, + 0x602A, 0x1390, 0x02, + 0x6F12, 0x0015, 0x02, + 0x602A, 0x139E, 0x02, + 0x6F12, 0x0050, 0x02, + 0x602A, 0x139C, 0x02, + 0x6F12, 0x02AF, 0x02, + 0x602A, 0x139A, 0x02, + 0x6F12, 0x7086, 0x02, + 0x602A, 0x13A2, 0x02, + 0x6F12, 0x0430, 0x02, + 0x602A, 0x13BC, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x12AA, 0x02, + 0x6F12, 0x0300, 0x02, + 0x6F12, 0x0307, 0x02, + 0x602A, 0x0A18, 0x02, + 0x6F12, 0x0440, 0x02, + 0x602A, 0x0A28, 0x02, + 0x6F12, 0x0007, 0x02, + 0x602A, 0x0A58, 0x02, + 0x6F12, 0x0008, 0x02, + 0x602A, 0x0A78, 0x02, + 0x6F12, 0x00E8, 0x02, + 0x602A, 0x0A80, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x0A88, 0x02, + 0x6F12, 0x00E6, 0x02, + 0x602A, 0x0A90, 0x02, + 0x6F12, 0x0116, 0x02, + 0x602A, 0x0A98, 0x02, + 0x6F12, 0x011D, 0x02, + 0x602A, 0x0AA0, 0x02, + 0x6F12, 0x00F7, 0x02, + 0x602A, 0x0AB8, 0x02, + 0x6F12, 0x0116, 0x02, + 0x602A, 0x0AC0, 0x02, + 0x6F12, 0x00FE, 0x02, + 0x602A, 0x0AF0, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0AF8, 0x02, + 0x6F12, 0x02B5, 0x02, + 0x602A, 0x0B00, 0x02, + 0x6F12, 0x00E8, 0x02, + 0x602A, 0x0B08, 0x02, + 0x6F12, 0x02B3, 0x02, + 0x602A, 0x0B20, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0B28, 0x02, + 0x6F12, 0x0126, 0x02, + 0x602A, 0x0B80, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0B88, 0x02, + 0x6F12, 0x0011, 0x02, + 0x602A, 0x0B90, 0x02, + 0x6F12, 0x0015, 0x02, + 0x602A, 0x0B98, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x0BA0, 0x02, + 0x6F12, 0x012A, 0x02, + 0x602A, 0x0BB8, 0x02, + 0x6F12, 0x0114, 0x02, + 0x602A, 0x0BC0, 0x02, + 0x6F12, 0x0118, 0x02, + 0x602A, 0x0BF0, 0x02, + 0x6F12, 0x02B1, 0x02, + 0x602A, 0x0C80, 0x02, + 0x6F12, 0x00E5, 0x02, + 0x602A, 0x0C88, 0x02, + 0x6F12, 0x0184, 0x02, + 0x602A, 0x0C90, 0x02, + 0x6F12, 0x02B1, 0x02, + 0x602A, 0x0C98, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0CA0, 0x02, + 0x6F12, 0x0104, 0x02, + 0x602A, 0x0CA8, 0x02, + 0x6F12, 0x00F4, 0x02, + 0x602A, 0x0CB0, 0x02, + 0x6F12, 0x010C, 0x02, + 0x602A, 0x0CB8, 0x02, + 0x6F12, 0x00FC, 0x02, + 0x602A, 0x0CC0, 0x02, + 0x6F12, 0x010C, 0x02, + 0x602A, 0x0CC8, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0CD0, 0x02, + 0x6F12, 0x00EF, 0x02, + 0x602A, 0x0CE8, 0x02, + 0x6F12, 0x00F4, 0x02, + 0x602A, 0x0CF0, 0x02, + 0x6F12, 0x010C, 0x02, + 0x602A, 0x0D08, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0D10, 0x02, + 0x6F12, 0x00EF, 0x02, + 0x602A, 0x0D20, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x602A, 0x0D28, 0x02, + 0x6F12, 0x0182, 0x02, + 0x602A, 0x0D30, 0x02, + 0x6F12, 0x02B3, 0x02, + 0x602A, 0x0D58, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0D60, 0x02, + 0x6F12, 0x0107, 0x02, + 0x602A, 0x0D78, 0x02, + 0x6F12, 0x00ED, 0x02, + 0x602A, 0x0D80, 0x02, + 0x6F12, 0x00EF, 0x02, + 0x602A, 0x0DA0, 0x02, + 0x6F12, 0x02B7, 0x02, + 0x602A, 0x0DB8, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x602A, 0x0DC0, 0x02, + 0x6F12, 0x00EA, 0x02, + 0x602A, 0x0DC8, 0x02, + 0x6F12, 0x02B3, 0x02, + 0x602A, 0x0DD0, 0x02, + 0x6F12, 0x02B6, 0x02, + 0x602A, 0x0DD8, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x602A, 0x0DE8, 0x02, + 0x6F12, 0x00F1, 0x02, + 0x602A, 0x0DF0, 0x02, + 0x6F12, 0x0012, 0x02, + 0x602A, 0x0F00, 0x02, + 0x6F12, 0x0001, 0x02, + 0x602A, 0x09BE, 0x02, + 0x6F12, 0x0080, 0x02, + 0x602A, 0x1382, 0x02, + 0x6F12, 0x3CFC, 0x02, + 0x602A, 0x1E80, 0x02, + 0x6F12, 0x0100, 0x02, + 0x6F12, 0x003F, 0x02, + 0x6F12, 0x003F, 0x02, + 0x6F12, 0x0004, 0x02, + 0x6F12, 0x0006, 0x02, + 0x6F12, 0xF48E, 0x02, + 0x6F12, 0x0004, 0x02, + 0x6F12, 0x0006, 0x02, + 0x6F12, 0xF490, 0x02, + 0x6F12, 0x0005, 0x02, + 0x6F12, 0x0004, 0x02, + 0x6F12, 0xF488, 0x02, + 0x602A, 0x43AE, 0x02, + 0x6F12, 0x0170, 0x02, + 0x6F12, 0x017F, 0x02, + 0x6F12, 0x00E7, 0x02, + 0x6F12, 0x02B2, 0x02, + 0x6F12, 0xF5E8, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x0220, 0x0000, 0x02, + 0x6028, 0x2000, 0x02, + 0x602A, 0x0990, 0x02, + 0x6F12, 0x0001, 0x02, + 0x602A, 0x1C7E, 0x02, + 0x6F12, 0x001A, 0x02, + 0x0B04, 0x0101, 0x02, + 0x6028, 0x2000, 0x02, + 0x602A, 0x1E5C, 0x02, + 0x6F12, 0x0100, 0x02, + 0x302A, 0x0CA0, 0x02, + 0x300E, 0x0100, 0x02, + 0x0138, 0x0100, 0x02, + 0x6028, 0x2000, 0x02, + 0x602A, 0x18DE, 0x02, + 0x6F12, 0x0F28, 0x02, + 0x602A, 0x1952, 0x02, + 0x6F12, 0x000A, 0x02, + 0x602A, 0x43A0, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x0410, 0x02, + 0x6F12, 0x1000, 0x02, + 0x6F12, 0x0000, 0x02, + 0x602A, 0x18DA, 0x02, + 0x6F12, 0x2850, 0x02, + 0x602A, 0x1A74, 0x02, + 0x6F12, 0x0100, 0x02, +}; + +/* + * [Mode Information] + * 0: [MCLK:26,Width:5184,Height:3880,Format:MIPI_RAW10,mipi_lane:4,mipi_datarate:1500,pvi_pclk_inverse:0] + */ + +const u32 sensor_2t7sx_setfile_B_5184x3880_30fps[] = { + 0x6028, 0x2000, 0x02, + 0x0344, 0x0008, 0x02, + 0x0346, 0x0008, 0x02, + 0x0348, 0x1447, 0x02, + 0x034A, 0x0F2F, 0x02, + 0x034C, 0x1440, 0x02, + 0x034E, 0x0F28, 0x02, + 0x0408, 0x0000, 0x02, + 0x040A, 0x0000, 0x02, + 0x0900, 0x0011, 0x02, + 0x0380, 0x0001, 0x02, + 0x0382, 0x0001, 0x02, + 0x0384, 0x0001, 0x02, + 0x0386, 0x0001, 0x02, + 0x0400, 0x0000, 0x02, + 0x0404, 0x0010, 0x02, + 0x301E, 0x0110, 0x02, + 0x0110, 0x0002, 0x02, + 0x0114, 0x0300, 0x02, + 0x0136, 0x1A00, 0x02, + 0x0300, 0x0005, 0x02, + 0x0302, 0x0001, 0x02, + 0x0304, 0x0006, 0x02, + 0x0306, 0x00C3, 0x02, + 0x0308, 0x0008, 0x02, + 0x030A, 0x0001, 0x02, + 0x030C, 0x0004, 0x02, + 0x030E, 0x0082, 0x02, + 0x0310, 0x0100, 0x02, + 0x0312, 0x0000, 0x02, + 0x0340, 0x0FA8, 0x02, + 0x0342, 0x1608, 0x02, + 0x602A, 0x1C78, 0x02, + 0x6F12, 0x8100, 0x02, + 0x602A, 0x43CA, 0x02, + 0x6F12, 0x0020, 0x02, + 0x602A, 0x13E4, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x000C, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6F12, 0x0012, 0x02, + 0x6226, 0x0001, 0x02, + 0x9400, 0x0001, 0x02, + 0x9402, 0x0028, 0x02, + 0x9404, 0x000A, 0x02, + 0x9406, 0x0000, 0x02, + 0x9408, 0x0000, 0x02, + 0x940A, 0x0000, 0x02, + 0x940C, 0x0000, 0x02, + 0x940E, 0x1400, 0x02, + 0x9410, 0x0780, 0x02, + 0x9412, 0x0000, 0x02, + 0x9414, 0x0000, 0x02, + 0x9416, 0x0000, 0x02, + 0x9418, 0x0001, 0x02, + 0x941A, 0x0082, 0x02, + 0x941C, 0x0186, 0x02, + 0x941E, 0x0082, 0x02, + 0x9420, 0x0186, 0x02, + 0x9422, 0x0141, 0x02, + 0x9424, 0x0141, 0x02, + 0x9426, 0x0141, 0x02, + 0x9428, 0x0141, 0x02, + 0x942A, 0x0008, 0x02, + 0x942C, 0x0008, 0x02, + 0x942E, 0x0004, 0x02, + 0x9430, 0x0004, 0x02, + 0x9432, 0x5500, 0x02, + 0x9434, 0x5500, 0x02, + 0x6226, 0x0000, 0x02, + 0x602A, 0x1E76, 0x02, + 0x6F12, 0x0100, 0x02, + 0x6F12, 0x0000, 0x02, +}; + +const struct sensor_pll_info_compact sensor_2t7sx_pllinfo_B_5184x3880_30fps = { + EXT_CLK_Mhz * 1000 * 1000, /* ext_clk */ + 1690000000, /* mipi_datarate */ + 676000000, /* pclk = VT pix CLK (this value is different by cis) */ + 0x0FA8, /* frame_length_lines (0x0340) */ + 0x1608, /* line_length_pck (0x0342) */ +}; + +static const u32 *sensor_2t7sx_setfiles_B[] = { + sensor_2t7sx_setfile_B_5184x3880_30fps, +}; + +static const u32 sensor_2t7sx_setfile_B_sizes[] = { + ARRAY_SIZE(sensor_2t7sx_setfile_B_5184x3880_30fps), +}; + +static const struct sensor_pll_info_compact *sensor_2t7sx_pllinfos_B[] = { + &sensor_2t7sx_pllinfo_B_5184x3880_30fps, +}; +#endif diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.c b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.c new file mode 100644 index 000000000000..640938ce3895 --- /dev/null +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.c @@ -0,0 +1,1825 @@ +/* + * Samsung Exynos5 SoC series Sensor driver + * + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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-2t7sx.h" +#include "fimc-is-cis-2t7sx-setA.h" +#include "fimc-is-cis-2t7sx-setB.h" + +#include "fimc-is-helper-i2c.h" + +#define SENSOR_NAME "S5K2T7SX" +/* #define DEBUG_2T7SX_PLL */ + +static const struct v4l2_subdev_ops subdev_ops; + +static const u32 *sensor_2t7sx_global; +static u32 sensor_2t7sx_global_size; +static const u32 **sensor_2t7sx_setfiles; +static const u32 *sensor_2t7sx_setfile_sizes; +static const struct sensor_pll_info_compact **sensor_2t7sx_pllinfos; +static u32 sensor_2t7sx_max_setfile_num; + +static void sensor_2t7sx_cis_data_calculation(const struct sensor_pll_info_compact *pll_info_compact, cis_shared_data *cis_data) +{ + u32 vt_pix_clk_hz = 0; + u32 frame_rate = 0, max_fps = 0, frame_valid_us = 0; + + BUG_ON(!pll_info_compact); + + /* 1. get pclk value from pll info */ + vt_pix_clk_hz = pll_info_compact->pclk; + + dbg_sensor(1, "ext_clock(%d), mipi_datarate(%d), pclk(%d)\n", + pll_info_compact->ext_clk, pll_info_compact->mipi_datarate, pll_info_compact->pclk); + + /* 2. the time of processing one frame calculation (us) */ + cis_data->min_frame_us_time = (pll_info_compact->frame_length_lines * pll_info_compact->line_length_pck + / (vt_pix_clk_hz / (1000 * 1000))); + cis_data->cur_frame_us_time = cis_data->min_frame_us_time; + + /* 3. FPS calculation */ + frame_rate = vt_pix_clk_hz / (pll_info_compact->frame_length_lines * pll_info_compact->line_length_pck); + dbg_sensor(1, "frame_rate (%d) = vt_pix_clk_hz(%d) / " + KERN_CONT "(pll_info_compact->frame_length_lines(%d) * pll_info_compact->line_length_pck(%d))\n", + frame_rate, vt_pix_clk_hz, pll_info_compact->frame_length_lines, pll_info_compact->line_length_pck); + + /* calculate max fps */ + max_fps = (vt_pix_clk_hz * 10) / (pll_info_compact->frame_length_lines * pll_info_compact->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_compact->frame_length_lines; + cis_data->line_length_pck = pll_info_compact->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); + + /* 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_2T7SX_FINE_INTEGRATION_TIME_MIN; + cis_data->max_fine_integration_time = SENSOR_2T7SX_FINE_INTEGRATION_TIME_MAX; + cis_data->min_coarse_integration_time = SENSOR_2T7SX_COARSE_INTEGRATION_TIME_MIN; + cis_data->max_margin_coarse_integration_time = SENSOR_2T7SX_COARSE_INTEGRATION_TIME_MAX_MARGIN; +} + +static int sensor_2t7sx_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_2t7sx_cis_init(struct v4l2_subdev *subdev) +{ + int ret = 0; + struct fimc_is_cis *cis; + u32 setfile_index = 0; + cis_setting_info setinfo; + + setinfo.return_value = 0; + + setinfo.param = NULL; + + 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_2t7sx_check_rev is fail when cis init"); + cis->rev_flag = true; + ret = 0; + } + + cis->cis_data->cur_width = SENSOR_2T7SX_MAX_WIDTH; + cis->cis_data->cur_height = SENSOR_2T7SX_MAX_HEIGHT; + cis->cis_data->low_expo_start = 33000; + cis->need_mode_change = false; + + sensor_2t7sx_cis_data_calculation(sensor_2t7sx_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_2t7sx_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"); + fimc_is_sensor_read16(client, 0x0000, &data16); + pr_err("[SEN:DUMP] model_id(%x)\n", data16); + fimc_is_sensor_read8(client, 0x0002, &data8); + pr_err("[SEN:DUMP] revision_number(%x)\n", data8); + fimc_is_sensor_read8(client, 0x0005, &data8); + pr_err("[SEN:DUMP] frame_count(%x)\n", data8); + fimc_is_sensor_read8(client, 0x0100, &data8); + pr_err("[SEN:DUMP] mode_select(%x)\n", data8); + + sensor_cis_dump_registers(subdev, sensor_2t7sx_setfiles[0], sensor_2t7sx_setfile_sizes[0]); + + pr_err("[SEN:DUMP] *******************************\n"); + +p_err: + return ret; +} + +#if USE_GROUP_PARAM_HOLD +static int sensor_2t7sx_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_2t7sx_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_2t7sx_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_2t7sx_cis_group_param_hold_func(subdev, hold); + if (ret < 0) + goto p_err; + +p_err: + return ret; +} + +int sensor_2t7sx_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); + + ret = sensor_cis_set_registers(subdev, sensor_2t7sx_global, sensor_2t7sx_global_size); + + if (ret < 0) { + err("sensor_3p8sp_set_registers fail!!"); + goto p_err; + } + + dbg_sensor(1, "[%s] global setting done\n", __func__); + +p_err: + return ret; +} + +int sensor_2t7sx_cis_mode_change(struct v4l2_subdev *subdev, u32 mode) +{ + 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); + + if (mode > sensor_2t7sx_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_2t7sx_check_rev is fail"); + goto p_err; + } + } + + sensor_2t7sx_cis_data_calculation(sensor_2t7sx_pllinfos[mode], cis->cis_data); + + ret = sensor_cis_set_registers(subdev, sensor_2t7sx_setfiles[mode], sensor_2t7sx_setfile_sizes[mode]); + if (ret < 0) { + err("sensor_2t7sx_set_registers fail!!"); + goto p_err; + } + + cis->cis_data->frame_time = (cis->cis_data->line_readOut_time * cis->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); + + 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_2t7sx_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_2t7sx_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_2T7SX_MAX_WIDTH / cis_data->cur_width); + ratio_h = (SENSOR_2T7SX_MAX_HEIGHT / cis_data->cur_height); + } else { + ratio_w = 1; + ratio_h = 1; + } + + if (((cis_data->cur_width * ratio_w) > SENSOR_2T7SX_MAX_WIDTH) || + ((cis_data->cur_height * ratio_h) > SENSOR_2T7SX_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_2T7SX_MAX_WIDTH - cis_data->cur_width * ratio_w) / 2) & (~0x1); + start_y = ((SENSOR_2T7SX_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_2t7sx_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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (ret < 0) + err("group_param_hold_func failed at stream on"); + +#ifdef DEBUG_2T7SX_PLL + { + u16 pll; + + fimc_is_sensor_read16(client, 0x0300, &pll); + dbg_sensor(1, "______ vt_pix_clk_div(%x)\n", pll); + fimc_is_sensor_read16(client, 0x0302, &pll); + dbg_sensor(1, "______ vt_sys_clk_div(%x)\n", pll); + fimc_is_sensor_read16(client, 0x0304, &pll); + dbg_sensor(1, "______ pre_pll_clk_div(%x)\n", pll); + fimc_is_sensor_read16(client, 0x0306, &pll); + dbg_sensor(1, "______ pll_multiplier(%x)\n", pll); + fimc_is_sensor_read16(client, 0x0308, &pll); + dbg_sensor(1, "______ op_pix_clk_div(%x)\n", pll); + fimc_is_sensor_read16(client, 0x030a, &pll); + dbg_sensor(1, "______ op_sys_clk_div(%x)\n", pll); + + fimc_is_sensor_read16(client, 0x030c, &pll); + dbg_sensor(1, "______ secnd_pre_pll_clk_div(%x)\n", pll); + fimc_is_sensor_read16(client, 0x030e, &pll); + dbg_sensor(1, "______ secnd_pll_multiplier(%x)\n", pll); + fimc_is_sensor_read16(client, 0x0340, &pll); + dbg_sensor(1, "______ frame_length_lines(%x)\n", pll); + fimc_is_sensor_read16(client, 0x0342, &pll); + dbg_sensor(1, "______ line_length_pck(%x)\n", pll); + } +#endif + + /* Sensor stream on */ + fimc_is_sensor_write16(client, 0x6028, 0x4000); + fimc_is_sensor_write8(client, 0x0100, 0x01); + + /* WDR */ + if (fimc_is_vender_wdr_mode_on(cis_data)) + fimc_is_sensor_write8(client, 0x0216, 0x01); + else + fimc_is_sensor_write8(client, 0x0216, 0x00); + + 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_2t7sx_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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (ret < 0) + err("group_param_hold_func failed at stream off"); + + /* Sensor stream off */ + fimc_is_sensor_write16(client, 0x6028, 0x4000); + fimc_is_sensor_write8(client, 0x0100, 0x00); + + 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_2t7sx_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_2t7sx_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 (fimc_is_vender_wdr_mode_on(cis_data)) { + 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), 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), 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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (hold < 0) + ret = hold; + } + + return ret; +} + +int sensor_2t7sx_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_2t7sx_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_2t7sx_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_2t7sx_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; + + u32 max_coarse_integration_time = 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_2t7sx_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; + + max_coarse_integration_time = cis_data->frame_length_lines - cis_data->max_margin_coarse_integration_time; + cis_data->max_coarse_integration_time = 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: + if (hold > 0) { + hold = sensor_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (hold < 0) + ret = hold; + } + + return ret; +} + +int sensor_2t7sx_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_2t7sx_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_2t7sx_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_2t7sx_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_2t7sx_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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (hold < 0) + ret = hold; + } + + return ret; +} + +int sensor_2t7sx_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_2t7sx_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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (hold < 0) + ret = hold; + } + + return ret; +} + +int sensor_2t7sx_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; + + fimc_is_sensor_read16(client, 0x0084, &read_value); + + 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_2t7sx_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; + + fimc_is_sensor_read16(client, 0x0086, &read_value); + + 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_2t7sx_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_2t7sx_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 (fimc_is_vender_wdr_mode_on(cis_data)) { + ret = fimc_is_sensor_write16(client, 0x305C, long_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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (hold < 0) + ret = hold; + } + + return ret; +} + +int sensor_2t7sx_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_2t7sx_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_2t7sx_cis_group_param_hold_func(subdev, 0x00); + if (hold < 0) + ret = hold; + } + + return ret; +} + +int sensor_2t7sx_cis_get_min_digital_gain(struct v4l2_subdev *subdev, u32 *min_dgain) +{ + 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_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; + + fimc_is_sensor_read16(client, 0x1084, &read_value); + + cis_data->min_digital_gain[0] = read_value; + + cis_data->min_digital_gain[1] = sensor_cis_calc_dgain_permile(read_value); + + *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 + +p_err: + return ret; +} + +int sensor_2t7sx_cis_get_max_digital_gain(struct v4l2_subdev *subdev, u32 *max_dgain) +{ + 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_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; + + fimc_is_sensor_read16(client, 0x1086, &read_value); + + cis_data->max_digital_gain[0] = read_value; + + cis_data->max_digital_gain[1] = sensor_cis_calc_dgain_permile(read_value); + + *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 + +p_err: + return ret; +} + +static struct fimc_is_cis_ops cis_ops = { + .cis_init = sensor_2t7sx_cis_init, + .cis_log_status = sensor_2t7sx_cis_log_status, + .cis_group_param_hold = sensor_2t7sx_cis_group_param_hold, + .cis_set_global_setting = sensor_2t7sx_cis_set_global_setting, + .cis_mode_change = sensor_2t7sx_cis_mode_change, + .cis_set_size = sensor_2t7sx_cis_set_size, + .cis_stream_on = sensor_2t7sx_cis_stream_on, + .cis_stream_off = sensor_2t7sx_cis_stream_off, + .cis_set_exposure_time = sensor_2t7sx_cis_set_exposure_time, + .cis_get_min_exposure_time = sensor_2t7sx_cis_get_min_exposure_time, + .cis_get_max_exposure_time = sensor_2t7sx_cis_get_max_exposure_time, + .cis_adjust_frame_duration = sensor_2t7sx_cis_adjust_frame_duration, + .cis_set_frame_duration = sensor_2t7sx_cis_set_frame_duration, + .cis_set_frame_rate = sensor_2t7sx_cis_set_frame_rate, + .cis_adjust_analog_gain = sensor_2t7sx_cis_adjust_analog_gain, + .cis_set_analog_gain = sensor_2t7sx_cis_set_analog_gain, + .cis_get_analog_gain = sensor_2t7sx_cis_get_analog_gain, + .cis_get_min_analog_gain = sensor_2t7sx_cis_get_min_analog_gain, + .cis_get_max_analog_gain = sensor_2t7sx_cis_get_max_analog_gain, + .cis_set_digital_gain = sensor_2t7sx_cis_set_digital_gain, + .cis_get_digital_gain = sensor_2t7sx_cis_get_digital_gain, + .cis_get_min_digital_gain = sensor_2t7sx_cis_get_min_digital_gain, + .cis_get_max_digital_gain = sensor_2t7sx_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, +}; + +static int cis_2t7sx_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + 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; + + ret = of_property_read_u32(dnode, "id", &sensor_id); + if (ret) { + err("sensor id read is fail(%d)", 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_S5K2T7SX); + 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 NULL"); + ret = -ENOMEM; + goto p_err; + } + sensor_peri->subdev_cis = subdev_cis; + + cis->id = SENSOR_NAME_S5K2T7SX; + 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 = F2_2; + } + + probe_info("%s f-number %d\n", __func__, cis->aperture_num); + + cis->use_dgain = true; + cis->hdr_ctrl_by_again = 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\n", __func__); + sensor_2t7sx_global = sensor_2t7sx_setfile_A_Global; + sensor_2t7sx_global_size = ARRAY_SIZE(sensor_2t7sx_setfile_A_Global); + sensor_2t7sx_setfiles = sensor_2t7sx_setfiles_A; + sensor_2t7sx_setfile_sizes = sensor_2t7sx_setfile_A_sizes; + sensor_2t7sx_pllinfos = sensor_2t7sx_pllinfos_A; + sensor_2t7sx_max_setfile_num = ARRAY_SIZE(sensor_2t7sx_setfiles_A); + } else if (strcmp(setfile, "setB") == 0) { + probe_info("%s setfile_B\n", __func__); + sensor_2t7sx_global = sensor_2t7sx_setfile_B_Global; + sensor_2t7sx_global_size = ARRAY_SIZE(sensor_2t7sx_setfile_B_Global); + sensor_2t7sx_setfiles = sensor_2t7sx_setfiles_B; + sensor_2t7sx_setfile_sizes = sensor_2t7sx_setfile_B_sizes; + sensor_2t7sx_pllinfos = sensor_2t7sx_pllinfos_B; + sensor_2t7sx_max_setfile_num = ARRAY_SIZE(sensor_2t7sx_setfiles_B); + } else { + err("%s setfile index out of bound, take default (setfile_A)", __func__); + sensor_2t7sx_global = sensor_2t7sx_setfile_A_Global; + sensor_2t7sx_global_size = ARRAY_SIZE(sensor_2t7sx_setfile_A_Global); + sensor_2t7sx_setfiles = sensor_2t7sx_setfiles_A; + sensor_2t7sx_setfile_sizes = sensor_2t7sx_setfile_A_sizes; + sensor_2t7sx_pllinfos = sensor_2t7sx_pllinfos_A; + sensor_2t7sx_max_setfile_num = ARRAY_SIZE(sensor_2t7sx_setfiles_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 const struct of_device_id sensor_cis_2t7sx_match[] = { + { + .compatible = "samsung,exynos5-fimc-is-cis-2t7sx", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, sensor_cis_2t7sx_match); + +static const struct i2c_device_id sensor_cis_2t7sx_idt[] = { + { SENSOR_NAME, 0 }, + {}, +}; + +static struct i2c_driver sensor_cis_2t7sx_driver = { + .probe = cis_2t7sx_probe, + .driver = { + .name = SENSOR_NAME, + .owner = THIS_MODULE, + .of_match_table = sensor_cis_2t7sx_match, + .suppress_bind_attrs = true, + }, + .id_table = sensor_cis_2t7sx_idt +}; + +static int __init sensor_cis_2t7sx_init(void) +{ + int ret; + + ret = i2c_add_driver(&sensor_cis_2t7sx_driver); + if (ret) + err("failed to add %s driver: %d\n", + sensor_cis_2t7sx_driver.driver.name, ret); + + return ret; +} +late_initcall_sync(sensor_cis_2t7sx_init); diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.h new file mode 100644 index 000000000000..90ccf4233fc8 --- /dev/null +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/cis/fimc-is-cis-2t7sx.h @@ -0,0 +1,31 @@ +/* + * Samsung Exynos5 SoC series Sensor driver + * + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef FIMC_IS_CIS_2T7SX_H +#define FIMC_IS_CIS_2T7SX_H + +#include "fimc-is-cis.h" + +#define EXT_CLK_Mhz (26) + +#define SENSOR_2T7SX_MAX_WIDTH (5168 + 16) /* 5184 */ +#define SENSOR_2T7SX_MAX_HEIGHT (3868 + 12) /* 3880 */ + +/* TODO: Check below values are valid */ +#define SENSOR_2T7SX_FINE_INTEGRATION_TIME_MIN 0x200 +#define SENSOR_2T7SX_FINE_INTEGRATION_TIME_MAX 0x200 +#define SENSOR_2T7SX_COARSE_INTEGRATION_TIME_MIN 0x4 +#define SENSOR_2T7SX_COARSE_INTEGRATION_TIME_MAX_MARGIN 0x8 + +#define USE_GROUP_PARAM_HOLD (1) + +#endif + diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/Makefile b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/Makefile index 61c9ca2905a7..6ac3218f2ddc 100644 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/Makefile +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_CAMERA_CIS_3P8SP_OBJ) += fimc-is-device-module-3p8sp.o obj-$(CONFIG_CAMERA_CIS_2P7SX_OBJ) += fimc-is-device-module-2p7sx.o obj-$(CONFIG_CAMERA_CIS_RPB_OBJ) += fimc-is-device-module-rpb.o obj-$(CONFIG_CAMERA_CIS_2P7SQ_OBJ) += fimc-is-device-module-2p7sq.o +obj-$(CONFIG_CAMERA_CIS_2T7SX_OBJ) += fimc-is-device-module-2t7sx.o obj-$(CONFIG_CAMERA_CIS_2L2_OBJ) += fimc-is-device-module-2l2.o obj-$(CONFIG_CAMERA_CIS_2L3_OBJ) += fimc-is-device-module-2l3.o obj-$(CONFIG_CAMERA_CIS_IMX260_OBJ) += fimc-is-device-module-imx260.o diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2t7sx.c b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2t7sx.c new file mode 100644 index 000000000000..fcbb0fe4e4a3 --- /dev/null +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-2t7sx.c @@ -0,0 +1,356 @@ +/* + * Samsung Exynos5 SoC series Sensor driver + * + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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_2T7SX_SETPIN_CNT 2 + +static struct fimc_is_sensor_cfg config_module_2t7sx[] = { + /* width, height, fps, settle, mode, lane, speed, interleave, pd_mode */ + FIMC_IS_SENSOR_CFG(5184, 3880, 30, 0, 0, CSI_DATA_LANES_4, 1690, CSI_MODE_VC_DT, PD_NONE, + VC_IN(0, HW_FORMAT_RAW10, 5184, 3880), VC_OUT(HW_FORMAT_RAW10, VC_NOTHING, 0, 0), + VC_IN(1, HW_FORMAT_UNKNOWN, 0, 0), VC_OUT(HW_FORMAT_UNKNOWN, VC_NOTHING, 0, 0), + VC_IN(2, HW_FORMAT_USER, 0, 0), VC_OUT(HW_FORMAT_USER, VC_NOTHING, 0, 0), + VC_IN(3, HW_FORMAT_UNKNOWN, 0, 0), VC_OUT(HW_FORMAT_UNKNOWN, VC_NOTHING, 0, 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_parm = sensor_module_s_param +}; + +static const struct v4l2_subdev_pad_ops pad_ops = { + .set_fmt = sensor_module_s_format +}; + +static const struct v4l2_subdev_ops subdev_ops = { + .core = &core_ops, + .video = &video_ops, + .pad = &pad_ops +}; + +static int sensor_module_2t7sx_power_setpin(struct device *dev, + struct exynos_platform_fimc_is_module *pdata) +{ + struct device_node *dnode; + int gpio_reset = 0; + int gpio_none = 0; + int gpio_mclk = 0; + + BUG_ON(!dev); + + dnode = dev->of_node; + + dev_info(dev, "%s E v4\n", __func__); + + /* TODO */ + 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_mclk = of_get_named_gpio(dnode, "gpio_mclk", 0); + if (gpio_is_valid(gpio_mclk)) { + if (gpio_request_one(gpio_mclk, GPIOF_OUT_INIT_LOW, "CAM_MCLK_OUTPUT_LOW")) { + dev_err(dev, "%s: failed to gpio request mclk\n", __func__); + return -ENODEV; + } + gpio_free(gpio_mclk); + } else { + dev_err(dev, "%s: failed to get mclk\n", __func__); + return -EINVAL; + } + + 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_VISION, GPIO_SCENARIO_ON); + SET_PIN_INIT(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF); + + /* BACK CAEMRA - POWER ON */ + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_reset, "sen_rst low", PIN_OUTPUT, 0, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM_T", PIN_REGULATOR, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDD_2.8V_OIS_T", PIN_REGULATOR, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDA_2.8V_CAM_T", PIN_REGULATOR, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "VDDD_1.0V_CAM_T", PIN_REGULATOR, 1, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_none, "pin", PIN_FUNCTION, 2, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_ON, gpio_reset, "sen_rst high", PIN_OUTPUT, 1, 2000); + + /* BACK CAEMRA - POWER OFF */ + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_reset, "sen_rst", PIN_RESET, 0, 10); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_reset, "sen_rst input", PIN_INPUT, 0, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDD_1.0V_CAM_T", PIN_REGULATOR, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDD_2.8V_OIS_T", PIN_REGULATOR, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDA_2.8V_CAM_T", PIN_REGULATOR, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM_T", PIN_REGULATOR, 0, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_NORMAL, GPIO_SCENARIO_OFF, gpio_none, "pin", PIN_FUNCTION, 0, 0); + 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", PIN_FUNCTION, 0, 0); + + /* REAR VISION CAEMRA - POWER ON */ + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_reset, "sen_rst low", PIN_OUTPUT, 0, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_none, "VDDIO_1.8V_CAM_T", PIN_REGULATOR, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_none, "VDDD_2.8V_OIS_T", PIN_REGULATOR, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_none, "VDDA_2.8V_CAM_T", PIN_REGULATOR, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_none, "VDDD_1.0V_CAM_T", PIN_REGULATOR, 1, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_none, "pin", PIN_FUNCTION, 2, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_ON, gpio_reset, "sen_rst high", PIN_OUTPUT, 1, 2000); + + + /* REAR VISION CAEMRA - POWER OFF */ + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_reset, "sen_rst", PIN_RESET, 0, 10); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_reset, "sen_rst input", PIN_INPUT, 0, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "VDDD_1.0V_CAM_T", PIN_REGULATOR, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "VDDD_2.8V_OIS_T", PIN_REGULATOR, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "VDDA_2.8V_CAM_T", PIN_REGULATOR, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "VDDIO_1.8V_CAM_T", PIN_REGULATOR, 0, 0); + + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "pin", PIN_FUNCTION, 0, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "pin", PIN_FUNCTION, 1, 0); + SET_PIN(pdata, SENSOR_SCENARIO_VISION, GPIO_SCENARIO_OFF, gpio_none, "pin", PIN_FUNCTION, 0, 0); + + dev_info(dev, "%s X v4\n", __func__); + + return 0; +} + +static int __init sensor_module_2t7sx_probe(struct platform_device *pdev) +{ + int ret = 0; + struct fimc_is_core *core; + struct v4l2_subdev *subdev_module; + struct fimc_is_module_enum *module; + struct fimc_is_device_sensor *device; + struct sensor_open_extended *ext; + struct exynos_platform_fimc_is_module *pdata; + struct device *dev; + struct pinctrl_state *s; + + 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; + +#ifdef CONFIG_OF + fimc_is_module_parse_dt(dev, sensor_module_2t7sx_power_setpin); +#endif + + 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_S5K2T7SX; + module->subdev = subdev_module; + module->device = pdata->id; + module->client = NULL; + module->active_width = 5168 + 16; + module->active_height = 3868 + 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->bitwidth = 10; + module->sensor_maker = "SLSI"; + module->sensor_name = "S5K2T7SX"; + module->setfile_name = "setfile_2t7sx.bin"; + module->cfgs = ARRAY_SIZE(config_module_2t7sx); + module->cfg = config_module_2t7sx; + module->ops = NULL; + + /* 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->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; + + ext->actuator_con.product_name = ACTUATOR_NAME_NOTHING; + ext->flash_con.product_name = FLADRV_NAME_NOTHING; + ext->from_con.product_name = FROMDRV_NAME_NOTHING; + ext->preprocessor_con.product_name = PREPROCESSOR_NAME_NOTHING; + ext->ois_con.product_name = OIS_NAME_NOTHING; + + 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; + if (pdata->preprocessor_dma_channel == DMA_CH_NOT_DEFINED) + ext->preprocessor_con.peri_info2.peri_setting.dma.channel = FLITE_ID_D; + else + ext->preprocessor_con.peri_info2.peri_setting.dma.channel = pdata->preprocessor_dma_channel; + } + + 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); + + s = pinctrl_lookup_state(pdata->pinctrl, "release"); + + if (pinctrl_select_state(pdata->pinctrl, s) < 0) { + probe_err("pinctrl_select_state is fail\n"); + goto p_err; + } + + probe_info("%s done\n", __func__); + +p_err: + return ret; +} + +static const struct of_device_id exynos_fimc_is_sensor_module_2t7sx_match[] = { + { + .compatible = "samsung,sensor-module-2t7sx", + }, + { + .compatible = "samsung,sensor-module-2t7sx-front", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_fimc_is_sensor_module_2t7sx_match); + +static struct platform_driver sensor_module_2t7sx_driver = { + .driver = { + .name = "FIMC-IS-SENSOR-MODULE-2T7SX", + .owner = THIS_MODULE, + .of_match_table = exynos_fimc_is_sensor_module_2t7sx_match, + } +}; + +static int __init fimc_is_sensor_module_2t7sx_init(void) +{ + int ret; + + ret = platform_driver_probe(&sensor_module_2t7sx_driver, + sensor_module_2t7sx_probe); + if (ret) + err("failed to probe %s driver: %d\n", + sensor_module_2t7sx_driver.driver.name, ret); + + return ret; +} +late_initcall(fimc_is_sensor_module_2t7sx_init); -- 2.20.1