xref: /openbmc/linux/drivers/media/i2c/ov13858.c (revision 4106cd72)
128cab405SChiranjeevi Rapolu // SPDX-License-Identifier: GPL-2.0
228cab405SChiranjeevi Rapolu // Copyright (c) 2017 Intel Corporation.
35fcf092eSHyungwoo Yang 
45fcf092eSHyungwoo Yang #include <linux/acpi.h>
55fcf092eSHyungwoo Yang #include <linux/i2c.h>
65fcf092eSHyungwoo Yang #include <linux/module.h>
75fcf092eSHyungwoo Yang #include <linux/pm_runtime.h>
85fcf092eSHyungwoo Yang #include <media/v4l2-ctrls.h>
95fcf092eSHyungwoo Yang #include <media/v4l2-device.h>
105bd4098cSRicardo Ribalda #include <media/v4l2-event.h>
1174c3ddd9SJacopo Mondi #include <media/v4l2-fwnode.h>
125fcf092eSHyungwoo Yang 
135fcf092eSHyungwoo Yang #define OV13858_REG_VALUE_08BIT		1
145fcf092eSHyungwoo Yang #define OV13858_REG_VALUE_16BIT		2
155fcf092eSHyungwoo Yang #define OV13858_REG_VALUE_24BIT		3
165fcf092eSHyungwoo Yang 
175fcf092eSHyungwoo Yang #define OV13858_REG_MODE_SELECT		0x0100
185fcf092eSHyungwoo Yang #define OV13858_MODE_STANDBY		0x00
195fcf092eSHyungwoo Yang #define OV13858_MODE_STREAMING		0x01
205fcf092eSHyungwoo Yang 
215fcf092eSHyungwoo Yang #define OV13858_REG_SOFTWARE_RST	0x0103
225fcf092eSHyungwoo Yang #define OV13858_SOFTWARE_RST		0x01
235fcf092eSHyungwoo Yang 
245fcf092eSHyungwoo Yang /* PLL1 generates PCLK and MIPI_PHY_CLK */
255fcf092eSHyungwoo Yang #define OV13858_REG_PLL1_CTRL_0		0x0300
265fcf092eSHyungwoo Yang #define OV13858_REG_PLL1_CTRL_1		0x0301
275fcf092eSHyungwoo Yang #define OV13858_REG_PLL1_CTRL_2		0x0302
285fcf092eSHyungwoo Yang #define OV13858_REG_PLL1_CTRL_3		0x0303
295fcf092eSHyungwoo Yang #define OV13858_REG_PLL1_CTRL_4		0x0304
305fcf092eSHyungwoo Yang #define OV13858_REG_PLL1_CTRL_5		0x0305
315fcf092eSHyungwoo Yang 
325fcf092eSHyungwoo Yang /* PLL2 generates DAC_CLK, SCLK and SRAM_CLK */
335fcf092eSHyungwoo Yang #define OV13858_REG_PLL2_CTRL_B		0x030b
345fcf092eSHyungwoo Yang #define OV13858_REG_PLL2_CTRL_C		0x030c
355fcf092eSHyungwoo Yang #define OV13858_REG_PLL2_CTRL_D		0x030d
365fcf092eSHyungwoo Yang #define OV13858_REG_PLL2_CTRL_E		0x030e
375fcf092eSHyungwoo Yang #define OV13858_REG_PLL2_CTRL_F		0x030f
385fcf092eSHyungwoo Yang #define OV13858_REG_PLL2_CTRL_12	0x0312
395fcf092eSHyungwoo Yang #define OV13858_REG_MIPI_SC_CTRL0	0x3016
405fcf092eSHyungwoo Yang #define OV13858_REG_MIPI_SC_CTRL1	0x3022
415fcf092eSHyungwoo Yang 
425fcf092eSHyungwoo Yang /* Chip ID */
435fcf092eSHyungwoo Yang #define OV13858_REG_CHIP_ID		0x300a
445fcf092eSHyungwoo Yang #define OV13858_CHIP_ID			0x00d855
455fcf092eSHyungwoo Yang 
465fcf092eSHyungwoo Yang /* V_TIMING internal */
475fcf092eSHyungwoo Yang #define OV13858_REG_VTS			0x380e
485fcf092eSHyungwoo Yang #define OV13858_VTS_30FPS		0x0c8e /* 30 fps */
495fcf092eSHyungwoo Yang #define OV13858_VTS_60FPS		0x0648 /* 60 fps */
505fcf092eSHyungwoo Yang #define OV13858_VTS_MAX			0x7fff
515fcf092eSHyungwoo Yang 
525fcf092eSHyungwoo Yang /* HBLANK control - read only */
5389d8b615SChiranjeevi Rapolu #define OV13858_PPL_270MHZ		2244
5489d8b615SChiranjeevi Rapolu #define OV13858_PPL_540MHZ		4488
555fcf092eSHyungwoo Yang 
565fcf092eSHyungwoo Yang /* Exposure control */
575fcf092eSHyungwoo Yang #define OV13858_REG_EXPOSURE		0x3500
585fcf092eSHyungwoo Yang #define OV13858_EXPOSURE_MIN		4
595fcf092eSHyungwoo Yang #define OV13858_EXPOSURE_STEP		1
605fcf092eSHyungwoo Yang #define OV13858_EXPOSURE_DEFAULT	0x640
615fcf092eSHyungwoo Yang 
625fcf092eSHyungwoo Yang /* Analog gain control */
635fcf092eSHyungwoo Yang #define OV13858_REG_ANALOG_GAIN		0x3508
645fcf092eSHyungwoo Yang #define OV13858_ANA_GAIN_MIN		0
655fcf092eSHyungwoo Yang #define OV13858_ANA_GAIN_MAX		0x1fff
665fcf092eSHyungwoo Yang #define OV13858_ANA_GAIN_STEP		1
675fcf092eSHyungwoo Yang #define OV13858_ANA_GAIN_DEFAULT	0x80
685fcf092eSHyungwoo Yang 
695fcf092eSHyungwoo Yang /* Digital gain control */
70bfced6d1SChiranjeevi Rapolu #define OV13858_REG_B_MWB_GAIN		0x5100
71bfced6d1SChiranjeevi Rapolu #define OV13858_REG_G_MWB_GAIN		0x5102
72bfced6d1SChiranjeevi Rapolu #define OV13858_REG_R_MWB_GAIN		0x5104
73bfced6d1SChiranjeevi Rapolu #define OV13858_DGTL_GAIN_MIN		0
74bfced6d1SChiranjeevi Rapolu #define OV13858_DGTL_GAIN_MAX		16384	/* Max = 16 X */
75bfced6d1SChiranjeevi Rapolu #define OV13858_DGTL_GAIN_DEFAULT	1024	/* Default gain = 1 X */
76bfced6d1SChiranjeevi Rapolu #define OV13858_DGTL_GAIN_STEP		1	/* Each step = 1/1024 */
775fcf092eSHyungwoo Yang 
785fcf092eSHyungwoo Yang /* Test Pattern Control */
795fcf092eSHyungwoo Yang #define OV13858_REG_TEST_PATTERN	0x4503
805fcf092eSHyungwoo Yang #define OV13858_TEST_PATTERN_ENABLE	BIT(7)
815fcf092eSHyungwoo Yang #define OV13858_TEST_PATTERN_MASK	0xfc
825fcf092eSHyungwoo Yang 
835fcf092eSHyungwoo Yang /* Number of frames to skip */
845fcf092eSHyungwoo Yang #define OV13858_NUM_OF_SKIP_FRAMES	2
855fcf092eSHyungwoo Yang 
865fcf092eSHyungwoo Yang struct ov13858_reg {
875fcf092eSHyungwoo Yang 	u16 address;
885fcf092eSHyungwoo Yang 	u8 val;
895fcf092eSHyungwoo Yang };
905fcf092eSHyungwoo Yang 
915fcf092eSHyungwoo Yang struct ov13858_reg_list {
925fcf092eSHyungwoo Yang 	u32 num_of_regs;
935fcf092eSHyungwoo Yang 	const struct ov13858_reg *regs;
945fcf092eSHyungwoo Yang };
955fcf092eSHyungwoo Yang 
965fcf092eSHyungwoo Yang /* Link frequency config */
975fcf092eSHyungwoo Yang struct ov13858_link_freq_config {
985fcf092eSHyungwoo Yang 	u32 pixels_per_line;
995fcf092eSHyungwoo Yang 
1005fcf092eSHyungwoo Yang 	/* PLL registers for this link frequency */
1015fcf092eSHyungwoo Yang 	struct ov13858_reg_list reg_list;
1025fcf092eSHyungwoo Yang };
1035fcf092eSHyungwoo Yang 
1045fcf092eSHyungwoo Yang /* Mode : resolution and related config&values */
1055fcf092eSHyungwoo Yang struct ov13858_mode {
1065fcf092eSHyungwoo Yang 	/* Frame width */
1075fcf092eSHyungwoo Yang 	u32 width;
1085fcf092eSHyungwoo Yang 	/* Frame height */
1095fcf092eSHyungwoo Yang 	u32 height;
1105fcf092eSHyungwoo Yang 
1115fcf092eSHyungwoo Yang 	/* V-timing */
11217fcd5f5SChiranjeevi Rapolu 	u32 vts_def;
11317fcd5f5SChiranjeevi Rapolu 	u32 vts_min;
1145fcf092eSHyungwoo Yang 
1155fcf092eSHyungwoo Yang 	/* Index of Link frequency config to be used */
1165fcf092eSHyungwoo Yang 	u32 link_freq_index;
1175fcf092eSHyungwoo Yang 	/* Default register values */
1185fcf092eSHyungwoo Yang 	struct ov13858_reg_list reg_list;
1195fcf092eSHyungwoo Yang };
1205fcf092eSHyungwoo Yang 
1215fcf092eSHyungwoo Yang /* 4224x3136 needs 1080Mbps/lane, 4 lanes */
1225fcf092eSHyungwoo Yang static const struct ov13858_reg mipi_data_rate_1080mbps[] = {
1235fcf092eSHyungwoo Yang 	/* PLL1 registers */
1245fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_0, 0x07},
1255fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_1, 0x01},
1265fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_2, 0xc2},
1275fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_3, 0x00},
1285fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_4, 0x00},
1295fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_5, 0x01},
1305fcf092eSHyungwoo Yang 
1315fcf092eSHyungwoo Yang 	/* PLL2 registers */
1325fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_B, 0x05},
1335fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_C, 0x01},
1345fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_D, 0x0e},
1355fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_E, 0x05},
1365fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_F, 0x01},
1375fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_12, 0x01},
1385fcf092eSHyungwoo Yang 	{OV13858_REG_MIPI_SC_CTRL0, 0x72},
1395fcf092eSHyungwoo Yang 	{OV13858_REG_MIPI_SC_CTRL1, 0x01},
1405fcf092eSHyungwoo Yang };
1415fcf092eSHyungwoo Yang 
1425fcf092eSHyungwoo Yang /*
1435fcf092eSHyungwoo Yang  * 2112x1568, 2112x1188, 1056x784 need 540Mbps/lane,
1445fcf092eSHyungwoo Yang  * 4 lanes
1455fcf092eSHyungwoo Yang  */
1465fcf092eSHyungwoo Yang static const struct ov13858_reg mipi_data_rate_540mbps[] = {
1475fcf092eSHyungwoo Yang 	/* PLL1 registers */
1485fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_0, 0x07},
1495fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_1, 0x01},
1505fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_2, 0xc2},
1515fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_3, 0x01},
1525fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_4, 0x00},
1535fcf092eSHyungwoo Yang 	{OV13858_REG_PLL1_CTRL_5, 0x01},
1545fcf092eSHyungwoo Yang 
1555fcf092eSHyungwoo Yang 	/* PLL2 registers */
1565fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_B, 0x05},
1575fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_C, 0x01},
1585fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_D, 0x0e},
1595fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_E, 0x05},
1605fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_F, 0x01},
1615fcf092eSHyungwoo Yang 	{OV13858_REG_PLL2_CTRL_12, 0x01},
1625fcf092eSHyungwoo Yang 	{OV13858_REG_MIPI_SC_CTRL0, 0x72},
1635fcf092eSHyungwoo Yang 	{OV13858_REG_MIPI_SC_CTRL1, 0x01},
1645fcf092eSHyungwoo Yang };
1655fcf092eSHyungwoo Yang 
1665fcf092eSHyungwoo Yang static const struct ov13858_reg mode_4224x3136_regs[] = {
1675fcf092eSHyungwoo Yang 	{0x3013, 0x32},
1685fcf092eSHyungwoo Yang 	{0x301b, 0xf0},
1695fcf092eSHyungwoo Yang 	{0x301f, 0xd0},
1705fcf092eSHyungwoo Yang 	{0x3106, 0x15},
1715fcf092eSHyungwoo Yang 	{0x3107, 0x23},
1725fcf092eSHyungwoo Yang 	{0x350a, 0x00},
1735fcf092eSHyungwoo Yang 	{0x350e, 0x00},
1745fcf092eSHyungwoo Yang 	{0x3510, 0x00},
1755fcf092eSHyungwoo Yang 	{0x3511, 0x02},
1765fcf092eSHyungwoo Yang 	{0x3512, 0x00},
1775fcf092eSHyungwoo Yang 	{0x3600, 0x2b},
1785fcf092eSHyungwoo Yang 	{0x3601, 0x52},
1795fcf092eSHyungwoo Yang 	{0x3602, 0x60},
1805fcf092eSHyungwoo Yang 	{0x3612, 0x05},
1815fcf092eSHyungwoo Yang 	{0x3613, 0xa4},
1825fcf092eSHyungwoo Yang 	{0x3620, 0x80},
1835fcf092eSHyungwoo Yang 	{0x3621, 0x10},
1845fcf092eSHyungwoo Yang 	{0x3622, 0x30},
1855fcf092eSHyungwoo Yang 	{0x3624, 0x1c},
1865fcf092eSHyungwoo Yang 	{0x3640, 0x10},
1875fcf092eSHyungwoo Yang 	{0x3641, 0x70},
188d365bc92SChiranjeevi Rapolu 	{0x3660, 0x04},
1895fcf092eSHyungwoo Yang 	{0x3661, 0x80},
1905fcf092eSHyungwoo Yang 	{0x3662, 0x12},
1915fcf092eSHyungwoo Yang 	{0x3664, 0x73},
1925fcf092eSHyungwoo Yang 	{0x3665, 0xa7},
1935fcf092eSHyungwoo Yang 	{0x366e, 0xff},
1945fcf092eSHyungwoo Yang 	{0x366f, 0xf4},
1955fcf092eSHyungwoo Yang 	{0x3674, 0x00},
1965fcf092eSHyungwoo Yang 	{0x3679, 0x0c},
1975fcf092eSHyungwoo Yang 	{0x367f, 0x01},
1985fcf092eSHyungwoo Yang 	{0x3680, 0x0c},
1995fcf092eSHyungwoo Yang 	{0x3681, 0x50},
2005fcf092eSHyungwoo Yang 	{0x3682, 0x50},
2015fcf092eSHyungwoo Yang 	{0x3683, 0xa9},
2025fcf092eSHyungwoo Yang 	{0x3684, 0xa9},
2035fcf092eSHyungwoo Yang 	{0x3709, 0x5f},
2045fcf092eSHyungwoo Yang 	{0x3714, 0x24},
2055fcf092eSHyungwoo Yang 	{0x371a, 0x3e},
2065fcf092eSHyungwoo Yang 	{0x3737, 0x04},
2075fcf092eSHyungwoo Yang 	{0x3738, 0xcc},
2085fcf092eSHyungwoo Yang 	{0x3739, 0x12},
2095fcf092eSHyungwoo Yang 	{0x373d, 0x26},
2105fcf092eSHyungwoo Yang 	{0x3764, 0x20},
2115fcf092eSHyungwoo Yang 	{0x3765, 0x20},
2125fcf092eSHyungwoo Yang 	{0x37a1, 0x36},
2135fcf092eSHyungwoo Yang 	{0x37a8, 0x3b},
2145fcf092eSHyungwoo Yang 	{0x37ab, 0x31},
2155fcf092eSHyungwoo Yang 	{0x37c2, 0x04},
2165fcf092eSHyungwoo Yang 	{0x37c3, 0xf1},
2175fcf092eSHyungwoo Yang 	{0x37c5, 0x00},
2185fcf092eSHyungwoo Yang 	{0x37d8, 0x03},
2195fcf092eSHyungwoo Yang 	{0x37d9, 0x0c},
2205fcf092eSHyungwoo Yang 	{0x37da, 0xc2},
2215fcf092eSHyungwoo Yang 	{0x37dc, 0x02},
2225fcf092eSHyungwoo Yang 	{0x37e0, 0x00},
2235fcf092eSHyungwoo Yang 	{0x37e1, 0x0a},
2245fcf092eSHyungwoo Yang 	{0x37e2, 0x14},
2255fcf092eSHyungwoo Yang 	{0x37e3, 0x04},
2265fcf092eSHyungwoo Yang 	{0x37e4, 0x2a},
2275fcf092eSHyungwoo Yang 	{0x37e5, 0x03},
2285fcf092eSHyungwoo Yang 	{0x37e6, 0x04},
2295fcf092eSHyungwoo Yang 	{0x3800, 0x00},
2305fcf092eSHyungwoo Yang 	{0x3801, 0x00},
2315fcf092eSHyungwoo Yang 	{0x3802, 0x00},
23258020c9fSChiranjeevi Rapolu 	{0x3803, 0x08},
2335fcf092eSHyungwoo Yang 	{0x3804, 0x10},
2345fcf092eSHyungwoo Yang 	{0x3805, 0x9f},
2355fcf092eSHyungwoo Yang 	{0x3806, 0x0c},
23658020c9fSChiranjeevi Rapolu 	{0x3807, 0x57},
2375fcf092eSHyungwoo Yang 	{0x3808, 0x10},
2385fcf092eSHyungwoo Yang 	{0x3809, 0x80},
2395fcf092eSHyungwoo Yang 	{0x380a, 0x0c},
2405fcf092eSHyungwoo Yang 	{0x380b, 0x40},
2415fcf092eSHyungwoo Yang 	{0x380c, 0x04},
2425fcf092eSHyungwoo Yang 	{0x380d, 0x62},
2435fcf092eSHyungwoo Yang 	{0x380e, 0x0c},
2445fcf092eSHyungwoo Yang 	{0x380f, 0x8e},
2455fcf092eSHyungwoo Yang 	{0x3811, 0x04},
2465fcf092eSHyungwoo Yang 	{0x3813, 0x05},
2475fcf092eSHyungwoo Yang 	{0x3814, 0x01},
2485fcf092eSHyungwoo Yang 	{0x3815, 0x01},
2495fcf092eSHyungwoo Yang 	{0x3816, 0x01},
2505fcf092eSHyungwoo Yang 	{0x3817, 0x01},
2515fcf092eSHyungwoo Yang 	{0x3820, 0xa8},
2525fcf092eSHyungwoo Yang 	{0x3821, 0x00},
2535fcf092eSHyungwoo Yang 	{0x3822, 0xc2},
2545fcf092eSHyungwoo Yang 	{0x3823, 0x18},
2555fcf092eSHyungwoo Yang 	{0x3826, 0x11},
2565fcf092eSHyungwoo Yang 	{0x3827, 0x1c},
2575fcf092eSHyungwoo Yang 	{0x3829, 0x03},
2585fcf092eSHyungwoo Yang 	{0x3832, 0x00},
2595fcf092eSHyungwoo Yang 	{0x3c80, 0x00},
2605fcf092eSHyungwoo Yang 	{0x3c87, 0x01},
2615fcf092eSHyungwoo Yang 	{0x3c8c, 0x19},
2625fcf092eSHyungwoo Yang 	{0x3c8d, 0x1c},
2635fcf092eSHyungwoo Yang 	{0x3c90, 0x00},
2645fcf092eSHyungwoo Yang 	{0x3c91, 0x00},
2655fcf092eSHyungwoo Yang 	{0x3c92, 0x00},
2665fcf092eSHyungwoo Yang 	{0x3c93, 0x00},
2675fcf092eSHyungwoo Yang 	{0x3c94, 0x40},
2685fcf092eSHyungwoo Yang 	{0x3c95, 0x54},
2695fcf092eSHyungwoo Yang 	{0x3c96, 0x34},
2705fcf092eSHyungwoo Yang 	{0x3c97, 0x04},
2715fcf092eSHyungwoo Yang 	{0x3c98, 0x00},
2725fcf092eSHyungwoo Yang 	{0x3d8c, 0x73},
2735fcf092eSHyungwoo Yang 	{0x3d8d, 0xc0},
2745fcf092eSHyungwoo Yang 	{0x3f00, 0x0b},
2755fcf092eSHyungwoo Yang 	{0x3f03, 0x00},
2765fcf092eSHyungwoo Yang 	{0x4001, 0xe0},
2775fcf092eSHyungwoo Yang 	{0x4008, 0x00},
2785fcf092eSHyungwoo Yang 	{0x4009, 0x0f},
2795fcf092eSHyungwoo Yang 	{0x4011, 0xf0},
2805fcf092eSHyungwoo Yang 	{0x4017, 0x08},
2815fcf092eSHyungwoo Yang 	{0x4050, 0x04},
2825fcf092eSHyungwoo Yang 	{0x4051, 0x0b},
2835fcf092eSHyungwoo Yang 	{0x4052, 0x00},
2845fcf092eSHyungwoo Yang 	{0x4053, 0x80},
2855fcf092eSHyungwoo Yang 	{0x4054, 0x00},
2865fcf092eSHyungwoo Yang 	{0x4055, 0x80},
2875fcf092eSHyungwoo Yang 	{0x4056, 0x00},
2885fcf092eSHyungwoo Yang 	{0x4057, 0x80},
2895fcf092eSHyungwoo Yang 	{0x4058, 0x00},
2905fcf092eSHyungwoo Yang 	{0x4059, 0x80},
2915fcf092eSHyungwoo Yang 	{0x405e, 0x20},
2925fcf092eSHyungwoo Yang 	{0x4500, 0x07},
2935fcf092eSHyungwoo Yang 	{0x4503, 0x00},
2945fcf092eSHyungwoo Yang 	{0x450a, 0x04},
2955fcf092eSHyungwoo Yang 	{0x4809, 0x04},
2965fcf092eSHyungwoo Yang 	{0x480c, 0x12},
2975fcf092eSHyungwoo Yang 	{0x481f, 0x30},
2985fcf092eSHyungwoo Yang 	{0x4833, 0x10},
2995fcf092eSHyungwoo Yang 	{0x4837, 0x0e},
3005fcf092eSHyungwoo Yang 	{0x4902, 0x01},
3015fcf092eSHyungwoo Yang 	{0x4d00, 0x03},
3025fcf092eSHyungwoo Yang 	{0x4d01, 0xc9},
3035fcf092eSHyungwoo Yang 	{0x4d02, 0xbc},
3045fcf092eSHyungwoo Yang 	{0x4d03, 0xd7},
3055fcf092eSHyungwoo Yang 	{0x4d04, 0xf0},
3065fcf092eSHyungwoo Yang 	{0x4d05, 0xa2},
3075fcf092eSHyungwoo Yang 	{0x5000, 0xfd},
3085fcf092eSHyungwoo Yang 	{0x5001, 0x01},
3095fcf092eSHyungwoo Yang 	{0x5040, 0x39},
3105fcf092eSHyungwoo Yang 	{0x5041, 0x10},
3115fcf092eSHyungwoo Yang 	{0x5042, 0x10},
3125fcf092eSHyungwoo Yang 	{0x5043, 0x84},
3135fcf092eSHyungwoo Yang 	{0x5044, 0x62},
3145fcf092eSHyungwoo Yang 	{0x5180, 0x00},
3155fcf092eSHyungwoo Yang 	{0x5181, 0x10},
3165fcf092eSHyungwoo Yang 	{0x5182, 0x02},
3175fcf092eSHyungwoo Yang 	{0x5183, 0x0f},
3185fcf092eSHyungwoo Yang 	{0x5200, 0x1b},
3195fcf092eSHyungwoo Yang 	{0x520b, 0x07},
3205fcf092eSHyungwoo Yang 	{0x520c, 0x0f},
3215fcf092eSHyungwoo Yang 	{0x5300, 0x04},
3225fcf092eSHyungwoo Yang 	{0x5301, 0x0c},
3235fcf092eSHyungwoo Yang 	{0x5302, 0x0c},
3245fcf092eSHyungwoo Yang 	{0x5303, 0x0f},
3255fcf092eSHyungwoo Yang 	{0x5304, 0x00},
3265fcf092eSHyungwoo Yang 	{0x5305, 0x70},
3275fcf092eSHyungwoo Yang 	{0x5306, 0x00},
3285fcf092eSHyungwoo Yang 	{0x5307, 0x80},
3295fcf092eSHyungwoo Yang 	{0x5308, 0x00},
3305fcf092eSHyungwoo Yang 	{0x5309, 0xa5},
3315fcf092eSHyungwoo Yang 	{0x530a, 0x00},
3325fcf092eSHyungwoo Yang 	{0x530b, 0xd3},
3335fcf092eSHyungwoo Yang 	{0x530c, 0x00},
3345fcf092eSHyungwoo Yang 	{0x530d, 0xf0},
3355fcf092eSHyungwoo Yang 	{0x530e, 0x01},
3365fcf092eSHyungwoo Yang 	{0x530f, 0x10},
3375fcf092eSHyungwoo Yang 	{0x5310, 0x01},
3385fcf092eSHyungwoo Yang 	{0x5311, 0x20},
3395fcf092eSHyungwoo Yang 	{0x5312, 0x01},
3405fcf092eSHyungwoo Yang 	{0x5313, 0x20},
3415fcf092eSHyungwoo Yang 	{0x5314, 0x01},
3425fcf092eSHyungwoo Yang 	{0x5315, 0x20},
3435fcf092eSHyungwoo Yang 	{0x5316, 0x08},
3445fcf092eSHyungwoo Yang 	{0x5317, 0x08},
3455fcf092eSHyungwoo Yang 	{0x5318, 0x10},
3465fcf092eSHyungwoo Yang 	{0x5319, 0x88},
3475fcf092eSHyungwoo Yang 	{0x531a, 0x88},
3485fcf092eSHyungwoo Yang 	{0x531b, 0xa9},
3495fcf092eSHyungwoo Yang 	{0x531c, 0xaa},
3505fcf092eSHyungwoo Yang 	{0x531d, 0x0a},
3515fcf092eSHyungwoo Yang 	{0x5405, 0x02},
3525fcf092eSHyungwoo Yang 	{0x5406, 0x67},
3535fcf092eSHyungwoo Yang 	{0x5407, 0x01},
3545fcf092eSHyungwoo Yang 	{0x5408, 0x4a},
3555fcf092eSHyungwoo Yang };
3565fcf092eSHyungwoo Yang 
3575fcf092eSHyungwoo Yang static const struct ov13858_reg mode_2112x1568_regs[] = {
3585fcf092eSHyungwoo Yang 	{0x3013, 0x32},
3595fcf092eSHyungwoo Yang 	{0x301b, 0xf0},
3605fcf092eSHyungwoo Yang 	{0x301f, 0xd0},
3615fcf092eSHyungwoo Yang 	{0x3106, 0x15},
3625fcf092eSHyungwoo Yang 	{0x3107, 0x23},
3635fcf092eSHyungwoo Yang 	{0x350a, 0x00},
3645fcf092eSHyungwoo Yang 	{0x350e, 0x00},
3655fcf092eSHyungwoo Yang 	{0x3510, 0x00},
3665fcf092eSHyungwoo Yang 	{0x3511, 0x02},
3675fcf092eSHyungwoo Yang 	{0x3512, 0x00},
3685fcf092eSHyungwoo Yang 	{0x3600, 0x2b},
3695fcf092eSHyungwoo Yang 	{0x3601, 0x52},
3705fcf092eSHyungwoo Yang 	{0x3602, 0x60},
3715fcf092eSHyungwoo Yang 	{0x3612, 0x05},
3725fcf092eSHyungwoo Yang 	{0x3613, 0xa4},
3735fcf092eSHyungwoo Yang 	{0x3620, 0x80},
3745fcf092eSHyungwoo Yang 	{0x3621, 0x10},
3755fcf092eSHyungwoo Yang 	{0x3622, 0x30},
3765fcf092eSHyungwoo Yang 	{0x3624, 0x1c},
3775fcf092eSHyungwoo Yang 	{0x3640, 0x10},
3785fcf092eSHyungwoo Yang 	{0x3641, 0x70},
379d365bc92SChiranjeevi Rapolu 	{0x3660, 0x04},
3805fcf092eSHyungwoo Yang 	{0x3661, 0x80},
3815fcf092eSHyungwoo Yang 	{0x3662, 0x10},
3825fcf092eSHyungwoo Yang 	{0x3664, 0x73},
3835fcf092eSHyungwoo Yang 	{0x3665, 0xa7},
3845fcf092eSHyungwoo Yang 	{0x366e, 0xff},
3855fcf092eSHyungwoo Yang 	{0x366f, 0xf4},
3865fcf092eSHyungwoo Yang 	{0x3674, 0x00},
3875fcf092eSHyungwoo Yang 	{0x3679, 0x0c},
3885fcf092eSHyungwoo Yang 	{0x367f, 0x01},
3895fcf092eSHyungwoo Yang 	{0x3680, 0x0c},
3905fcf092eSHyungwoo Yang 	{0x3681, 0x50},
3915fcf092eSHyungwoo Yang 	{0x3682, 0x50},
3925fcf092eSHyungwoo Yang 	{0x3683, 0xa9},
3935fcf092eSHyungwoo Yang 	{0x3684, 0xa9},
3945fcf092eSHyungwoo Yang 	{0x3709, 0x5f},
3955fcf092eSHyungwoo Yang 	{0x3714, 0x28},
3965fcf092eSHyungwoo Yang 	{0x371a, 0x3e},
3975fcf092eSHyungwoo Yang 	{0x3737, 0x08},
3985fcf092eSHyungwoo Yang 	{0x3738, 0xcc},
3995fcf092eSHyungwoo Yang 	{0x3739, 0x20},
4005fcf092eSHyungwoo Yang 	{0x373d, 0x26},
4015fcf092eSHyungwoo Yang 	{0x3764, 0x20},
4025fcf092eSHyungwoo Yang 	{0x3765, 0x20},
4035fcf092eSHyungwoo Yang 	{0x37a1, 0x36},
4045fcf092eSHyungwoo Yang 	{0x37a8, 0x3b},
4055fcf092eSHyungwoo Yang 	{0x37ab, 0x31},
4065fcf092eSHyungwoo Yang 	{0x37c2, 0x14},
4075fcf092eSHyungwoo Yang 	{0x37c3, 0xf1},
4085fcf092eSHyungwoo Yang 	{0x37c5, 0x00},
4095fcf092eSHyungwoo Yang 	{0x37d8, 0x03},
4105fcf092eSHyungwoo Yang 	{0x37d9, 0x0c},
4115fcf092eSHyungwoo Yang 	{0x37da, 0xc2},
4125fcf092eSHyungwoo Yang 	{0x37dc, 0x02},
4135fcf092eSHyungwoo Yang 	{0x37e0, 0x00},
4145fcf092eSHyungwoo Yang 	{0x37e1, 0x0a},
4155fcf092eSHyungwoo Yang 	{0x37e2, 0x14},
4165fcf092eSHyungwoo Yang 	{0x37e3, 0x08},
4175fcf092eSHyungwoo Yang 	{0x37e4, 0x38},
4185fcf092eSHyungwoo Yang 	{0x37e5, 0x03},
4195fcf092eSHyungwoo Yang 	{0x37e6, 0x08},
4205fcf092eSHyungwoo Yang 	{0x3800, 0x00},
4215fcf092eSHyungwoo Yang 	{0x3801, 0x00},
4225fcf092eSHyungwoo Yang 	{0x3802, 0x00},
4235fcf092eSHyungwoo Yang 	{0x3803, 0x00},
4245fcf092eSHyungwoo Yang 	{0x3804, 0x10},
4255fcf092eSHyungwoo Yang 	{0x3805, 0x9f},
4265fcf092eSHyungwoo Yang 	{0x3806, 0x0c},
4275fcf092eSHyungwoo Yang 	{0x3807, 0x5f},
4285fcf092eSHyungwoo Yang 	{0x3808, 0x08},
4295fcf092eSHyungwoo Yang 	{0x3809, 0x40},
4305fcf092eSHyungwoo Yang 	{0x380a, 0x06},
4315fcf092eSHyungwoo Yang 	{0x380b, 0x20},
4325fcf092eSHyungwoo Yang 	{0x380c, 0x04},
4335fcf092eSHyungwoo Yang 	{0x380d, 0x62},
4345fcf092eSHyungwoo Yang 	{0x380e, 0x0c},
4355fcf092eSHyungwoo Yang 	{0x380f, 0x8e},
4365fcf092eSHyungwoo Yang 	{0x3811, 0x04},
4375fcf092eSHyungwoo Yang 	{0x3813, 0x05},
4385fcf092eSHyungwoo Yang 	{0x3814, 0x03},
4395fcf092eSHyungwoo Yang 	{0x3815, 0x01},
4405fcf092eSHyungwoo Yang 	{0x3816, 0x03},
4415fcf092eSHyungwoo Yang 	{0x3817, 0x01},
4425fcf092eSHyungwoo Yang 	{0x3820, 0xab},
4435fcf092eSHyungwoo Yang 	{0x3821, 0x00},
4445fcf092eSHyungwoo Yang 	{0x3822, 0xc2},
4455fcf092eSHyungwoo Yang 	{0x3823, 0x18},
4465fcf092eSHyungwoo Yang 	{0x3826, 0x04},
4475fcf092eSHyungwoo Yang 	{0x3827, 0x90},
4485fcf092eSHyungwoo Yang 	{0x3829, 0x07},
4495fcf092eSHyungwoo Yang 	{0x3832, 0x00},
4505fcf092eSHyungwoo Yang 	{0x3c80, 0x00},
4515fcf092eSHyungwoo Yang 	{0x3c87, 0x01},
4525fcf092eSHyungwoo Yang 	{0x3c8c, 0x19},
4535fcf092eSHyungwoo Yang 	{0x3c8d, 0x1c},
4545fcf092eSHyungwoo Yang 	{0x3c90, 0x00},
4555fcf092eSHyungwoo Yang 	{0x3c91, 0x00},
4565fcf092eSHyungwoo Yang 	{0x3c92, 0x00},
4575fcf092eSHyungwoo Yang 	{0x3c93, 0x00},
4585fcf092eSHyungwoo Yang 	{0x3c94, 0x40},
4595fcf092eSHyungwoo Yang 	{0x3c95, 0x54},
4605fcf092eSHyungwoo Yang 	{0x3c96, 0x34},
4615fcf092eSHyungwoo Yang 	{0x3c97, 0x04},
4625fcf092eSHyungwoo Yang 	{0x3c98, 0x00},
4635fcf092eSHyungwoo Yang 	{0x3d8c, 0x73},
4645fcf092eSHyungwoo Yang 	{0x3d8d, 0xc0},
4655fcf092eSHyungwoo Yang 	{0x3f00, 0x0b},
4665fcf092eSHyungwoo Yang 	{0x3f03, 0x00},
4675fcf092eSHyungwoo Yang 	{0x4001, 0xe0},
4685fcf092eSHyungwoo Yang 	{0x4008, 0x00},
4695fcf092eSHyungwoo Yang 	{0x4009, 0x0d},
4705fcf092eSHyungwoo Yang 	{0x4011, 0xf0},
4715fcf092eSHyungwoo Yang 	{0x4017, 0x08},
4725fcf092eSHyungwoo Yang 	{0x4050, 0x04},
4735fcf092eSHyungwoo Yang 	{0x4051, 0x0b},
4745fcf092eSHyungwoo Yang 	{0x4052, 0x00},
4755fcf092eSHyungwoo Yang 	{0x4053, 0x80},
4765fcf092eSHyungwoo Yang 	{0x4054, 0x00},
4775fcf092eSHyungwoo Yang 	{0x4055, 0x80},
4785fcf092eSHyungwoo Yang 	{0x4056, 0x00},
4795fcf092eSHyungwoo Yang 	{0x4057, 0x80},
4805fcf092eSHyungwoo Yang 	{0x4058, 0x00},
4815fcf092eSHyungwoo Yang 	{0x4059, 0x80},
4825fcf092eSHyungwoo Yang 	{0x405e, 0x20},
4835fcf092eSHyungwoo Yang 	{0x4500, 0x07},
4845fcf092eSHyungwoo Yang 	{0x4503, 0x00},
4855fcf092eSHyungwoo Yang 	{0x450a, 0x04},
4865fcf092eSHyungwoo Yang 	{0x4809, 0x04},
4875fcf092eSHyungwoo Yang 	{0x480c, 0x12},
4885fcf092eSHyungwoo Yang 	{0x481f, 0x30},
4895fcf092eSHyungwoo Yang 	{0x4833, 0x10},
4905fcf092eSHyungwoo Yang 	{0x4837, 0x1c},
4915fcf092eSHyungwoo Yang 	{0x4902, 0x01},
4925fcf092eSHyungwoo Yang 	{0x4d00, 0x03},
4935fcf092eSHyungwoo Yang 	{0x4d01, 0xc9},
4945fcf092eSHyungwoo Yang 	{0x4d02, 0xbc},
4955fcf092eSHyungwoo Yang 	{0x4d03, 0xd7},
4965fcf092eSHyungwoo Yang 	{0x4d04, 0xf0},
4975fcf092eSHyungwoo Yang 	{0x4d05, 0xa2},
4985fcf092eSHyungwoo Yang 	{0x5000, 0xfd},
4995fcf092eSHyungwoo Yang 	{0x5001, 0x01},
5005fcf092eSHyungwoo Yang 	{0x5040, 0x39},
5015fcf092eSHyungwoo Yang 	{0x5041, 0x10},
5025fcf092eSHyungwoo Yang 	{0x5042, 0x10},
5035fcf092eSHyungwoo Yang 	{0x5043, 0x84},
5045fcf092eSHyungwoo Yang 	{0x5044, 0x62},
5055fcf092eSHyungwoo Yang 	{0x5180, 0x00},
5065fcf092eSHyungwoo Yang 	{0x5181, 0x10},
5075fcf092eSHyungwoo Yang 	{0x5182, 0x02},
5085fcf092eSHyungwoo Yang 	{0x5183, 0x0f},
5095fcf092eSHyungwoo Yang 	{0x5200, 0x1b},
5105fcf092eSHyungwoo Yang 	{0x520b, 0x07},
5115fcf092eSHyungwoo Yang 	{0x520c, 0x0f},
5125fcf092eSHyungwoo Yang 	{0x5300, 0x04},
5135fcf092eSHyungwoo Yang 	{0x5301, 0x0c},
5145fcf092eSHyungwoo Yang 	{0x5302, 0x0c},
5155fcf092eSHyungwoo Yang 	{0x5303, 0x0f},
5165fcf092eSHyungwoo Yang 	{0x5304, 0x00},
5175fcf092eSHyungwoo Yang 	{0x5305, 0x70},
5185fcf092eSHyungwoo Yang 	{0x5306, 0x00},
5195fcf092eSHyungwoo Yang 	{0x5307, 0x80},
5205fcf092eSHyungwoo Yang 	{0x5308, 0x00},
5215fcf092eSHyungwoo Yang 	{0x5309, 0xa5},
5225fcf092eSHyungwoo Yang 	{0x530a, 0x00},
5235fcf092eSHyungwoo Yang 	{0x530b, 0xd3},
5245fcf092eSHyungwoo Yang 	{0x530c, 0x00},
5255fcf092eSHyungwoo Yang 	{0x530d, 0xf0},
5265fcf092eSHyungwoo Yang 	{0x530e, 0x01},
5275fcf092eSHyungwoo Yang 	{0x530f, 0x10},
5285fcf092eSHyungwoo Yang 	{0x5310, 0x01},
5295fcf092eSHyungwoo Yang 	{0x5311, 0x20},
5305fcf092eSHyungwoo Yang 	{0x5312, 0x01},
5315fcf092eSHyungwoo Yang 	{0x5313, 0x20},
5325fcf092eSHyungwoo Yang 	{0x5314, 0x01},
5335fcf092eSHyungwoo Yang 	{0x5315, 0x20},
5345fcf092eSHyungwoo Yang 	{0x5316, 0x08},
5355fcf092eSHyungwoo Yang 	{0x5317, 0x08},
5365fcf092eSHyungwoo Yang 	{0x5318, 0x10},
5375fcf092eSHyungwoo Yang 	{0x5319, 0x88},
5385fcf092eSHyungwoo Yang 	{0x531a, 0x88},
5395fcf092eSHyungwoo Yang 	{0x531b, 0xa9},
5405fcf092eSHyungwoo Yang 	{0x531c, 0xaa},
5415fcf092eSHyungwoo Yang 	{0x531d, 0x0a},
5425fcf092eSHyungwoo Yang 	{0x5405, 0x02},
5435fcf092eSHyungwoo Yang 	{0x5406, 0x67},
5445fcf092eSHyungwoo Yang 	{0x5407, 0x01},
5455fcf092eSHyungwoo Yang 	{0x5408, 0x4a},
5465fcf092eSHyungwoo Yang };
5475fcf092eSHyungwoo Yang 
5485fcf092eSHyungwoo Yang static const struct ov13858_reg mode_2112x1188_regs[] = {
5495fcf092eSHyungwoo Yang 	{0x3013, 0x32},
5505fcf092eSHyungwoo Yang 	{0x301b, 0xf0},
5515fcf092eSHyungwoo Yang 	{0x301f, 0xd0},
5525fcf092eSHyungwoo Yang 	{0x3106, 0x15},
5535fcf092eSHyungwoo Yang 	{0x3107, 0x23},
5545fcf092eSHyungwoo Yang 	{0x350a, 0x00},
5555fcf092eSHyungwoo Yang 	{0x350e, 0x00},
5565fcf092eSHyungwoo Yang 	{0x3510, 0x00},
5575fcf092eSHyungwoo Yang 	{0x3511, 0x02},
5585fcf092eSHyungwoo Yang 	{0x3512, 0x00},
5595fcf092eSHyungwoo Yang 	{0x3600, 0x2b},
5605fcf092eSHyungwoo Yang 	{0x3601, 0x52},
5615fcf092eSHyungwoo Yang 	{0x3602, 0x60},
5625fcf092eSHyungwoo Yang 	{0x3612, 0x05},
5635fcf092eSHyungwoo Yang 	{0x3613, 0xa4},
5645fcf092eSHyungwoo Yang 	{0x3620, 0x80},
5655fcf092eSHyungwoo Yang 	{0x3621, 0x10},
5665fcf092eSHyungwoo Yang 	{0x3622, 0x30},
5675fcf092eSHyungwoo Yang 	{0x3624, 0x1c},
5685fcf092eSHyungwoo Yang 	{0x3640, 0x10},
5695fcf092eSHyungwoo Yang 	{0x3641, 0x70},
570d365bc92SChiranjeevi Rapolu 	{0x3660, 0x04},
5715fcf092eSHyungwoo Yang 	{0x3661, 0x80},
5725fcf092eSHyungwoo Yang 	{0x3662, 0x10},
5735fcf092eSHyungwoo Yang 	{0x3664, 0x73},
5745fcf092eSHyungwoo Yang 	{0x3665, 0xa7},
5755fcf092eSHyungwoo Yang 	{0x366e, 0xff},
5765fcf092eSHyungwoo Yang 	{0x366f, 0xf4},
5775fcf092eSHyungwoo Yang 	{0x3674, 0x00},
5785fcf092eSHyungwoo Yang 	{0x3679, 0x0c},
5795fcf092eSHyungwoo Yang 	{0x367f, 0x01},
5805fcf092eSHyungwoo Yang 	{0x3680, 0x0c},
5815fcf092eSHyungwoo Yang 	{0x3681, 0x50},
5825fcf092eSHyungwoo Yang 	{0x3682, 0x50},
5835fcf092eSHyungwoo Yang 	{0x3683, 0xa9},
5845fcf092eSHyungwoo Yang 	{0x3684, 0xa9},
5855fcf092eSHyungwoo Yang 	{0x3709, 0x5f},
5865fcf092eSHyungwoo Yang 	{0x3714, 0x28},
5875fcf092eSHyungwoo Yang 	{0x371a, 0x3e},
5885fcf092eSHyungwoo Yang 	{0x3737, 0x08},
5895fcf092eSHyungwoo Yang 	{0x3738, 0xcc},
5905fcf092eSHyungwoo Yang 	{0x3739, 0x20},
5915fcf092eSHyungwoo Yang 	{0x373d, 0x26},
5925fcf092eSHyungwoo Yang 	{0x3764, 0x20},
5935fcf092eSHyungwoo Yang 	{0x3765, 0x20},
5945fcf092eSHyungwoo Yang 	{0x37a1, 0x36},
5955fcf092eSHyungwoo Yang 	{0x37a8, 0x3b},
5965fcf092eSHyungwoo Yang 	{0x37ab, 0x31},
5975fcf092eSHyungwoo Yang 	{0x37c2, 0x14},
5985fcf092eSHyungwoo Yang 	{0x37c3, 0xf1},
5995fcf092eSHyungwoo Yang 	{0x37c5, 0x00},
6005fcf092eSHyungwoo Yang 	{0x37d8, 0x03},
6015fcf092eSHyungwoo Yang 	{0x37d9, 0x0c},
6025fcf092eSHyungwoo Yang 	{0x37da, 0xc2},
6035fcf092eSHyungwoo Yang 	{0x37dc, 0x02},
6045fcf092eSHyungwoo Yang 	{0x37e0, 0x00},
6055fcf092eSHyungwoo Yang 	{0x37e1, 0x0a},
6065fcf092eSHyungwoo Yang 	{0x37e2, 0x14},
6075fcf092eSHyungwoo Yang 	{0x37e3, 0x08},
6085fcf092eSHyungwoo Yang 	{0x37e4, 0x38},
6095fcf092eSHyungwoo Yang 	{0x37e5, 0x03},
6105fcf092eSHyungwoo Yang 	{0x37e6, 0x08},
6115fcf092eSHyungwoo Yang 	{0x3800, 0x00},
6125fcf092eSHyungwoo Yang 	{0x3801, 0x00},
6135fcf092eSHyungwoo Yang 	{0x3802, 0x01},
6145fcf092eSHyungwoo Yang 	{0x3803, 0x84},
6155fcf092eSHyungwoo Yang 	{0x3804, 0x10},
6165fcf092eSHyungwoo Yang 	{0x3805, 0x9f},
6175fcf092eSHyungwoo Yang 	{0x3806, 0x0a},
6185fcf092eSHyungwoo Yang 	{0x3807, 0xd3},
6195fcf092eSHyungwoo Yang 	{0x3808, 0x08},
6205fcf092eSHyungwoo Yang 	{0x3809, 0x40},
6215fcf092eSHyungwoo Yang 	{0x380a, 0x04},
6225fcf092eSHyungwoo Yang 	{0x380b, 0xa4},
6235fcf092eSHyungwoo Yang 	{0x380c, 0x04},
6245fcf092eSHyungwoo Yang 	{0x380d, 0x62},
6255fcf092eSHyungwoo Yang 	{0x380e, 0x0c},
6265fcf092eSHyungwoo Yang 	{0x380f, 0x8e},
6275fcf092eSHyungwoo Yang 	{0x3811, 0x08},
6285fcf092eSHyungwoo Yang 	{0x3813, 0x03},
6295fcf092eSHyungwoo Yang 	{0x3814, 0x03},
6305fcf092eSHyungwoo Yang 	{0x3815, 0x01},
6315fcf092eSHyungwoo Yang 	{0x3816, 0x03},
6325fcf092eSHyungwoo Yang 	{0x3817, 0x01},
6335fcf092eSHyungwoo Yang 	{0x3820, 0xab},
6345fcf092eSHyungwoo Yang 	{0x3821, 0x00},
6355fcf092eSHyungwoo Yang 	{0x3822, 0xc2},
6365fcf092eSHyungwoo Yang 	{0x3823, 0x18},
6375fcf092eSHyungwoo Yang 	{0x3826, 0x04},
6385fcf092eSHyungwoo Yang 	{0x3827, 0x90},
6395fcf092eSHyungwoo Yang 	{0x3829, 0x07},
6405fcf092eSHyungwoo Yang 	{0x3832, 0x00},
6415fcf092eSHyungwoo Yang 	{0x3c80, 0x00},
6425fcf092eSHyungwoo Yang 	{0x3c87, 0x01},
6435fcf092eSHyungwoo Yang 	{0x3c8c, 0x19},
6445fcf092eSHyungwoo Yang 	{0x3c8d, 0x1c},
6455fcf092eSHyungwoo Yang 	{0x3c90, 0x00},
6465fcf092eSHyungwoo Yang 	{0x3c91, 0x00},
6475fcf092eSHyungwoo Yang 	{0x3c92, 0x00},
6485fcf092eSHyungwoo Yang 	{0x3c93, 0x00},
6495fcf092eSHyungwoo Yang 	{0x3c94, 0x40},
6505fcf092eSHyungwoo Yang 	{0x3c95, 0x54},
6515fcf092eSHyungwoo Yang 	{0x3c96, 0x34},
6525fcf092eSHyungwoo Yang 	{0x3c97, 0x04},
6535fcf092eSHyungwoo Yang 	{0x3c98, 0x00},
6545fcf092eSHyungwoo Yang 	{0x3d8c, 0x73},
6555fcf092eSHyungwoo Yang 	{0x3d8d, 0xc0},
6565fcf092eSHyungwoo Yang 	{0x3f00, 0x0b},
6575fcf092eSHyungwoo Yang 	{0x3f03, 0x00},
6585fcf092eSHyungwoo Yang 	{0x4001, 0xe0},
6595fcf092eSHyungwoo Yang 	{0x4008, 0x00},
6605fcf092eSHyungwoo Yang 	{0x4009, 0x0d},
6615fcf092eSHyungwoo Yang 	{0x4011, 0xf0},
6625fcf092eSHyungwoo Yang 	{0x4017, 0x08},
6635fcf092eSHyungwoo Yang 	{0x4050, 0x04},
6645fcf092eSHyungwoo Yang 	{0x4051, 0x0b},
6655fcf092eSHyungwoo Yang 	{0x4052, 0x00},
6665fcf092eSHyungwoo Yang 	{0x4053, 0x80},
6675fcf092eSHyungwoo Yang 	{0x4054, 0x00},
6685fcf092eSHyungwoo Yang 	{0x4055, 0x80},
6695fcf092eSHyungwoo Yang 	{0x4056, 0x00},
6705fcf092eSHyungwoo Yang 	{0x4057, 0x80},
6715fcf092eSHyungwoo Yang 	{0x4058, 0x00},
6725fcf092eSHyungwoo Yang 	{0x4059, 0x80},
6735fcf092eSHyungwoo Yang 	{0x405e, 0x20},
6745fcf092eSHyungwoo Yang 	{0x4500, 0x07},
6755fcf092eSHyungwoo Yang 	{0x4503, 0x00},
6765fcf092eSHyungwoo Yang 	{0x450a, 0x04},
6775fcf092eSHyungwoo Yang 	{0x4809, 0x04},
6785fcf092eSHyungwoo Yang 	{0x480c, 0x12},
6795fcf092eSHyungwoo Yang 	{0x481f, 0x30},
6805fcf092eSHyungwoo Yang 	{0x4833, 0x10},
6815fcf092eSHyungwoo Yang 	{0x4837, 0x1c},
6825fcf092eSHyungwoo Yang 	{0x4902, 0x01},
6835fcf092eSHyungwoo Yang 	{0x4d00, 0x03},
6845fcf092eSHyungwoo Yang 	{0x4d01, 0xc9},
6855fcf092eSHyungwoo Yang 	{0x4d02, 0xbc},
6865fcf092eSHyungwoo Yang 	{0x4d03, 0xd7},
6875fcf092eSHyungwoo Yang 	{0x4d04, 0xf0},
6885fcf092eSHyungwoo Yang 	{0x4d05, 0xa2},
6895fcf092eSHyungwoo Yang 	{0x5000, 0xfd},
6905fcf092eSHyungwoo Yang 	{0x5001, 0x01},
6915fcf092eSHyungwoo Yang 	{0x5040, 0x39},
6925fcf092eSHyungwoo Yang 	{0x5041, 0x10},
6935fcf092eSHyungwoo Yang 	{0x5042, 0x10},
6945fcf092eSHyungwoo Yang 	{0x5043, 0x84},
6955fcf092eSHyungwoo Yang 	{0x5044, 0x62},
6965fcf092eSHyungwoo Yang 	{0x5180, 0x00},
6975fcf092eSHyungwoo Yang 	{0x5181, 0x10},
6985fcf092eSHyungwoo Yang 	{0x5182, 0x02},
6995fcf092eSHyungwoo Yang 	{0x5183, 0x0f},
7005fcf092eSHyungwoo Yang 	{0x5200, 0x1b},
7015fcf092eSHyungwoo Yang 	{0x520b, 0x07},
7025fcf092eSHyungwoo Yang 	{0x520c, 0x0f},
7035fcf092eSHyungwoo Yang 	{0x5300, 0x04},
7045fcf092eSHyungwoo Yang 	{0x5301, 0x0c},
7055fcf092eSHyungwoo Yang 	{0x5302, 0x0c},
7065fcf092eSHyungwoo Yang 	{0x5303, 0x0f},
7075fcf092eSHyungwoo Yang 	{0x5304, 0x00},
7085fcf092eSHyungwoo Yang 	{0x5305, 0x70},
7095fcf092eSHyungwoo Yang 	{0x5306, 0x00},
7105fcf092eSHyungwoo Yang 	{0x5307, 0x80},
7115fcf092eSHyungwoo Yang 	{0x5308, 0x00},
7125fcf092eSHyungwoo Yang 	{0x5309, 0xa5},
7135fcf092eSHyungwoo Yang 	{0x530a, 0x00},
7145fcf092eSHyungwoo Yang 	{0x530b, 0xd3},
7155fcf092eSHyungwoo Yang 	{0x530c, 0x00},
7165fcf092eSHyungwoo Yang 	{0x530d, 0xf0},
7175fcf092eSHyungwoo Yang 	{0x530e, 0x01},
7185fcf092eSHyungwoo Yang 	{0x530f, 0x10},
7195fcf092eSHyungwoo Yang 	{0x5310, 0x01},
7205fcf092eSHyungwoo Yang 	{0x5311, 0x20},
7215fcf092eSHyungwoo Yang 	{0x5312, 0x01},
7225fcf092eSHyungwoo Yang 	{0x5313, 0x20},
7235fcf092eSHyungwoo Yang 	{0x5314, 0x01},
7245fcf092eSHyungwoo Yang 	{0x5315, 0x20},
7255fcf092eSHyungwoo Yang 	{0x5316, 0x08},
7265fcf092eSHyungwoo Yang 	{0x5317, 0x08},
7275fcf092eSHyungwoo Yang 	{0x5318, 0x10},
7285fcf092eSHyungwoo Yang 	{0x5319, 0x88},
7295fcf092eSHyungwoo Yang 	{0x531a, 0x88},
7305fcf092eSHyungwoo Yang 	{0x531b, 0xa9},
7315fcf092eSHyungwoo Yang 	{0x531c, 0xaa},
7325fcf092eSHyungwoo Yang 	{0x531d, 0x0a},
7335fcf092eSHyungwoo Yang 	{0x5405, 0x02},
7345fcf092eSHyungwoo Yang 	{0x5406, 0x67},
7355fcf092eSHyungwoo Yang 	{0x5407, 0x01},
7365fcf092eSHyungwoo Yang 	{0x5408, 0x4a},
7375fcf092eSHyungwoo Yang };
7385fcf092eSHyungwoo Yang 
7395fcf092eSHyungwoo Yang static const struct ov13858_reg mode_1056x784_regs[] = {
7405fcf092eSHyungwoo Yang 	{0x3013, 0x32},
7415fcf092eSHyungwoo Yang 	{0x301b, 0xf0},
7425fcf092eSHyungwoo Yang 	{0x301f, 0xd0},
7435fcf092eSHyungwoo Yang 	{0x3106, 0x15},
7445fcf092eSHyungwoo Yang 	{0x3107, 0x23},
7455fcf092eSHyungwoo Yang 	{0x350a, 0x00},
7465fcf092eSHyungwoo Yang 	{0x350e, 0x00},
7475fcf092eSHyungwoo Yang 	{0x3510, 0x00},
7485fcf092eSHyungwoo Yang 	{0x3511, 0x02},
7495fcf092eSHyungwoo Yang 	{0x3512, 0x00},
7505fcf092eSHyungwoo Yang 	{0x3600, 0x2b},
7515fcf092eSHyungwoo Yang 	{0x3601, 0x52},
7525fcf092eSHyungwoo Yang 	{0x3602, 0x60},
7535fcf092eSHyungwoo Yang 	{0x3612, 0x05},
7545fcf092eSHyungwoo Yang 	{0x3613, 0xa4},
7555fcf092eSHyungwoo Yang 	{0x3620, 0x80},
7565fcf092eSHyungwoo Yang 	{0x3621, 0x10},
7575fcf092eSHyungwoo Yang 	{0x3622, 0x30},
7585fcf092eSHyungwoo Yang 	{0x3624, 0x1c},
7595fcf092eSHyungwoo Yang 	{0x3640, 0x10},
7605fcf092eSHyungwoo Yang 	{0x3641, 0x70},
761d365bc92SChiranjeevi Rapolu 	{0x3660, 0x04},
7625fcf092eSHyungwoo Yang 	{0x3661, 0x80},
7635fcf092eSHyungwoo Yang 	{0x3662, 0x08},
7645fcf092eSHyungwoo Yang 	{0x3664, 0x73},
7655fcf092eSHyungwoo Yang 	{0x3665, 0xa7},
7665fcf092eSHyungwoo Yang 	{0x366e, 0xff},
7675fcf092eSHyungwoo Yang 	{0x366f, 0xf4},
7685fcf092eSHyungwoo Yang 	{0x3674, 0x00},
7695fcf092eSHyungwoo Yang 	{0x3679, 0x0c},
7705fcf092eSHyungwoo Yang 	{0x367f, 0x01},
7715fcf092eSHyungwoo Yang 	{0x3680, 0x0c},
7725fcf092eSHyungwoo Yang 	{0x3681, 0x50},
7735fcf092eSHyungwoo Yang 	{0x3682, 0x50},
7745fcf092eSHyungwoo Yang 	{0x3683, 0xa9},
7755fcf092eSHyungwoo Yang 	{0x3684, 0xa9},
7765fcf092eSHyungwoo Yang 	{0x3709, 0x5f},
7775fcf092eSHyungwoo Yang 	{0x3714, 0x30},
7785fcf092eSHyungwoo Yang 	{0x371a, 0x3e},
7795fcf092eSHyungwoo Yang 	{0x3737, 0x08},
7805fcf092eSHyungwoo Yang 	{0x3738, 0xcc},
7815fcf092eSHyungwoo Yang 	{0x3739, 0x20},
7825fcf092eSHyungwoo Yang 	{0x373d, 0x26},
7835fcf092eSHyungwoo Yang 	{0x3764, 0x20},
7845fcf092eSHyungwoo Yang 	{0x3765, 0x20},
7855fcf092eSHyungwoo Yang 	{0x37a1, 0x36},
7865fcf092eSHyungwoo Yang 	{0x37a8, 0x3b},
7875fcf092eSHyungwoo Yang 	{0x37ab, 0x31},
7885fcf092eSHyungwoo Yang 	{0x37c2, 0x2c},
7895fcf092eSHyungwoo Yang 	{0x37c3, 0xf1},
7905fcf092eSHyungwoo Yang 	{0x37c5, 0x00},
7915fcf092eSHyungwoo Yang 	{0x37d8, 0x03},
7925fcf092eSHyungwoo Yang 	{0x37d9, 0x06},
7935fcf092eSHyungwoo Yang 	{0x37da, 0xc2},
7945fcf092eSHyungwoo Yang 	{0x37dc, 0x02},
7955fcf092eSHyungwoo Yang 	{0x37e0, 0x00},
7965fcf092eSHyungwoo Yang 	{0x37e1, 0x0a},
7975fcf092eSHyungwoo Yang 	{0x37e2, 0x14},
7985fcf092eSHyungwoo Yang 	{0x37e3, 0x08},
7995fcf092eSHyungwoo Yang 	{0x37e4, 0x36},
8005fcf092eSHyungwoo Yang 	{0x37e5, 0x03},
8015fcf092eSHyungwoo Yang 	{0x37e6, 0x08},
8025fcf092eSHyungwoo Yang 	{0x3800, 0x00},
8035fcf092eSHyungwoo Yang 	{0x3801, 0x00},
8045fcf092eSHyungwoo Yang 	{0x3802, 0x00},
8055fcf092eSHyungwoo Yang 	{0x3803, 0x00},
8065fcf092eSHyungwoo Yang 	{0x3804, 0x10},
8075fcf092eSHyungwoo Yang 	{0x3805, 0x9f},
8085fcf092eSHyungwoo Yang 	{0x3806, 0x0c},
8095fcf092eSHyungwoo Yang 	{0x3807, 0x5f},
8105fcf092eSHyungwoo Yang 	{0x3808, 0x04},
8115fcf092eSHyungwoo Yang 	{0x3809, 0x20},
8125fcf092eSHyungwoo Yang 	{0x380a, 0x03},
8135fcf092eSHyungwoo Yang 	{0x380b, 0x10},
8145fcf092eSHyungwoo Yang 	{0x380c, 0x04},
8155fcf092eSHyungwoo Yang 	{0x380d, 0x62},
8165fcf092eSHyungwoo Yang 	{0x380e, 0x0c},
8175fcf092eSHyungwoo Yang 	{0x380f, 0x8e},
8185fcf092eSHyungwoo Yang 	{0x3811, 0x04},
8195fcf092eSHyungwoo Yang 	{0x3813, 0x05},
8205fcf092eSHyungwoo Yang 	{0x3814, 0x07},
8215fcf092eSHyungwoo Yang 	{0x3815, 0x01},
8225fcf092eSHyungwoo Yang 	{0x3816, 0x07},
8235fcf092eSHyungwoo Yang 	{0x3817, 0x01},
8245fcf092eSHyungwoo Yang 	{0x3820, 0xac},
8255fcf092eSHyungwoo Yang 	{0x3821, 0x00},
8265fcf092eSHyungwoo Yang 	{0x3822, 0xc2},
8275fcf092eSHyungwoo Yang 	{0x3823, 0x18},
8285fcf092eSHyungwoo Yang 	{0x3826, 0x04},
8295fcf092eSHyungwoo Yang 	{0x3827, 0x48},
8305fcf092eSHyungwoo Yang 	{0x3829, 0x03},
8315fcf092eSHyungwoo Yang 	{0x3832, 0x00},
8325fcf092eSHyungwoo Yang 	{0x3c80, 0x00},
8335fcf092eSHyungwoo Yang 	{0x3c87, 0x01},
8345fcf092eSHyungwoo Yang 	{0x3c8c, 0x19},
8355fcf092eSHyungwoo Yang 	{0x3c8d, 0x1c},
8365fcf092eSHyungwoo Yang 	{0x3c90, 0x00},
8375fcf092eSHyungwoo Yang 	{0x3c91, 0x00},
8385fcf092eSHyungwoo Yang 	{0x3c92, 0x00},
8395fcf092eSHyungwoo Yang 	{0x3c93, 0x00},
8405fcf092eSHyungwoo Yang 	{0x3c94, 0x40},
8415fcf092eSHyungwoo Yang 	{0x3c95, 0x54},
8425fcf092eSHyungwoo Yang 	{0x3c96, 0x34},
8435fcf092eSHyungwoo Yang 	{0x3c97, 0x04},
8445fcf092eSHyungwoo Yang 	{0x3c98, 0x00},
8455fcf092eSHyungwoo Yang 	{0x3d8c, 0x73},
8465fcf092eSHyungwoo Yang 	{0x3d8d, 0xc0},
8475fcf092eSHyungwoo Yang 	{0x3f00, 0x0b},
8485fcf092eSHyungwoo Yang 	{0x3f03, 0x00},
8495fcf092eSHyungwoo Yang 	{0x4001, 0xe0},
8505fcf092eSHyungwoo Yang 	{0x4008, 0x00},
8515fcf092eSHyungwoo Yang 	{0x4009, 0x05},
8525fcf092eSHyungwoo Yang 	{0x4011, 0xf0},
8535fcf092eSHyungwoo Yang 	{0x4017, 0x08},
8545fcf092eSHyungwoo Yang 	{0x4050, 0x02},
8555fcf092eSHyungwoo Yang 	{0x4051, 0x05},
8565fcf092eSHyungwoo Yang 	{0x4052, 0x00},
8575fcf092eSHyungwoo Yang 	{0x4053, 0x80},
8585fcf092eSHyungwoo Yang 	{0x4054, 0x00},
8595fcf092eSHyungwoo Yang 	{0x4055, 0x80},
8605fcf092eSHyungwoo Yang 	{0x4056, 0x00},
8615fcf092eSHyungwoo Yang 	{0x4057, 0x80},
8625fcf092eSHyungwoo Yang 	{0x4058, 0x00},
8635fcf092eSHyungwoo Yang 	{0x4059, 0x80},
8645fcf092eSHyungwoo Yang 	{0x405e, 0x20},
8655fcf092eSHyungwoo Yang 	{0x4500, 0x07},
8665fcf092eSHyungwoo Yang 	{0x4503, 0x00},
8675fcf092eSHyungwoo Yang 	{0x450a, 0x04},
8685fcf092eSHyungwoo Yang 	{0x4809, 0x04},
8695fcf092eSHyungwoo Yang 	{0x480c, 0x12},
8705fcf092eSHyungwoo Yang 	{0x481f, 0x30},
8715fcf092eSHyungwoo Yang 	{0x4833, 0x10},
8725fcf092eSHyungwoo Yang 	{0x4837, 0x1e},
8735fcf092eSHyungwoo Yang 	{0x4902, 0x02},
8745fcf092eSHyungwoo Yang 	{0x4d00, 0x03},
8755fcf092eSHyungwoo Yang 	{0x4d01, 0xc9},
8765fcf092eSHyungwoo Yang 	{0x4d02, 0xbc},
8775fcf092eSHyungwoo Yang 	{0x4d03, 0xd7},
8785fcf092eSHyungwoo Yang 	{0x4d04, 0xf0},
8795fcf092eSHyungwoo Yang 	{0x4d05, 0xa2},
8805fcf092eSHyungwoo Yang 	{0x5000, 0xfd},
8815fcf092eSHyungwoo Yang 	{0x5001, 0x01},
8825fcf092eSHyungwoo Yang 	{0x5040, 0x39},
8835fcf092eSHyungwoo Yang 	{0x5041, 0x10},
8845fcf092eSHyungwoo Yang 	{0x5042, 0x10},
8855fcf092eSHyungwoo Yang 	{0x5043, 0x84},
8865fcf092eSHyungwoo Yang 	{0x5044, 0x62},
8875fcf092eSHyungwoo Yang 	{0x5180, 0x00},
8885fcf092eSHyungwoo Yang 	{0x5181, 0x10},
8895fcf092eSHyungwoo Yang 	{0x5182, 0x02},
8905fcf092eSHyungwoo Yang 	{0x5183, 0x0f},
8915fcf092eSHyungwoo Yang 	{0x5200, 0x1b},
8925fcf092eSHyungwoo Yang 	{0x520b, 0x07},
8935fcf092eSHyungwoo Yang 	{0x520c, 0x0f},
8945fcf092eSHyungwoo Yang 	{0x5300, 0x04},
8955fcf092eSHyungwoo Yang 	{0x5301, 0x0c},
8965fcf092eSHyungwoo Yang 	{0x5302, 0x0c},
8975fcf092eSHyungwoo Yang 	{0x5303, 0x0f},
8985fcf092eSHyungwoo Yang 	{0x5304, 0x00},
8995fcf092eSHyungwoo Yang 	{0x5305, 0x70},
9005fcf092eSHyungwoo Yang 	{0x5306, 0x00},
9015fcf092eSHyungwoo Yang 	{0x5307, 0x80},
9025fcf092eSHyungwoo Yang 	{0x5308, 0x00},
9035fcf092eSHyungwoo Yang 	{0x5309, 0xa5},
9045fcf092eSHyungwoo Yang 	{0x530a, 0x00},
9055fcf092eSHyungwoo Yang 	{0x530b, 0xd3},
9065fcf092eSHyungwoo Yang 	{0x530c, 0x00},
9075fcf092eSHyungwoo Yang 	{0x530d, 0xf0},
9085fcf092eSHyungwoo Yang 	{0x530e, 0x01},
9095fcf092eSHyungwoo Yang 	{0x530f, 0x10},
9105fcf092eSHyungwoo Yang 	{0x5310, 0x01},
9115fcf092eSHyungwoo Yang 	{0x5311, 0x20},
9125fcf092eSHyungwoo Yang 	{0x5312, 0x01},
9135fcf092eSHyungwoo Yang 	{0x5313, 0x20},
9145fcf092eSHyungwoo Yang 	{0x5314, 0x01},
9155fcf092eSHyungwoo Yang 	{0x5315, 0x20},
9165fcf092eSHyungwoo Yang 	{0x5316, 0x08},
9175fcf092eSHyungwoo Yang 	{0x5317, 0x08},
9185fcf092eSHyungwoo Yang 	{0x5318, 0x10},
9195fcf092eSHyungwoo Yang 	{0x5319, 0x88},
9205fcf092eSHyungwoo Yang 	{0x531a, 0x88},
9215fcf092eSHyungwoo Yang 	{0x531b, 0xa9},
9225fcf092eSHyungwoo Yang 	{0x531c, 0xaa},
9235fcf092eSHyungwoo Yang 	{0x531d, 0x0a},
9245fcf092eSHyungwoo Yang 	{0x5405, 0x02},
9255fcf092eSHyungwoo Yang 	{0x5406, 0x67},
9265fcf092eSHyungwoo Yang 	{0x5407, 0x01},
9275fcf092eSHyungwoo Yang 	{0x5408, 0x4a},
9285fcf092eSHyungwoo Yang };
9295fcf092eSHyungwoo Yang 
9305fcf092eSHyungwoo Yang static const char * const ov13858_test_pattern_menu[] = {
9315fcf092eSHyungwoo Yang 	"Disabled",
9325fcf092eSHyungwoo Yang 	"Vertical Color Bar Type 1",
9335fcf092eSHyungwoo Yang 	"Vertical Color Bar Type 2",
9345fcf092eSHyungwoo Yang 	"Vertical Color Bar Type 3",
9355fcf092eSHyungwoo Yang 	"Vertical Color Bar Type 4"
9365fcf092eSHyungwoo Yang };
9375fcf092eSHyungwoo Yang 
9385fcf092eSHyungwoo Yang /* Configurations for supported link frequencies */
9395fcf092eSHyungwoo Yang #define OV13858_NUM_OF_LINK_FREQS	2
94089d8b615SChiranjeevi Rapolu #define OV13858_LINK_FREQ_540MHZ	540000000ULL
94189d8b615SChiranjeevi Rapolu #define OV13858_LINK_FREQ_270MHZ	270000000ULL
9425fcf092eSHyungwoo Yang #define OV13858_LINK_FREQ_INDEX_0	0
9435fcf092eSHyungwoo Yang #define OV13858_LINK_FREQ_INDEX_1	1
9445fcf092eSHyungwoo Yang 
9456f2a0594SChiranjeevi Rapolu /*
9466f2a0594SChiranjeevi Rapolu  * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
9476f2a0594SChiranjeevi Rapolu  * data rate => double data rate; number of lanes => 4; bits per pixel => 10
9486f2a0594SChiranjeevi Rapolu  */
link_freq_to_pixel_rate(u64 f)949880d45f8SSakari Ailus static u64 link_freq_to_pixel_rate(u64 f)
950880d45f8SSakari Ailus {
951880d45f8SSakari Ailus 	f *= 2 * 4;
952880d45f8SSakari Ailus 	do_div(f, 10);
953880d45f8SSakari Ailus 
954880d45f8SSakari Ailus 	return f;
955880d45f8SSakari Ailus }
9566f2a0594SChiranjeevi Rapolu 
9575fcf092eSHyungwoo Yang /* Menu items for LINK_FREQ V4L2 control */
9583bd30b24SMauro Carvalho Chehab static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = {
95989d8b615SChiranjeevi Rapolu 	OV13858_LINK_FREQ_540MHZ,
96089d8b615SChiranjeevi Rapolu 	OV13858_LINK_FREQ_270MHZ
9615fcf092eSHyungwoo Yang };
9625fcf092eSHyungwoo Yang 
9635fcf092eSHyungwoo Yang /* Link frequency configs */
9645fcf092eSHyungwoo Yang static const struct ov13858_link_freq_config
9655fcf092eSHyungwoo Yang 			link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = {
9665fcf092eSHyungwoo Yang 	{
96789d8b615SChiranjeevi Rapolu 		.pixels_per_line = OV13858_PPL_540MHZ,
9685fcf092eSHyungwoo Yang 		.reg_list = {
9695fcf092eSHyungwoo Yang 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps),
9705fcf092eSHyungwoo Yang 			.regs = mipi_data_rate_1080mbps,
9715fcf092eSHyungwoo Yang 		}
9725fcf092eSHyungwoo Yang 	},
9735fcf092eSHyungwoo Yang 	{
97489d8b615SChiranjeevi Rapolu 		.pixels_per_line = OV13858_PPL_270MHZ,
9755fcf092eSHyungwoo Yang 		.reg_list = {
9765fcf092eSHyungwoo Yang 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps),
9775fcf092eSHyungwoo Yang 			.regs = mipi_data_rate_540mbps,
9785fcf092eSHyungwoo Yang 		}
9795fcf092eSHyungwoo Yang 	}
9805fcf092eSHyungwoo Yang };
9815fcf092eSHyungwoo Yang 
9825fcf092eSHyungwoo Yang /* Mode configs */
9835fcf092eSHyungwoo Yang static const struct ov13858_mode supported_modes[] = {
9845fcf092eSHyungwoo Yang 	{
9855fcf092eSHyungwoo Yang 		.width = 4224,
9865fcf092eSHyungwoo Yang 		.height = 3136,
98717fcd5f5SChiranjeevi Rapolu 		.vts_def = OV13858_VTS_30FPS,
98817fcd5f5SChiranjeevi Rapolu 		.vts_min = OV13858_VTS_30FPS,
9895fcf092eSHyungwoo Yang 		.reg_list = {
9905fcf092eSHyungwoo Yang 			.num_of_regs = ARRAY_SIZE(mode_4224x3136_regs),
9915fcf092eSHyungwoo Yang 			.regs = mode_4224x3136_regs,
9925fcf092eSHyungwoo Yang 		},
9935fcf092eSHyungwoo Yang 		.link_freq_index = OV13858_LINK_FREQ_INDEX_0,
9945fcf092eSHyungwoo Yang 	},
9955fcf092eSHyungwoo Yang 	{
9965fcf092eSHyungwoo Yang 		.width = 2112,
9975fcf092eSHyungwoo Yang 		.height = 1568,
99817fcd5f5SChiranjeevi Rapolu 		.vts_def = OV13858_VTS_30FPS,
99917fcd5f5SChiranjeevi Rapolu 		.vts_min = 1608,
10005fcf092eSHyungwoo Yang 		.reg_list = {
10015fcf092eSHyungwoo Yang 			.num_of_regs = ARRAY_SIZE(mode_2112x1568_regs),
10025fcf092eSHyungwoo Yang 			.regs = mode_2112x1568_regs,
10035fcf092eSHyungwoo Yang 		},
10045fcf092eSHyungwoo Yang 		.link_freq_index = OV13858_LINK_FREQ_INDEX_1,
10055fcf092eSHyungwoo Yang 	},
10065fcf092eSHyungwoo Yang 	{
10075fcf092eSHyungwoo Yang 		.width = 2112,
10085fcf092eSHyungwoo Yang 		.height = 1188,
100917fcd5f5SChiranjeevi Rapolu 		.vts_def = OV13858_VTS_30FPS,
101017fcd5f5SChiranjeevi Rapolu 		.vts_min = 1608,
10115fcf092eSHyungwoo Yang 		.reg_list = {
10125fcf092eSHyungwoo Yang 			.num_of_regs = ARRAY_SIZE(mode_2112x1188_regs),
10135fcf092eSHyungwoo Yang 			.regs = mode_2112x1188_regs,
10145fcf092eSHyungwoo Yang 		},
10155fcf092eSHyungwoo Yang 		.link_freq_index = OV13858_LINK_FREQ_INDEX_1,
10165fcf092eSHyungwoo Yang 	},
10175fcf092eSHyungwoo Yang 	{
10185fcf092eSHyungwoo Yang 		.width = 1056,
10195fcf092eSHyungwoo Yang 		.height = 784,
102017fcd5f5SChiranjeevi Rapolu 		.vts_def = OV13858_VTS_30FPS,
102117fcd5f5SChiranjeevi Rapolu 		.vts_min = 804,
10225fcf092eSHyungwoo Yang 		.reg_list = {
10235fcf092eSHyungwoo Yang 			.num_of_regs = ARRAY_SIZE(mode_1056x784_regs),
10245fcf092eSHyungwoo Yang 			.regs = mode_1056x784_regs,
10255fcf092eSHyungwoo Yang 		},
10265fcf092eSHyungwoo Yang 		.link_freq_index = OV13858_LINK_FREQ_INDEX_1,
10275fcf092eSHyungwoo Yang 	}
10285fcf092eSHyungwoo Yang };
10295fcf092eSHyungwoo Yang 
10305fcf092eSHyungwoo Yang struct ov13858 {
10315fcf092eSHyungwoo Yang 	struct v4l2_subdev sd;
10325fcf092eSHyungwoo Yang 	struct media_pad pad;
10335fcf092eSHyungwoo Yang 
10345fcf092eSHyungwoo Yang 	struct v4l2_ctrl_handler ctrl_handler;
10355fcf092eSHyungwoo Yang 	/* V4L2 Controls */
10365fcf092eSHyungwoo Yang 	struct v4l2_ctrl *link_freq;
10375fcf092eSHyungwoo Yang 	struct v4l2_ctrl *pixel_rate;
10385fcf092eSHyungwoo Yang 	struct v4l2_ctrl *vblank;
10395fcf092eSHyungwoo Yang 	struct v4l2_ctrl *hblank;
10405fcf092eSHyungwoo Yang 	struct v4l2_ctrl *exposure;
10415fcf092eSHyungwoo Yang 
10425fcf092eSHyungwoo Yang 	/* Current mode */
10435fcf092eSHyungwoo Yang 	const struct ov13858_mode *cur_mode;
10445fcf092eSHyungwoo Yang 
10455fcf092eSHyungwoo Yang 	/* Mutex for serialized access */
10465fcf092eSHyungwoo Yang 	struct mutex mutex;
10475fcf092eSHyungwoo Yang 
10485fcf092eSHyungwoo Yang 	/* Streaming on/off */
10495fcf092eSHyungwoo Yang 	bool streaming;
10505fcf092eSHyungwoo Yang };
10515fcf092eSHyungwoo Yang 
10525fcf092eSHyungwoo Yang #define to_ov13858(_sd)	container_of(_sd, struct ov13858, sd)
10535fcf092eSHyungwoo Yang 
10545fcf092eSHyungwoo Yang /* Read registers up to 4 at a time */
ov13858_read_reg(struct ov13858 * ov13858,u16 reg,u32 len,u32 * val)1055a7bc5773SMauro Carvalho Chehab static int ov13858_read_reg(struct ov13858 *ov13858, u16 reg, u32 len,
1056a7bc5773SMauro Carvalho Chehab 			    u32 *val)
10575fcf092eSHyungwoo Yang {
10585fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
10595fcf092eSHyungwoo Yang 	struct i2c_msg msgs[2];
10605fcf092eSHyungwoo Yang 	u8 *data_be_p;
10615fcf092eSHyungwoo Yang 	int ret;
1062a7bc5773SMauro Carvalho Chehab 	__be32 data_be = 0;
1063a7bc5773SMauro Carvalho Chehab 	__be16 reg_addr_be = cpu_to_be16(reg);
10645fcf092eSHyungwoo Yang 
10655fcf092eSHyungwoo Yang 	if (len > 4)
10665fcf092eSHyungwoo Yang 		return -EINVAL;
10675fcf092eSHyungwoo Yang 
10685fcf092eSHyungwoo Yang 	data_be_p = (u8 *)&data_be;
10695fcf092eSHyungwoo Yang 	/* Write register address */
10705fcf092eSHyungwoo Yang 	msgs[0].addr = client->addr;
10715fcf092eSHyungwoo Yang 	msgs[0].flags = 0;
10725fcf092eSHyungwoo Yang 	msgs[0].len = 2;
10735fcf092eSHyungwoo Yang 	msgs[0].buf = (u8 *)&reg_addr_be;
10745fcf092eSHyungwoo Yang 
10755fcf092eSHyungwoo Yang 	/* Read data from register */
10765fcf092eSHyungwoo Yang 	msgs[1].addr = client->addr;
10775fcf092eSHyungwoo Yang 	msgs[1].flags = I2C_M_RD;
10785fcf092eSHyungwoo Yang 	msgs[1].len = len;
10795fcf092eSHyungwoo Yang 	msgs[1].buf = &data_be_p[4 - len];
10805fcf092eSHyungwoo Yang 
10815fcf092eSHyungwoo Yang 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
10825fcf092eSHyungwoo Yang 	if (ret != ARRAY_SIZE(msgs))
10835fcf092eSHyungwoo Yang 		return -EIO;
10845fcf092eSHyungwoo Yang 
10855fcf092eSHyungwoo Yang 	*val = be32_to_cpu(data_be);
10865fcf092eSHyungwoo Yang 
10875fcf092eSHyungwoo Yang 	return 0;
10885fcf092eSHyungwoo Yang }
10895fcf092eSHyungwoo Yang 
10905fcf092eSHyungwoo Yang /* Write registers up to 4 at a time */
ov13858_write_reg(struct ov13858 * ov13858,u16 reg,u32 len,u32 __val)1091a7bc5773SMauro Carvalho Chehab static int ov13858_write_reg(struct ov13858 *ov13858, u16 reg, u32 len,
1092a7bc5773SMauro Carvalho Chehab 			     u32 __val)
10935fcf092eSHyungwoo Yang {
10945fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
10955fcf092eSHyungwoo Yang 	int buf_i, val_i;
10965fcf092eSHyungwoo Yang 	u8 buf[6], *val_p;
1097a7bc5773SMauro Carvalho Chehab 	__be32 val;
10985fcf092eSHyungwoo Yang 
10995fcf092eSHyungwoo Yang 	if (len > 4)
11005fcf092eSHyungwoo Yang 		return -EINVAL;
11015fcf092eSHyungwoo Yang 
11025fcf092eSHyungwoo Yang 	buf[0] = reg >> 8;
11035fcf092eSHyungwoo Yang 	buf[1] = reg & 0xff;
11045fcf092eSHyungwoo Yang 
1105a7bc5773SMauro Carvalho Chehab 	val = cpu_to_be32(__val);
11065fcf092eSHyungwoo Yang 	val_p = (u8 *)&val;
11075fcf092eSHyungwoo Yang 	buf_i = 2;
11085fcf092eSHyungwoo Yang 	val_i = 4 - len;
11095fcf092eSHyungwoo Yang 
11105fcf092eSHyungwoo Yang 	while (val_i < 4)
11115fcf092eSHyungwoo Yang 		buf[buf_i++] = val_p[val_i++];
11125fcf092eSHyungwoo Yang 
11135fcf092eSHyungwoo Yang 	if (i2c_master_send(client, buf, len + 2) != len + 2)
11145fcf092eSHyungwoo Yang 		return -EIO;
11155fcf092eSHyungwoo Yang 
11165fcf092eSHyungwoo Yang 	return 0;
11175fcf092eSHyungwoo Yang }
11185fcf092eSHyungwoo Yang 
11195fcf092eSHyungwoo Yang /* Write a list of registers */
ov13858_write_regs(struct ov13858 * ov13858,const struct ov13858_reg * regs,u32 len)11205fcf092eSHyungwoo Yang static int ov13858_write_regs(struct ov13858 *ov13858,
11215fcf092eSHyungwoo Yang 			      const struct ov13858_reg *regs, u32 len)
11225fcf092eSHyungwoo Yang {
11235fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
11245fcf092eSHyungwoo Yang 	int ret;
11255fcf092eSHyungwoo Yang 	u32 i;
11265fcf092eSHyungwoo Yang 
11275fcf092eSHyungwoo Yang 	for (i = 0; i < len; i++) {
11285fcf092eSHyungwoo Yang 		ret = ov13858_write_reg(ov13858, regs[i].address, 1,
11295fcf092eSHyungwoo Yang 					regs[i].val);
11305fcf092eSHyungwoo Yang 		if (ret) {
11315fcf092eSHyungwoo Yang 			dev_err_ratelimited(
11325fcf092eSHyungwoo Yang 				&client->dev,
11335fcf092eSHyungwoo Yang 				"Failed to write reg 0x%4.4x. error = %d\n",
11345fcf092eSHyungwoo Yang 				regs[i].address, ret);
11355fcf092eSHyungwoo Yang 
11365fcf092eSHyungwoo Yang 			return ret;
11375fcf092eSHyungwoo Yang 		}
11385fcf092eSHyungwoo Yang 	}
11395fcf092eSHyungwoo Yang 
11405fcf092eSHyungwoo Yang 	return 0;
11415fcf092eSHyungwoo Yang }
11425fcf092eSHyungwoo Yang 
ov13858_write_reg_list(struct ov13858 * ov13858,const struct ov13858_reg_list * r_list)11435fcf092eSHyungwoo Yang static int ov13858_write_reg_list(struct ov13858 *ov13858,
11445fcf092eSHyungwoo Yang 				  const struct ov13858_reg_list *r_list)
11455fcf092eSHyungwoo Yang {
11465fcf092eSHyungwoo Yang 	return ov13858_write_regs(ov13858, r_list->regs, r_list->num_of_regs);
11475fcf092eSHyungwoo Yang }
11485fcf092eSHyungwoo Yang 
11495fcf092eSHyungwoo Yang /* Open sub-device */
ov13858_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)11505fcf092eSHyungwoo Yang static int ov13858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
11515fcf092eSHyungwoo Yang {
11525fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
11535fcf092eSHyungwoo Yang 	struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(sd,
11540d346d2aSTomi Valkeinen 									fh->state,
11555fcf092eSHyungwoo Yang 									0);
11565fcf092eSHyungwoo Yang 
11575fcf092eSHyungwoo Yang 	mutex_lock(&ov13858->mutex);
11585fcf092eSHyungwoo Yang 
11595fcf092eSHyungwoo Yang 	/* Initialize try_fmt */
11605fcf092eSHyungwoo Yang 	try_fmt->width = ov13858->cur_mode->width;
11615fcf092eSHyungwoo Yang 	try_fmt->height = ov13858->cur_mode->height;
11625fcf092eSHyungwoo Yang 	try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
11635fcf092eSHyungwoo Yang 	try_fmt->field = V4L2_FIELD_NONE;
11645fcf092eSHyungwoo Yang 
11655fcf092eSHyungwoo Yang 	/* No crop or compose */
11665fcf092eSHyungwoo Yang 	mutex_unlock(&ov13858->mutex);
11675fcf092eSHyungwoo Yang 
11685fcf092eSHyungwoo Yang 	return 0;
11695fcf092eSHyungwoo Yang }
11705fcf092eSHyungwoo Yang 
ov13858_update_digital_gain(struct ov13858 * ov13858,u32 d_gain)11715fcf092eSHyungwoo Yang static int ov13858_update_digital_gain(struct ov13858 *ov13858, u32 d_gain)
11725fcf092eSHyungwoo Yang {
11735fcf092eSHyungwoo Yang 	int ret;
11745fcf092eSHyungwoo Yang 
1175bfced6d1SChiranjeevi Rapolu 	ret = ov13858_write_reg(ov13858, OV13858_REG_B_MWB_GAIN,
1176bfced6d1SChiranjeevi Rapolu 				OV13858_REG_VALUE_16BIT, d_gain);
11775fcf092eSHyungwoo Yang 	if (ret)
11785fcf092eSHyungwoo Yang 		return ret;
11795fcf092eSHyungwoo Yang 
1180bfced6d1SChiranjeevi Rapolu 	ret = ov13858_write_reg(ov13858, OV13858_REG_G_MWB_GAIN,
1181bfced6d1SChiranjeevi Rapolu 				OV13858_REG_VALUE_16BIT, d_gain);
1182bfced6d1SChiranjeevi Rapolu 	if (ret)
1183bfced6d1SChiranjeevi Rapolu 		return ret;
11845fcf092eSHyungwoo Yang 
1185bfced6d1SChiranjeevi Rapolu 	ret = ov13858_write_reg(ov13858, OV13858_REG_R_MWB_GAIN,
1186bfced6d1SChiranjeevi Rapolu 				OV13858_REG_VALUE_16BIT, d_gain);
1187bfced6d1SChiranjeevi Rapolu 
1188bfced6d1SChiranjeevi Rapolu 	return ret;
11895fcf092eSHyungwoo Yang }
11905fcf092eSHyungwoo Yang 
ov13858_enable_test_pattern(struct ov13858 * ov13858,u32 pattern)11915fcf092eSHyungwoo Yang static int ov13858_enable_test_pattern(struct ov13858 *ov13858, u32 pattern)
11925fcf092eSHyungwoo Yang {
11935fcf092eSHyungwoo Yang 	int ret;
11945fcf092eSHyungwoo Yang 	u32 val;
11955fcf092eSHyungwoo Yang 
11965fcf092eSHyungwoo Yang 	ret = ov13858_read_reg(ov13858, OV13858_REG_TEST_PATTERN,
11975fcf092eSHyungwoo Yang 			       OV13858_REG_VALUE_08BIT, &val);
11985fcf092eSHyungwoo Yang 	if (ret)
11995fcf092eSHyungwoo Yang 		return ret;
12005fcf092eSHyungwoo Yang 
12015fcf092eSHyungwoo Yang 	if (pattern) {
12025fcf092eSHyungwoo Yang 		val &= OV13858_TEST_PATTERN_MASK;
12035fcf092eSHyungwoo Yang 		val |= (pattern - 1) | OV13858_TEST_PATTERN_ENABLE;
12045fcf092eSHyungwoo Yang 	} else {
12055fcf092eSHyungwoo Yang 		val &= ~OV13858_TEST_PATTERN_ENABLE;
12065fcf092eSHyungwoo Yang 	}
12075fcf092eSHyungwoo Yang 
12085fcf092eSHyungwoo Yang 	return ov13858_write_reg(ov13858, OV13858_REG_TEST_PATTERN,
12095fcf092eSHyungwoo Yang 				 OV13858_REG_VALUE_08BIT, val);
12105fcf092eSHyungwoo Yang }
12115fcf092eSHyungwoo Yang 
ov13858_set_ctrl(struct v4l2_ctrl * ctrl)12125fcf092eSHyungwoo Yang static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl)
12135fcf092eSHyungwoo Yang {
12145fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = container_of(ctrl->handler,
12155fcf092eSHyungwoo Yang 					       struct ov13858, ctrl_handler);
12165fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
12175fcf092eSHyungwoo Yang 	s64 max;
12185fcf092eSHyungwoo Yang 	int ret;
12195fcf092eSHyungwoo Yang 
12205fcf092eSHyungwoo Yang 	/* Propagate change of current control to all related controls */
12215fcf092eSHyungwoo Yang 	switch (ctrl->id) {
12225fcf092eSHyungwoo Yang 	case V4L2_CID_VBLANK:
12235fcf092eSHyungwoo Yang 		/* Update max exposure while meeting expected vblanking */
12245fcf092eSHyungwoo Yang 		max = ov13858->cur_mode->height + ctrl->val - 8;
12255fcf092eSHyungwoo Yang 		__v4l2_ctrl_modify_range(ov13858->exposure,
12265fcf092eSHyungwoo Yang 					 ov13858->exposure->minimum,
12275fcf092eSHyungwoo Yang 					 max, ov13858->exposure->step, max);
12285fcf092eSHyungwoo Yang 		break;
122926092e7eSShobhit Kukreti 	}
12305fcf092eSHyungwoo Yang 
12315fcf092eSHyungwoo Yang 	/*
12325fcf092eSHyungwoo Yang 	 * Applying V4L2 control value only happens
12335fcf092eSHyungwoo Yang 	 * when power is up for streaming
12345fcf092eSHyungwoo Yang 	 */
12354d471563SSakari Ailus 	if (!pm_runtime_get_if_in_use(&client->dev))
12365fcf092eSHyungwoo Yang 		return 0;
12375fcf092eSHyungwoo Yang 
12385fcf092eSHyungwoo Yang 	ret = 0;
12395fcf092eSHyungwoo Yang 	switch (ctrl->id) {
12405fcf092eSHyungwoo Yang 	case V4L2_CID_ANALOGUE_GAIN:
12415fcf092eSHyungwoo Yang 		ret = ov13858_write_reg(ov13858, OV13858_REG_ANALOG_GAIN,
12425fcf092eSHyungwoo Yang 					OV13858_REG_VALUE_16BIT, ctrl->val);
12435fcf092eSHyungwoo Yang 		break;
12445fcf092eSHyungwoo Yang 	case V4L2_CID_DIGITAL_GAIN:
12455fcf092eSHyungwoo Yang 		ret = ov13858_update_digital_gain(ov13858, ctrl->val);
12465fcf092eSHyungwoo Yang 		break;
12475fcf092eSHyungwoo Yang 	case V4L2_CID_EXPOSURE:
12485fcf092eSHyungwoo Yang 		ret = ov13858_write_reg(ov13858, OV13858_REG_EXPOSURE,
12495fcf092eSHyungwoo Yang 					OV13858_REG_VALUE_24BIT,
12505fcf092eSHyungwoo Yang 					ctrl->val << 4);
12515fcf092eSHyungwoo Yang 		break;
12525fcf092eSHyungwoo Yang 	case V4L2_CID_VBLANK:
12535fcf092eSHyungwoo Yang 		/* Update VTS that meets expected vertical blanking */
12545fcf092eSHyungwoo Yang 		ret = ov13858_write_reg(ov13858, OV13858_REG_VTS,
12555fcf092eSHyungwoo Yang 					OV13858_REG_VALUE_16BIT,
12565fcf092eSHyungwoo Yang 					ov13858->cur_mode->height
12575fcf092eSHyungwoo Yang 					  + ctrl->val);
12585fcf092eSHyungwoo Yang 		break;
12595fcf092eSHyungwoo Yang 	case V4L2_CID_TEST_PATTERN:
12605fcf092eSHyungwoo Yang 		ret = ov13858_enable_test_pattern(ov13858, ctrl->val);
12615fcf092eSHyungwoo Yang 		break;
12625fcf092eSHyungwoo Yang 	default:
12635fcf092eSHyungwoo Yang 		dev_info(&client->dev,
12645fcf092eSHyungwoo Yang 			 "ctrl(id:0x%x,val:0x%x) is not handled\n",
12655fcf092eSHyungwoo Yang 			 ctrl->id, ctrl->val);
12665fcf092eSHyungwoo Yang 		break;
126726092e7eSShobhit Kukreti 	}
12685fcf092eSHyungwoo Yang 
12695fcf092eSHyungwoo Yang 	pm_runtime_put(&client->dev);
12705fcf092eSHyungwoo Yang 
12715fcf092eSHyungwoo Yang 	return ret;
12725fcf092eSHyungwoo Yang }
12735fcf092eSHyungwoo Yang 
12745fcf092eSHyungwoo Yang static const struct v4l2_ctrl_ops ov13858_ctrl_ops = {
12755fcf092eSHyungwoo Yang 	.s_ctrl = ov13858_set_ctrl,
12765fcf092eSHyungwoo Yang };
12775fcf092eSHyungwoo Yang 
ov13858_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)12785fcf092eSHyungwoo Yang static int ov13858_enum_mbus_code(struct v4l2_subdev *sd,
12790d346d2aSTomi Valkeinen 				  struct v4l2_subdev_state *sd_state,
12805fcf092eSHyungwoo Yang 				  struct v4l2_subdev_mbus_code_enum *code)
12815fcf092eSHyungwoo Yang {
12825fcf092eSHyungwoo Yang 	/* Only one bayer order(GRBG) is supported */
12835fcf092eSHyungwoo Yang 	if (code->index > 0)
12845fcf092eSHyungwoo Yang 		return -EINVAL;
12855fcf092eSHyungwoo Yang 
12865fcf092eSHyungwoo Yang 	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
12875fcf092eSHyungwoo Yang 
12885fcf092eSHyungwoo Yang 	return 0;
12895fcf092eSHyungwoo Yang }
12905fcf092eSHyungwoo Yang 
ov13858_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)12915fcf092eSHyungwoo Yang static int ov13858_enum_frame_size(struct v4l2_subdev *sd,
12920d346d2aSTomi Valkeinen 				   struct v4l2_subdev_state *sd_state,
12935fcf092eSHyungwoo Yang 				   struct v4l2_subdev_frame_size_enum *fse)
12945fcf092eSHyungwoo Yang {
12955fcf092eSHyungwoo Yang 	if (fse->index >= ARRAY_SIZE(supported_modes))
12965fcf092eSHyungwoo Yang 		return -EINVAL;
12975fcf092eSHyungwoo Yang 
12985fcf092eSHyungwoo Yang 	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
12995fcf092eSHyungwoo Yang 		return -EINVAL;
13005fcf092eSHyungwoo Yang 
13015fcf092eSHyungwoo Yang 	fse->min_width = supported_modes[fse->index].width;
13025fcf092eSHyungwoo Yang 	fse->max_width = fse->min_width;
13035fcf092eSHyungwoo Yang 	fse->min_height = supported_modes[fse->index].height;
13045fcf092eSHyungwoo Yang 	fse->max_height = fse->min_height;
13055fcf092eSHyungwoo Yang 
13065fcf092eSHyungwoo Yang 	return 0;
13075fcf092eSHyungwoo Yang }
13085fcf092eSHyungwoo Yang 
ov13858_update_pad_format(const struct ov13858_mode * mode,struct v4l2_subdev_format * fmt)13095fcf092eSHyungwoo Yang static void ov13858_update_pad_format(const struct ov13858_mode *mode,
13105fcf092eSHyungwoo Yang 				      struct v4l2_subdev_format *fmt)
13115fcf092eSHyungwoo Yang {
13125fcf092eSHyungwoo Yang 	fmt->format.width = mode->width;
13135fcf092eSHyungwoo Yang 	fmt->format.height = mode->height;
13145fcf092eSHyungwoo Yang 	fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
13155fcf092eSHyungwoo Yang 	fmt->format.field = V4L2_FIELD_NONE;
13165fcf092eSHyungwoo Yang }
13175fcf092eSHyungwoo Yang 
ov13858_do_get_pad_format(struct ov13858 * ov13858,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)13185fcf092eSHyungwoo Yang static int ov13858_do_get_pad_format(struct ov13858 *ov13858,
13190d346d2aSTomi Valkeinen 				     struct v4l2_subdev_state *sd_state,
13205fcf092eSHyungwoo Yang 				     struct v4l2_subdev_format *fmt)
13215fcf092eSHyungwoo Yang {
13225fcf092eSHyungwoo Yang 	struct v4l2_mbus_framefmt *framefmt;
13235fcf092eSHyungwoo Yang 	struct v4l2_subdev *sd = &ov13858->sd;
13245fcf092eSHyungwoo Yang 
13255fcf092eSHyungwoo Yang 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
13260d346d2aSTomi Valkeinen 		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
13275fcf092eSHyungwoo Yang 		fmt->format = *framefmt;
13285fcf092eSHyungwoo Yang 	} else {
13295fcf092eSHyungwoo Yang 		ov13858_update_pad_format(ov13858->cur_mode, fmt);
13305fcf092eSHyungwoo Yang 	}
13315fcf092eSHyungwoo Yang 
13325fcf092eSHyungwoo Yang 	return 0;
13335fcf092eSHyungwoo Yang }
13345fcf092eSHyungwoo Yang 
ov13858_get_pad_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)13355fcf092eSHyungwoo Yang static int ov13858_get_pad_format(struct v4l2_subdev *sd,
13360d346d2aSTomi Valkeinen 				  struct v4l2_subdev_state *sd_state,
13375fcf092eSHyungwoo Yang 				  struct v4l2_subdev_format *fmt)
13385fcf092eSHyungwoo Yang {
13395fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
13405fcf092eSHyungwoo Yang 	int ret;
13415fcf092eSHyungwoo Yang 
13425fcf092eSHyungwoo Yang 	mutex_lock(&ov13858->mutex);
13430d346d2aSTomi Valkeinen 	ret = ov13858_do_get_pad_format(ov13858, sd_state, fmt);
13445fcf092eSHyungwoo Yang 	mutex_unlock(&ov13858->mutex);
13455fcf092eSHyungwoo Yang 
13465fcf092eSHyungwoo Yang 	return ret;
13475fcf092eSHyungwoo Yang }
13485fcf092eSHyungwoo Yang 
13495fcf092eSHyungwoo Yang static int
ov13858_set_pad_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)13505fcf092eSHyungwoo Yang ov13858_set_pad_format(struct v4l2_subdev *sd,
13510d346d2aSTomi Valkeinen 		       struct v4l2_subdev_state *sd_state,
13525fcf092eSHyungwoo Yang 		       struct v4l2_subdev_format *fmt)
13535fcf092eSHyungwoo Yang {
13545fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
13555fcf092eSHyungwoo Yang 	const struct ov13858_mode *mode;
13565fcf092eSHyungwoo Yang 	struct v4l2_mbus_framefmt *framefmt;
1357b3775edcSChiranjeevi Rapolu 	s32 vblank_def;
135817fcd5f5SChiranjeevi Rapolu 	s32 vblank_min;
13595fcf092eSHyungwoo Yang 	s64 h_blank;
13606f2a0594SChiranjeevi Rapolu 	s64 pixel_rate;
13616f2a0594SChiranjeevi Rapolu 	s64 link_freq;
13625fcf092eSHyungwoo Yang 
13635fcf092eSHyungwoo Yang 	mutex_lock(&ov13858->mutex);
13645fcf092eSHyungwoo Yang 
13655fcf092eSHyungwoo Yang 	/* Only one raw bayer(GRBG) order is supported */
13665fcf092eSHyungwoo Yang 	if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10)
13675fcf092eSHyungwoo Yang 		fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
13685fcf092eSHyungwoo Yang 
1369d2dc57b1SSakari Ailus 	mode = v4l2_find_nearest_size(supported_modes,
1370d2dc57b1SSakari Ailus 				      ARRAY_SIZE(supported_modes),
1371d2dc57b1SSakari Ailus 				      width, height,
1372227b183dSSakari Ailus 				      fmt->format.width, fmt->format.height);
13735fcf092eSHyungwoo Yang 	ov13858_update_pad_format(mode, fmt);
13745fcf092eSHyungwoo Yang 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
13750d346d2aSTomi Valkeinen 		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
13765fcf092eSHyungwoo Yang 		*framefmt = fmt->format;
13775fcf092eSHyungwoo Yang 	} else {
13785fcf092eSHyungwoo Yang 		ov13858->cur_mode = mode;
13795fcf092eSHyungwoo Yang 		__v4l2_ctrl_s_ctrl(ov13858->link_freq, mode->link_freq_index);
13806f2a0594SChiranjeevi Rapolu 		link_freq = link_freq_menu_items[mode->link_freq_index];
1381880d45f8SSakari Ailus 		pixel_rate = link_freq_to_pixel_rate(link_freq);
13826f2a0594SChiranjeevi Rapolu 		__v4l2_ctrl_s_ctrl_int64(ov13858->pixel_rate, pixel_rate);
13836f2a0594SChiranjeevi Rapolu 
13845fcf092eSHyungwoo Yang 		/* Update limits and set FPS to default */
138517fcd5f5SChiranjeevi Rapolu 		vblank_def = ov13858->cur_mode->vts_def -
138617fcd5f5SChiranjeevi Rapolu 			     ov13858->cur_mode->height;
138717fcd5f5SChiranjeevi Rapolu 		vblank_min = ov13858->cur_mode->vts_min -
138817fcd5f5SChiranjeevi Rapolu 			     ov13858->cur_mode->height;
13895fcf092eSHyungwoo Yang 		__v4l2_ctrl_modify_range(
139017fcd5f5SChiranjeevi Rapolu 			ov13858->vblank, vblank_min,
13915fcf092eSHyungwoo Yang 			OV13858_VTS_MAX - ov13858->cur_mode->height, 1,
1392b3775edcSChiranjeevi Rapolu 			vblank_def);
1393b3775edcSChiranjeevi Rapolu 		__v4l2_ctrl_s_ctrl(ov13858->vblank, vblank_def);
13945fcf092eSHyungwoo Yang 		h_blank =
13955fcf092eSHyungwoo Yang 			link_freq_configs[mode->link_freq_index].pixels_per_line
13965fcf092eSHyungwoo Yang 			 - ov13858->cur_mode->width;
13975fcf092eSHyungwoo Yang 		__v4l2_ctrl_modify_range(ov13858->hblank, h_blank,
13985fcf092eSHyungwoo Yang 					 h_blank, 1, h_blank);
13995fcf092eSHyungwoo Yang 	}
14005fcf092eSHyungwoo Yang 
14015fcf092eSHyungwoo Yang 	mutex_unlock(&ov13858->mutex);
14025fcf092eSHyungwoo Yang 
14035fcf092eSHyungwoo Yang 	return 0;
14045fcf092eSHyungwoo Yang }
14055fcf092eSHyungwoo Yang 
ov13858_get_skip_frames(struct v4l2_subdev * sd,u32 * frames)14065fcf092eSHyungwoo Yang static int ov13858_get_skip_frames(struct v4l2_subdev *sd, u32 *frames)
14075fcf092eSHyungwoo Yang {
14085fcf092eSHyungwoo Yang 	*frames = OV13858_NUM_OF_SKIP_FRAMES;
14095fcf092eSHyungwoo Yang 
14105fcf092eSHyungwoo Yang 	return 0;
14115fcf092eSHyungwoo Yang }
14125fcf092eSHyungwoo Yang 
14135fcf092eSHyungwoo Yang /* Start streaming */
ov13858_start_streaming(struct ov13858 * ov13858)14145fcf092eSHyungwoo Yang static int ov13858_start_streaming(struct ov13858 *ov13858)
14155fcf092eSHyungwoo Yang {
14165fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
14175fcf092eSHyungwoo Yang 	const struct ov13858_reg_list *reg_list;
14185fcf092eSHyungwoo Yang 	int ret, link_freq_index;
14195fcf092eSHyungwoo Yang 
14205fcf092eSHyungwoo Yang 	/* Get out of from software reset */
14215fcf092eSHyungwoo Yang 	ret = ov13858_write_reg(ov13858, OV13858_REG_SOFTWARE_RST,
14225fcf092eSHyungwoo Yang 				OV13858_REG_VALUE_08BIT, OV13858_SOFTWARE_RST);
14235fcf092eSHyungwoo Yang 	if (ret) {
14245fcf092eSHyungwoo Yang 		dev_err(&client->dev, "%s failed to set powerup registers\n",
14255fcf092eSHyungwoo Yang 			__func__);
14265fcf092eSHyungwoo Yang 		return ret;
14275fcf092eSHyungwoo Yang 	}
14285fcf092eSHyungwoo Yang 
14295fcf092eSHyungwoo Yang 	/* Setup PLL */
14305fcf092eSHyungwoo Yang 	link_freq_index = ov13858->cur_mode->link_freq_index;
14315fcf092eSHyungwoo Yang 	reg_list = &link_freq_configs[link_freq_index].reg_list;
14325fcf092eSHyungwoo Yang 	ret = ov13858_write_reg_list(ov13858, reg_list);
14335fcf092eSHyungwoo Yang 	if (ret) {
14345fcf092eSHyungwoo Yang 		dev_err(&client->dev, "%s failed to set plls\n", __func__);
14355fcf092eSHyungwoo Yang 		return ret;
14365fcf092eSHyungwoo Yang 	}
14375fcf092eSHyungwoo Yang 
14385fcf092eSHyungwoo Yang 	/* Apply default values of current mode */
14395fcf092eSHyungwoo Yang 	reg_list = &ov13858->cur_mode->reg_list;
14405fcf092eSHyungwoo Yang 	ret = ov13858_write_reg_list(ov13858, reg_list);
14415fcf092eSHyungwoo Yang 	if (ret) {
14425fcf092eSHyungwoo Yang 		dev_err(&client->dev, "%s failed to set mode\n", __func__);
14435fcf092eSHyungwoo Yang 		return ret;
14445fcf092eSHyungwoo Yang 	}
14455fcf092eSHyungwoo Yang 
14465fcf092eSHyungwoo Yang 	/* Apply customized values from user */
14475fcf092eSHyungwoo Yang 	ret =  __v4l2_ctrl_handler_setup(ov13858->sd.ctrl_handler);
14485fcf092eSHyungwoo Yang 	if (ret)
14495fcf092eSHyungwoo Yang 		return ret;
14505fcf092eSHyungwoo Yang 
14515fcf092eSHyungwoo Yang 	return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT,
14525fcf092eSHyungwoo Yang 				 OV13858_REG_VALUE_08BIT,
14535fcf092eSHyungwoo Yang 				 OV13858_MODE_STREAMING);
14545fcf092eSHyungwoo Yang }
14555fcf092eSHyungwoo Yang 
14565fcf092eSHyungwoo Yang /* Stop streaming */
ov13858_stop_streaming(struct ov13858 * ov13858)14575fcf092eSHyungwoo Yang static int ov13858_stop_streaming(struct ov13858 *ov13858)
14585fcf092eSHyungwoo Yang {
14595fcf092eSHyungwoo Yang 	return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT,
14605fcf092eSHyungwoo Yang 				 OV13858_REG_VALUE_08BIT, OV13858_MODE_STANDBY);
14615fcf092eSHyungwoo Yang }
14625fcf092eSHyungwoo Yang 
ov13858_set_stream(struct v4l2_subdev * sd,int enable)14635fcf092eSHyungwoo Yang static int ov13858_set_stream(struct v4l2_subdev *sd, int enable)
14645fcf092eSHyungwoo Yang {
14655fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
14665fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(sd);
14675fcf092eSHyungwoo Yang 	int ret = 0;
14685fcf092eSHyungwoo Yang 
14695fcf092eSHyungwoo Yang 	mutex_lock(&ov13858->mutex);
14705fcf092eSHyungwoo Yang 	if (ov13858->streaming == enable) {
14715fcf092eSHyungwoo Yang 		mutex_unlock(&ov13858->mutex);
14725fcf092eSHyungwoo Yang 		return 0;
14735fcf092eSHyungwoo Yang 	}
14745fcf092eSHyungwoo Yang 
14755fcf092eSHyungwoo Yang 	if (enable) {
1476cc9351ffSMauro Carvalho Chehab 		ret = pm_runtime_resume_and_get(&client->dev);
1477cc9351ffSMauro Carvalho Chehab 		if (ret < 0)
14785fcf092eSHyungwoo Yang 			goto err_unlock;
14795fcf092eSHyungwoo Yang 
14805fcf092eSHyungwoo Yang 		/*
14815fcf092eSHyungwoo Yang 		 * Apply default & customized values
14825fcf092eSHyungwoo Yang 		 * and then start streaming.
14835fcf092eSHyungwoo Yang 		 */
14845fcf092eSHyungwoo Yang 		ret = ov13858_start_streaming(ov13858);
14855fcf092eSHyungwoo Yang 		if (ret)
14865fcf092eSHyungwoo Yang 			goto err_rpm_put;
14875fcf092eSHyungwoo Yang 	} else {
14885fcf092eSHyungwoo Yang 		ov13858_stop_streaming(ov13858);
14895fcf092eSHyungwoo Yang 		pm_runtime_put(&client->dev);
14905fcf092eSHyungwoo Yang 	}
14915fcf092eSHyungwoo Yang 
14925fcf092eSHyungwoo Yang 	ov13858->streaming = enable;
14935fcf092eSHyungwoo Yang 	mutex_unlock(&ov13858->mutex);
14945fcf092eSHyungwoo Yang 
14955fcf092eSHyungwoo Yang 	return ret;
14965fcf092eSHyungwoo Yang 
14975fcf092eSHyungwoo Yang err_rpm_put:
14985fcf092eSHyungwoo Yang 	pm_runtime_put(&client->dev);
14995fcf092eSHyungwoo Yang err_unlock:
15005fcf092eSHyungwoo Yang 	mutex_unlock(&ov13858->mutex);
15015fcf092eSHyungwoo Yang 
15025fcf092eSHyungwoo Yang 	return ret;
15035fcf092eSHyungwoo Yang }
15045fcf092eSHyungwoo Yang 
ov13858_suspend(struct device * dev)15055fcf092eSHyungwoo Yang static int __maybe_unused ov13858_suspend(struct device *dev)
15065fcf092eSHyungwoo Yang {
150700dd015dSKrzysztof Kozlowski 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
15085fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
15095fcf092eSHyungwoo Yang 
15105fcf092eSHyungwoo Yang 	if (ov13858->streaming)
15115fcf092eSHyungwoo Yang 		ov13858_stop_streaming(ov13858);
15125fcf092eSHyungwoo Yang 
15135fcf092eSHyungwoo Yang 	return 0;
15145fcf092eSHyungwoo Yang }
15155fcf092eSHyungwoo Yang 
ov13858_resume(struct device * dev)15165fcf092eSHyungwoo Yang static int __maybe_unused ov13858_resume(struct device *dev)
15175fcf092eSHyungwoo Yang {
151800dd015dSKrzysztof Kozlowski 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
15195fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
15205fcf092eSHyungwoo Yang 	int ret;
15215fcf092eSHyungwoo Yang 
15225fcf092eSHyungwoo Yang 	if (ov13858->streaming) {
15235fcf092eSHyungwoo Yang 		ret = ov13858_start_streaming(ov13858);
15245fcf092eSHyungwoo Yang 		if (ret)
15255fcf092eSHyungwoo Yang 			goto error;
15265fcf092eSHyungwoo Yang 	}
15275fcf092eSHyungwoo Yang 
15285fcf092eSHyungwoo Yang 	return 0;
15295fcf092eSHyungwoo Yang 
15305fcf092eSHyungwoo Yang error:
15315fcf092eSHyungwoo Yang 	ov13858_stop_streaming(ov13858);
1532f4b32c29SGustavo A. R. Silva 	ov13858->streaming = false;
15335fcf092eSHyungwoo Yang 	return ret;
15345fcf092eSHyungwoo Yang }
15355fcf092eSHyungwoo Yang 
15365fcf092eSHyungwoo Yang /* Verify chip ID */
ov13858_identify_module(struct ov13858 * ov13858)15375fcf092eSHyungwoo Yang static int ov13858_identify_module(struct ov13858 *ov13858)
15385fcf092eSHyungwoo Yang {
15395fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
15405fcf092eSHyungwoo Yang 	int ret;
15415fcf092eSHyungwoo Yang 	u32 val;
15425fcf092eSHyungwoo Yang 
15435fcf092eSHyungwoo Yang 	ret = ov13858_read_reg(ov13858, OV13858_REG_CHIP_ID,
15445fcf092eSHyungwoo Yang 			       OV13858_REG_VALUE_24BIT, &val);
15455fcf092eSHyungwoo Yang 	if (ret)
15465fcf092eSHyungwoo Yang 		return ret;
15475fcf092eSHyungwoo Yang 
15485fcf092eSHyungwoo Yang 	if (val != OV13858_CHIP_ID) {
15495fcf092eSHyungwoo Yang 		dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
15505fcf092eSHyungwoo Yang 			OV13858_CHIP_ID, val);
15515fcf092eSHyungwoo Yang 		return -EIO;
15525fcf092eSHyungwoo Yang 	}
15535fcf092eSHyungwoo Yang 
15545fcf092eSHyungwoo Yang 	return 0;
15555fcf092eSHyungwoo Yang }
15565fcf092eSHyungwoo Yang 
15575bd4098cSRicardo Ribalda static const struct v4l2_subdev_core_ops ov13858_core_ops = {
15585bd4098cSRicardo Ribalda 	.log_status = v4l2_ctrl_subdev_log_status,
15595bd4098cSRicardo Ribalda 	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
15605bd4098cSRicardo Ribalda 	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
15615bd4098cSRicardo Ribalda };
15625bd4098cSRicardo Ribalda 
15635fcf092eSHyungwoo Yang static const struct v4l2_subdev_video_ops ov13858_video_ops = {
15645fcf092eSHyungwoo Yang 	.s_stream = ov13858_set_stream,
15655fcf092eSHyungwoo Yang };
15665fcf092eSHyungwoo Yang 
15675fcf092eSHyungwoo Yang static const struct v4l2_subdev_pad_ops ov13858_pad_ops = {
15685fcf092eSHyungwoo Yang 	.enum_mbus_code = ov13858_enum_mbus_code,
15695fcf092eSHyungwoo Yang 	.get_fmt = ov13858_get_pad_format,
15705fcf092eSHyungwoo Yang 	.set_fmt = ov13858_set_pad_format,
15715fcf092eSHyungwoo Yang 	.enum_frame_size = ov13858_enum_frame_size,
15725fcf092eSHyungwoo Yang };
15735fcf092eSHyungwoo Yang 
15745fcf092eSHyungwoo Yang static const struct v4l2_subdev_sensor_ops ov13858_sensor_ops = {
15755fcf092eSHyungwoo Yang 	.g_skip_frames = ov13858_get_skip_frames,
15765fcf092eSHyungwoo Yang };
15775fcf092eSHyungwoo Yang 
15785fcf092eSHyungwoo Yang static const struct v4l2_subdev_ops ov13858_subdev_ops = {
15795bd4098cSRicardo Ribalda 	.core = &ov13858_core_ops,
15805fcf092eSHyungwoo Yang 	.video = &ov13858_video_ops,
15815fcf092eSHyungwoo Yang 	.pad = &ov13858_pad_ops,
15825fcf092eSHyungwoo Yang 	.sensor = &ov13858_sensor_ops,
15835fcf092eSHyungwoo Yang };
15845fcf092eSHyungwoo Yang 
15855fcf092eSHyungwoo Yang static const struct media_entity_operations ov13858_subdev_entity_ops = {
15865fcf092eSHyungwoo Yang 	.link_validate = v4l2_subdev_link_validate,
15875fcf092eSHyungwoo Yang };
15885fcf092eSHyungwoo Yang 
15895fcf092eSHyungwoo Yang static const struct v4l2_subdev_internal_ops ov13858_internal_ops = {
15905fcf092eSHyungwoo Yang 	.open = ov13858_open,
15915fcf092eSHyungwoo Yang };
15925fcf092eSHyungwoo Yang 
15935fcf092eSHyungwoo Yang /* Initialize control handlers */
ov13858_init_controls(struct ov13858 * ov13858)15945fcf092eSHyungwoo Yang static int ov13858_init_controls(struct ov13858 *ov13858)
15955fcf092eSHyungwoo Yang {
15965fcf092eSHyungwoo Yang 	struct i2c_client *client = v4l2_get_subdevdata(&ov13858->sd);
159774c3ddd9SJacopo Mondi 	struct v4l2_fwnode_device_properties props;
15985fcf092eSHyungwoo Yang 	struct v4l2_ctrl_handler *ctrl_hdlr;
159933eea132SChiranjeevi Rapolu 	s64 exposure_max;
160017fcd5f5SChiranjeevi Rapolu 	s64 vblank_def;
160117fcd5f5SChiranjeevi Rapolu 	s64 vblank_min;
16026f2a0594SChiranjeevi Rapolu 	s64 hblank;
16036f2a0594SChiranjeevi Rapolu 	s64 pixel_rate_min;
16046f2a0594SChiranjeevi Rapolu 	s64 pixel_rate_max;
16056f2a0594SChiranjeevi Rapolu 	const struct ov13858_mode *mode;
16065fcf092eSHyungwoo Yang 	int ret;
16075fcf092eSHyungwoo Yang 
16085fcf092eSHyungwoo Yang 	ctrl_hdlr = &ov13858->ctrl_handler;
160974c3ddd9SJacopo Mondi 	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
16105fcf092eSHyungwoo Yang 	if (ret)
16115fcf092eSHyungwoo Yang 		return ret;
16125fcf092eSHyungwoo Yang 
16135fcf092eSHyungwoo Yang 	mutex_init(&ov13858->mutex);
16145fcf092eSHyungwoo Yang 	ctrl_hdlr->lock = &ov13858->mutex;
16155fcf092eSHyungwoo Yang 	ov13858->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
16165fcf092eSHyungwoo Yang 				&ov13858_ctrl_ops,
16175fcf092eSHyungwoo Yang 				V4L2_CID_LINK_FREQ,
16185fcf092eSHyungwoo Yang 				OV13858_NUM_OF_LINK_FREQS - 1,
16195fcf092eSHyungwoo Yang 				0,
16205fcf092eSHyungwoo Yang 				link_freq_menu_items);
162135629182SChiranjeevi Rapolu 	if (ov13858->link_freq)
16225fcf092eSHyungwoo Yang 		ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
16235fcf092eSHyungwoo Yang 
1624880d45f8SSakari Ailus 	pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
1625880d45f8SSakari Ailus 	pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);
16265fcf092eSHyungwoo Yang 	/* By default, PIXEL_RATE is read only */
16275fcf092eSHyungwoo Yang 	ov13858->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops,
16286f2a0594SChiranjeevi Rapolu 						V4L2_CID_PIXEL_RATE,
16296f2a0594SChiranjeevi Rapolu 						pixel_rate_min, pixel_rate_max,
16306f2a0594SChiranjeevi Rapolu 						1, pixel_rate_max);
16315fcf092eSHyungwoo Yang 
16326f2a0594SChiranjeevi Rapolu 	mode = ov13858->cur_mode;
16336f2a0594SChiranjeevi Rapolu 	vblank_def = mode->vts_def - mode->height;
16346f2a0594SChiranjeevi Rapolu 	vblank_min = mode->vts_min - mode->height;
16355fcf092eSHyungwoo Yang 	ov13858->vblank = v4l2_ctrl_new_std(
16365fcf092eSHyungwoo Yang 				ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VBLANK,
16376f2a0594SChiranjeevi Rapolu 				vblank_min, OV13858_VTS_MAX - mode->height, 1,
163817fcd5f5SChiranjeevi Rapolu 				vblank_def);
16395fcf092eSHyungwoo Yang 
16406f2a0594SChiranjeevi Rapolu 	hblank = link_freq_configs[mode->link_freq_index].pixels_per_line -
16416f2a0594SChiranjeevi Rapolu 		 mode->width;
16425fcf092eSHyungwoo Yang 	ov13858->hblank = v4l2_ctrl_new_std(
16435fcf092eSHyungwoo Yang 				ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HBLANK,
16446f2a0594SChiranjeevi Rapolu 				hblank, hblank, 1, hblank);
164535629182SChiranjeevi Rapolu 	if (ov13858->hblank)
16465fcf092eSHyungwoo Yang 		ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
16475fcf092eSHyungwoo Yang 
16486f2a0594SChiranjeevi Rapolu 	exposure_max = mode->vts_def - 8;
16495fcf092eSHyungwoo Yang 	ov13858->exposure = v4l2_ctrl_new_std(
16505fcf092eSHyungwoo Yang 				ctrl_hdlr, &ov13858_ctrl_ops,
16515fcf092eSHyungwoo Yang 				V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN,
165233eea132SChiranjeevi Rapolu 				exposure_max, OV13858_EXPOSURE_STEP,
16535fcf092eSHyungwoo Yang 				OV13858_EXPOSURE_DEFAULT);
16545fcf092eSHyungwoo Yang 
16555fcf092eSHyungwoo Yang 	v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
16565fcf092eSHyungwoo Yang 			  OV13858_ANA_GAIN_MIN, OV13858_ANA_GAIN_MAX,
16575fcf092eSHyungwoo Yang 			  OV13858_ANA_GAIN_STEP, OV13858_ANA_GAIN_DEFAULT);
16585fcf092eSHyungwoo Yang 
16595fcf092eSHyungwoo Yang 	/* Digital gain */
16605fcf092eSHyungwoo Yang 	v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
16615fcf092eSHyungwoo Yang 			  OV13858_DGTL_GAIN_MIN, OV13858_DGTL_GAIN_MAX,
16625fcf092eSHyungwoo Yang 			  OV13858_DGTL_GAIN_STEP, OV13858_DGTL_GAIN_DEFAULT);
16635fcf092eSHyungwoo Yang 
16645fcf092eSHyungwoo Yang 	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov13858_ctrl_ops,
16655fcf092eSHyungwoo Yang 				     V4L2_CID_TEST_PATTERN,
16665fcf092eSHyungwoo Yang 				     ARRAY_SIZE(ov13858_test_pattern_menu) - 1,
16675fcf092eSHyungwoo Yang 				     0, 0, ov13858_test_pattern_menu);
16685fcf092eSHyungwoo Yang 	if (ctrl_hdlr->error) {
16695fcf092eSHyungwoo Yang 		ret = ctrl_hdlr->error;
16705fcf092eSHyungwoo Yang 		dev_err(&client->dev, "%s control init failed (%d)\n",
16715fcf092eSHyungwoo Yang 			__func__, ret);
16725fcf092eSHyungwoo Yang 		goto error;
16735fcf092eSHyungwoo Yang 	}
16745fcf092eSHyungwoo Yang 
167574c3ddd9SJacopo Mondi 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
167674c3ddd9SJacopo Mondi 	if (ret)
167774c3ddd9SJacopo Mondi 		goto error;
167874c3ddd9SJacopo Mondi 
167974c3ddd9SJacopo Mondi 	ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov13858_ctrl_ops,
168074c3ddd9SJacopo Mondi 					      &props);
168174c3ddd9SJacopo Mondi 	if (ret)
168274c3ddd9SJacopo Mondi 		goto error;
168374c3ddd9SJacopo Mondi 
16845fcf092eSHyungwoo Yang 	ov13858->sd.ctrl_handler = ctrl_hdlr;
16855fcf092eSHyungwoo Yang 
16865fcf092eSHyungwoo Yang 	return 0;
16875fcf092eSHyungwoo Yang 
16885fcf092eSHyungwoo Yang error:
16895fcf092eSHyungwoo Yang 	v4l2_ctrl_handler_free(ctrl_hdlr);
16905fcf092eSHyungwoo Yang 	mutex_destroy(&ov13858->mutex);
16915fcf092eSHyungwoo Yang 
16925fcf092eSHyungwoo Yang 	return ret;
16935fcf092eSHyungwoo Yang }
16945fcf092eSHyungwoo Yang 
ov13858_free_controls(struct ov13858 * ov13858)16955fcf092eSHyungwoo Yang static void ov13858_free_controls(struct ov13858 *ov13858)
16965fcf092eSHyungwoo Yang {
16975fcf092eSHyungwoo Yang 	v4l2_ctrl_handler_free(ov13858->sd.ctrl_handler);
16985fcf092eSHyungwoo Yang 	mutex_destroy(&ov13858->mutex);
16995fcf092eSHyungwoo Yang }
17005fcf092eSHyungwoo Yang 
ov13858_probe(struct i2c_client * client)17012ab6e408SUwe Kleine-König static int ov13858_probe(struct i2c_client *client)
17025fcf092eSHyungwoo Yang {
17035fcf092eSHyungwoo Yang 	struct ov13858 *ov13858;
17045fcf092eSHyungwoo Yang 	int ret;
17055fcf092eSHyungwoo Yang 	u32 val = 0;
17065fcf092eSHyungwoo Yang 
17075fcf092eSHyungwoo Yang 	device_property_read_u32(&client->dev, "clock-frequency", &val);
17085fcf092eSHyungwoo Yang 	if (val != 19200000)
17095fcf092eSHyungwoo Yang 		return -EINVAL;
17105fcf092eSHyungwoo Yang 
17115fcf092eSHyungwoo Yang 	ov13858 = devm_kzalloc(&client->dev, sizeof(*ov13858), GFP_KERNEL);
17125fcf092eSHyungwoo Yang 	if (!ov13858)
17135fcf092eSHyungwoo Yang 		return -ENOMEM;
17145fcf092eSHyungwoo Yang 
17155fcf092eSHyungwoo Yang 	/* Initialize subdev */
17165fcf092eSHyungwoo Yang 	v4l2_i2c_subdev_init(&ov13858->sd, client, &ov13858_subdev_ops);
17175fcf092eSHyungwoo Yang 
17185fcf092eSHyungwoo Yang 	/* Check module identity */
17195fcf092eSHyungwoo Yang 	ret = ov13858_identify_module(ov13858);
17205fcf092eSHyungwoo Yang 	if (ret) {
17215fcf092eSHyungwoo Yang 		dev_err(&client->dev, "failed to find sensor: %d\n", ret);
17225fcf092eSHyungwoo Yang 		return ret;
17235fcf092eSHyungwoo Yang 	}
17245fcf092eSHyungwoo Yang 
17255fcf092eSHyungwoo Yang 	/* Set default mode to max resolution */
17265fcf092eSHyungwoo Yang 	ov13858->cur_mode = &supported_modes[0];
17275fcf092eSHyungwoo Yang 
17285fcf092eSHyungwoo Yang 	ret = ov13858_init_controls(ov13858);
17295fcf092eSHyungwoo Yang 	if (ret)
17305fcf092eSHyungwoo Yang 		return ret;
17315fcf092eSHyungwoo Yang 
17325fcf092eSHyungwoo Yang 	/* Initialize subdev */
17335fcf092eSHyungwoo Yang 	ov13858->sd.internal_ops = &ov13858_internal_ops;
17345bd4098cSRicardo Ribalda 	ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
17355bd4098cSRicardo Ribalda 			     V4L2_SUBDEV_FL_HAS_EVENTS;
17365fcf092eSHyungwoo Yang 	ov13858->sd.entity.ops = &ov13858_subdev_entity_ops;
17375fcf092eSHyungwoo Yang 	ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
17385fcf092eSHyungwoo Yang 
17395fcf092eSHyungwoo Yang 	/* Initialize source pad */
17405fcf092eSHyungwoo Yang 	ov13858->pad.flags = MEDIA_PAD_FL_SOURCE;
17415fcf092eSHyungwoo Yang 	ret = media_entity_pads_init(&ov13858->sd.entity, 1, &ov13858->pad);
17425fcf092eSHyungwoo Yang 	if (ret) {
17435fcf092eSHyungwoo Yang 		dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
17445fcf092eSHyungwoo Yang 		goto error_handler_free;
17455fcf092eSHyungwoo Yang 	}
17465fcf092eSHyungwoo Yang 
174715786f7bSSakari Ailus 	ret = v4l2_async_register_subdev_sensor(&ov13858->sd);
17485fcf092eSHyungwoo Yang 	if (ret < 0)
17495fcf092eSHyungwoo Yang 		goto error_media_entity;
17505fcf092eSHyungwoo Yang 
17515fcf092eSHyungwoo Yang 	/*
17525fcf092eSHyungwoo Yang 	 * Device is already turned on by i2c-core with ACPI domain PM.
17535fcf092eSHyungwoo Yang 	 * Enable runtime PM and turn off the device.
17545fcf092eSHyungwoo Yang 	 */
17555fcf092eSHyungwoo Yang 	pm_runtime_set_active(&client->dev);
17565fcf092eSHyungwoo Yang 	pm_runtime_enable(&client->dev);
1757d508fffbSSakari Ailus 	pm_runtime_idle(&client->dev);
17585fcf092eSHyungwoo Yang 
17595fcf092eSHyungwoo Yang 	return 0;
17605fcf092eSHyungwoo Yang 
17615fcf092eSHyungwoo Yang error_media_entity:
17625fcf092eSHyungwoo Yang 	media_entity_cleanup(&ov13858->sd.entity);
17635fcf092eSHyungwoo Yang 
17645fcf092eSHyungwoo Yang error_handler_free:
17655fcf092eSHyungwoo Yang 	ov13858_free_controls(ov13858);
17665fcf092eSHyungwoo Yang 	dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
17675fcf092eSHyungwoo Yang 
17685fcf092eSHyungwoo Yang 	return ret;
17695fcf092eSHyungwoo Yang }
17705fcf092eSHyungwoo Yang 
ov13858_remove(struct i2c_client * client)1771ed5c2f5fSUwe Kleine-König static void ov13858_remove(struct i2c_client *client)
17725fcf092eSHyungwoo Yang {
17735fcf092eSHyungwoo Yang 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
17745fcf092eSHyungwoo Yang 	struct ov13858 *ov13858 = to_ov13858(sd);
17755fcf092eSHyungwoo Yang 
17765fcf092eSHyungwoo Yang 	v4l2_async_unregister_subdev(sd);
17775fcf092eSHyungwoo Yang 	media_entity_cleanup(&sd->entity);
17785fcf092eSHyungwoo Yang 	ov13858_free_controls(ov13858);
17795fcf092eSHyungwoo Yang 
17805fcf092eSHyungwoo Yang 	pm_runtime_disable(&client->dev);
17815fcf092eSHyungwoo Yang }
17825fcf092eSHyungwoo Yang 
17835fcf092eSHyungwoo Yang static const struct i2c_device_id ov13858_id_table[] = {
17845fcf092eSHyungwoo Yang 	{"ov13858", 0},
17855fcf092eSHyungwoo Yang 	{},
17865fcf092eSHyungwoo Yang };
17875fcf092eSHyungwoo Yang 
17885fcf092eSHyungwoo Yang MODULE_DEVICE_TABLE(i2c, ov13858_id_table);
17895fcf092eSHyungwoo Yang 
17905fcf092eSHyungwoo Yang static const struct dev_pm_ops ov13858_pm_ops = {
17915fcf092eSHyungwoo Yang 	SET_SYSTEM_SLEEP_PM_OPS(ov13858_suspend, ov13858_resume)
17925fcf092eSHyungwoo Yang };
17935fcf092eSHyungwoo Yang 
17945fcf092eSHyungwoo Yang #ifdef CONFIG_ACPI
17955fcf092eSHyungwoo Yang static const struct acpi_device_id ov13858_acpi_ids[] = {
17965fcf092eSHyungwoo Yang 	{"OVTID858"},
17975fcf092eSHyungwoo Yang 	{ /* sentinel */ }
17985fcf092eSHyungwoo Yang };
17995fcf092eSHyungwoo Yang 
18005fcf092eSHyungwoo Yang MODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids);
18015fcf092eSHyungwoo Yang #endif
18025fcf092eSHyungwoo Yang 
18035fcf092eSHyungwoo Yang static struct i2c_driver ov13858_i2c_driver = {
18045fcf092eSHyungwoo Yang 	.driver = {
18055fcf092eSHyungwoo Yang 		.name = "ov13858",
18065fcf092eSHyungwoo Yang 		.pm = &ov13858_pm_ops,
18075fcf092eSHyungwoo Yang 		.acpi_match_table = ACPI_PTR(ov13858_acpi_ids),
18085fcf092eSHyungwoo Yang 	},
1809aaeb31c0SUwe Kleine-König 	.probe = ov13858_probe,
18105fcf092eSHyungwoo Yang 	.remove = ov13858_remove,
18115fcf092eSHyungwoo Yang 	.id_table = ov13858_id_table,
18125fcf092eSHyungwoo Yang };
18135fcf092eSHyungwoo Yang 
18145fcf092eSHyungwoo Yang module_i2c_driver(ov13858_i2c_driver);
18155fcf092eSHyungwoo Yang 
18165fcf092eSHyungwoo Yang MODULE_AUTHOR("Kan, Chris <chris.kan@intel.com>");
1817*4106cd72SSakari Ailus MODULE_AUTHOR("Rapolu, Chiranjeevi");
18185fcec420SSakari Ailus MODULE_AUTHOR("Yang, Hyungwoo");
18195fcf092eSHyungwoo Yang MODULE_DESCRIPTION("Omnivision ov13858 sensor driver");
18205fcf092eSHyungwoo Yang MODULE_LICENSE("GPL v2");
1821