xref: /openbmc/linux/drivers/media/i2c/ov13b10.c (revision 000339cb)
17ee85054SArec Kao // SPDX-License-Identifier: GPL-2.0
27ee85054SArec Kao // Copyright (c) 2021 Intel Corporation.
37ee85054SArec Kao 
47ee85054SArec Kao #include <linux/acpi.h>
56e28afd1SBingbu Cao #include <linux/clk.h>
66e28afd1SBingbu Cao #include <linux/delay.h>
76e28afd1SBingbu Cao #include <linux/gpio/consumer.h>
87ee85054SArec Kao #include <linux/i2c.h>
97ee85054SArec Kao #include <linux/module.h>
107ee85054SArec Kao #include <linux/pm_runtime.h>
117ee85054SArec Kao #include <media/v4l2-ctrls.h>
127ee85054SArec Kao #include <media/v4l2-device.h>
137ee85054SArec Kao #include <media/v4l2-fwnode.h>
147ee85054SArec Kao 
157ee85054SArec Kao #define OV13B10_REG_VALUE_08BIT		1
167ee85054SArec Kao #define OV13B10_REG_VALUE_16BIT		2
177ee85054SArec Kao #define OV13B10_REG_VALUE_24BIT		3
187ee85054SArec Kao 
197ee85054SArec Kao #define OV13B10_REG_MODE_SELECT		0x0100
207ee85054SArec Kao #define OV13B10_MODE_STANDBY		0x00
217ee85054SArec Kao #define OV13B10_MODE_STREAMING		0x01
227ee85054SArec Kao 
237ee85054SArec Kao #define OV13B10_REG_SOFTWARE_RST	0x0103
247ee85054SArec Kao #define OV13B10_SOFTWARE_RST		0x01
257ee85054SArec Kao 
267ee85054SArec Kao /* Chip ID */
277ee85054SArec Kao #define OV13B10_REG_CHIP_ID		0x300a
287ee85054SArec Kao #define OV13B10_CHIP_ID			0x560d42
297ee85054SArec Kao 
307ee85054SArec Kao /* V_TIMING internal */
317ee85054SArec Kao #define OV13B10_REG_VTS			0x380e
327ee85054SArec Kao #define OV13B10_VTS_30FPS		0x0c7c
337ee85054SArec Kao #define OV13B10_VTS_60FPS		0x063e
347ee85054SArec Kao #define OV13B10_VTS_MAX			0x7fff
357ee85054SArec Kao 
367ee85054SArec Kao /* HBLANK control - read only */
377ee85054SArec Kao #define OV13B10_PPL_560MHZ		4704
387ee85054SArec Kao 
397ee85054SArec Kao /* Exposure control */
407ee85054SArec Kao #define OV13B10_REG_EXPOSURE		0x3500
417ee85054SArec Kao #define OV13B10_EXPOSURE_MIN		4
427ee85054SArec Kao #define OV13B10_EXPOSURE_STEP		1
437ee85054SArec Kao #define OV13B10_EXPOSURE_DEFAULT	0x40
447ee85054SArec Kao 
457ee85054SArec Kao /* Analog gain control */
467ee85054SArec Kao #define OV13B10_REG_ANALOG_GAIN		0x3508
477ee85054SArec Kao #define OV13B10_ANA_GAIN_MIN		0x80
487ee85054SArec Kao #define OV13B10_ANA_GAIN_MAX		0x07c0
497ee85054SArec Kao #define OV13B10_ANA_GAIN_STEP		1
507ee85054SArec Kao #define OV13B10_ANA_GAIN_DEFAULT	0x80
517ee85054SArec Kao 
527ee85054SArec Kao /* Digital gain control */
537ee85054SArec Kao #define OV13B10_REG_DGTL_GAIN_H		0x350a
547ee85054SArec Kao #define OV13B10_REG_DGTL_GAIN_M		0x350b
557ee85054SArec Kao #define OV13B10_REG_DGTL_GAIN_L		0x350c
567ee85054SArec Kao 
577ee85054SArec Kao #define OV13B10_DGTL_GAIN_MIN		1024	     /* Min = 1 X */
587ee85054SArec Kao #define OV13B10_DGTL_GAIN_MAX		(4096 - 1)   /* Max = 4 X */
597ee85054SArec Kao #define OV13B10_DGTL_GAIN_DEFAULT	2560	     /* Default gain = 2.5 X */
607ee85054SArec Kao #define OV13B10_DGTL_GAIN_STEP		1	     /* Each step = 1/1024 */
617ee85054SArec Kao 
627ee85054SArec Kao #define OV13B10_DGTL_GAIN_L_SHIFT	6
637ee85054SArec Kao #define OV13B10_DGTL_GAIN_L_MASK	0x3
647ee85054SArec Kao #define OV13B10_DGTL_GAIN_M_SHIFT	2
657ee85054SArec Kao #define OV13B10_DGTL_GAIN_M_MASK	0xff
667ee85054SArec Kao #define OV13B10_DGTL_GAIN_H_SHIFT	10
677ee85054SArec Kao #define OV13B10_DGTL_GAIN_H_MASK	0x3
687ee85054SArec Kao 
697ee85054SArec Kao /* Test Pattern Control */
707ee85054SArec Kao #define OV13B10_REG_TEST_PATTERN	0x5080
717ee85054SArec Kao #define OV13B10_TEST_PATTERN_ENABLE	BIT(7)
727ee85054SArec Kao #define OV13B10_TEST_PATTERN_MASK	0xf3
737ee85054SArec Kao #define OV13B10_TEST_PATTERN_BAR_SHIFT	2
747ee85054SArec Kao 
757ee85054SArec Kao /* Flip Control */
767ee85054SArec Kao #define OV13B10_REG_FORMAT1		0x3820
777ee85054SArec Kao #define OV13B10_REG_FORMAT2		0x3821
787ee85054SArec Kao 
797ee85054SArec Kao /* Horizontal Window Offset */
807ee85054SArec Kao #define OV13B10_REG_H_WIN_OFFSET	0x3811
817ee85054SArec Kao 
827ee85054SArec Kao /* Vertical Window Offset */
837ee85054SArec Kao #define OV13B10_REG_V_WIN_OFFSET	0x3813
847ee85054SArec Kao 
857ee85054SArec Kao struct ov13b10_reg {
867ee85054SArec Kao 	u16 address;
877ee85054SArec Kao 	u8 val;
887ee85054SArec Kao };
897ee85054SArec Kao 
907ee85054SArec Kao struct ov13b10_reg_list {
917ee85054SArec Kao 	u32 num_of_regs;
927ee85054SArec Kao 	const struct ov13b10_reg *regs;
937ee85054SArec Kao };
947ee85054SArec Kao 
957ee85054SArec Kao /* Link frequency config */
967ee85054SArec Kao struct ov13b10_link_freq_config {
977ee85054SArec Kao 	u32 pixels_per_line;
987ee85054SArec Kao 
997ee85054SArec Kao 	/* registers for this link frequency */
1007ee85054SArec Kao 	struct ov13b10_reg_list reg_list;
1017ee85054SArec Kao };
1027ee85054SArec Kao 
1037ee85054SArec Kao /* Mode : resolution and related config&values */
1047ee85054SArec Kao struct ov13b10_mode {
1057ee85054SArec Kao 	/* Frame width */
1067ee85054SArec Kao 	u32 width;
1077ee85054SArec Kao 	/* Frame height */
1087ee85054SArec Kao 	u32 height;
1097ee85054SArec Kao 
1107ee85054SArec Kao 	/* V-timing */
1117ee85054SArec Kao 	u32 vts_def;
1127ee85054SArec Kao 	u32 vts_min;
1137ee85054SArec Kao 
1147ee85054SArec Kao 	/* Index of Link frequency config to be used */
1157ee85054SArec Kao 	u32 link_freq_index;
1167ee85054SArec Kao 	/* Default register values */
1177ee85054SArec Kao 	struct ov13b10_reg_list reg_list;
1187ee85054SArec Kao };
1197ee85054SArec Kao 
1207ee85054SArec Kao /* 4208x3120 needs 1120Mbps/lane, 4 lanes */
1217ee85054SArec Kao static const struct ov13b10_reg mipi_data_rate_1120mbps[] = {
1227ee85054SArec Kao 	{0x0103, 0x01},
1237ee85054SArec Kao 	{0x0303, 0x04},
1247ee85054SArec Kao 	{0x0305, 0xaf},
1257ee85054SArec Kao 	{0x0321, 0x00},
1267ee85054SArec Kao 	{0x0323, 0x04},
1277ee85054SArec Kao 	{0x0324, 0x01},
1287ee85054SArec Kao 	{0x0325, 0xa4},
1297ee85054SArec Kao 	{0x0326, 0x81},
1307ee85054SArec Kao 	{0x0327, 0x04},
1317ee85054SArec Kao 	{0x3012, 0x07},
1327ee85054SArec Kao 	{0x3013, 0x32},
1337ee85054SArec Kao 	{0x3107, 0x23},
1347ee85054SArec Kao 	{0x3501, 0x0c},
1357ee85054SArec Kao 	{0x3502, 0x10},
1367ee85054SArec Kao 	{0x3504, 0x08},
1377ee85054SArec Kao 	{0x3508, 0x07},
1387ee85054SArec Kao 	{0x3509, 0xc0},
1397ee85054SArec Kao 	{0x3600, 0x16},
1407ee85054SArec Kao 	{0x3601, 0x54},
1417ee85054SArec Kao 	{0x3612, 0x4e},
1427ee85054SArec Kao 	{0x3620, 0x00},
1437ee85054SArec Kao 	{0x3621, 0x68},
1447ee85054SArec Kao 	{0x3622, 0x66},
1457ee85054SArec Kao 	{0x3623, 0x03},
1467ee85054SArec Kao 	{0x3662, 0x92},
1477ee85054SArec Kao 	{0x3666, 0xbb},
1487ee85054SArec Kao 	{0x3667, 0x44},
1497ee85054SArec Kao 	{0x366e, 0xff},
1507ee85054SArec Kao 	{0x366f, 0xf3},
1517ee85054SArec Kao 	{0x3675, 0x44},
1527ee85054SArec Kao 	{0x3676, 0x00},
1537ee85054SArec Kao 	{0x367f, 0xe9},
1547ee85054SArec Kao 	{0x3681, 0x32},
1557ee85054SArec Kao 	{0x3682, 0x1f},
1567ee85054SArec Kao 	{0x3683, 0x0b},
1577ee85054SArec Kao 	{0x3684, 0x0b},
1587ee85054SArec Kao 	{0x3704, 0x0f},
1597ee85054SArec Kao 	{0x3706, 0x40},
1607ee85054SArec Kao 	{0x3708, 0x3b},
1617ee85054SArec Kao 	{0x3709, 0x72},
1627ee85054SArec Kao 	{0x370b, 0xa2},
1637ee85054SArec Kao 	{0x3714, 0x24},
1647ee85054SArec Kao 	{0x371a, 0x3e},
1657ee85054SArec Kao 	{0x3725, 0x42},
1667ee85054SArec Kao 	{0x3739, 0x12},
1677ee85054SArec Kao 	{0x3767, 0x00},
1687ee85054SArec Kao 	{0x377a, 0x0d},
1697ee85054SArec Kao 	{0x3789, 0x18},
1707ee85054SArec Kao 	{0x3790, 0x40},
1717ee85054SArec Kao 	{0x3791, 0xa2},
1727ee85054SArec Kao 	{0x37c2, 0x04},
1737ee85054SArec Kao 	{0x37c3, 0xf1},
1747ee85054SArec Kao 	{0x37d9, 0x0c},
1757ee85054SArec Kao 	{0x37da, 0x02},
1767ee85054SArec Kao 	{0x37dc, 0x02},
1777ee85054SArec Kao 	{0x37e1, 0x04},
1787ee85054SArec Kao 	{0x37e2, 0x0a},
1797ee85054SArec Kao 	{0x3800, 0x00},
1807ee85054SArec Kao 	{0x3801, 0x00},
1817ee85054SArec Kao 	{0x3802, 0x00},
1827ee85054SArec Kao 	{0x3803, 0x08},
1837ee85054SArec Kao 	{0x3804, 0x10},
1847ee85054SArec Kao 	{0x3805, 0x8f},
1857ee85054SArec Kao 	{0x3806, 0x0c},
1867ee85054SArec Kao 	{0x3807, 0x47},
1877ee85054SArec Kao 	{0x3808, 0x10},
1887ee85054SArec Kao 	{0x3809, 0x70},
1897ee85054SArec Kao 	{0x380a, 0x0c},
1907ee85054SArec Kao 	{0x380b, 0x30},
1917ee85054SArec Kao 	{0x380c, 0x04},
1927ee85054SArec Kao 	{0x380d, 0x98},
1937ee85054SArec Kao 	{0x380e, 0x0c},
1947ee85054SArec Kao 	{0x380f, 0x7c},
1957ee85054SArec Kao 	{0x3811, 0x0f},
1967ee85054SArec Kao 	{0x3813, 0x09},
1977ee85054SArec Kao 	{0x3814, 0x01},
1987ee85054SArec Kao 	{0x3815, 0x01},
1997ee85054SArec Kao 	{0x3816, 0x01},
2007ee85054SArec Kao 	{0x3817, 0x01},
2017ee85054SArec Kao 	{0x381f, 0x08},
2027ee85054SArec Kao 	{0x3820, 0x88},
2037ee85054SArec Kao 	{0x3821, 0x00},
2047ee85054SArec Kao 	{0x3822, 0x14},
2057ee85054SArec Kao 	{0x382e, 0xe6},
2067ee85054SArec Kao 	{0x3c80, 0x00},
2077ee85054SArec Kao 	{0x3c87, 0x01},
2087ee85054SArec Kao 	{0x3c8c, 0x19},
2097ee85054SArec Kao 	{0x3c8d, 0x1c},
2107ee85054SArec Kao 	{0x3ca0, 0x00},
2117ee85054SArec Kao 	{0x3ca1, 0x00},
2127ee85054SArec Kao 	{0x3ca2, 0x00},
2137ee85054SArec Kao 	{0x3ca3, 0x00},
2147ee85054SArec Kao 	{0x3ca4, 0x50},
2157ee85054SArec Kao 	{0x3ca5, 0x11},
2167ee85054SArec Kao 	{0x3ca6, 0x01},
2177ee85054SArec Kao 	{0x3ca7, 0x00},
2187ee85054SArec Kao 	{0x3ca8, 0x00},
2197ee85054SArec Kao 	{0x4008, 0x02},
2207ee85054SArec Kao 	{0x4009, 0x0f},
2217ee85054SArec Kao 	{0x400a, 0x01},
2227ee85054SArec Kao 	{0x400b, 0x19},
2237ee85054SArec Kao 	{0x4011, 0x21},
2247ee85054SArec Kao 	{0x4017, 0x08},
2257ee85054SArec Kao 	{0x4019, 0x04},
2267ee85054SArec Kao 	{0x401a, 0x58},
2277ee85054SArec Kao 	{0x4032, 0x1e},
2287ee85054SArec Kao 	{0x4050, 0x02},
2297ee85054SArec Kao 	{0x4051, 0x09},
2307ee85054SArec Kao 	{0x405e, 0x00},
2317ee85054SArec Kao 	{0x4066, 0x02},
2327ee85054SArec Kao 	{0x4501, 0x00},
2337ee85054SArec Kao 	{0x4502, 0x10},
2347ee85054SArec Kao 	{0x4505, 0x00},
2357ee85054SArec Kao 	{0x4800, 0x64},
2367ee85054SArec Kao 	{0x481b, 0x3e},
2377ee85054SArec Kao 	{0x481f, 0x30},
2387ee85054SArec Kao 	{0x4825, 0x34},
2397ee85054SArec Kao 	{0x4837, 0x0e},
2407ee85054SArec Kao 	{0x484b, 0x01},
2417ee85054SArec Kao 	{0x4883, 0x02},
2427ee85054SArec Kao 	{0x5000, 0xff},
2437ee85054SArec Kao 	{0x5001, 0x0f},
2447ee85054SArec Kao 	{0x5045, 0x20},
2457ee85054SArec Kao 	{0x5046, 0x20},
2467ee85054SArec Kao 	{0x5047, 0xa4},
2477ee85054SArec Kao 	{0x5048, 0x20},
2487ee85054SArec Kao 	{0x5049, 0xa4},
2497ee85054SArec Kao };
2507ee85054SArec Kao 
2517ee85054SArec Kao static const struct ov13b10_reg mode_4208x3120_regs[] = {
2527ee85054SArec Kao 	{0x0305, 0xaf},
2537ee85054SArec Kao 	{0x3501, 0x0c},
2547ee85054SArec Kao 	{0x3662, 0x92},
2557ee85054SArec Kao 	{0x3714, 0x24},
2567ee85054SArec Kao 	{0x3739, 0x12},
2577ee85054SArec Kao 	{0x37c2, 0x04},
2587ee85054SArec Kao 	{0x37d9, 0x0c},
2597ee85054SArec Kao 	{0x37e2, 0x0a},
2607ee85054SArec Kao 	{0x3800, 0x00},
2617ee85054SArec Kao 	{0x3801, 0x00},
2627ee85054SArec Kao 	{0x3802, 0x00},
2637ee85054SArec Kao 	{0x3803, 0x08},
2647ee85054SArec Kao 	{0x3804, 0x10},
2657ee85054SArec Kao 	{0x3805, 0x8f},
2667ee85054SArec Kao 	{0x3806, 0x0c},
2677ee85054SArec Kao 	{0x3807, 0x47},
2687ee85054SArec Kao 	{0x3808, 0x10},
2697ee85054SArec Kao 	{0x3809, 0x70},
2707ee85054SArec Kao 	{0x380a, 0x0c},
2717ee85054SArec Kao 	{0x380b, 0x30},
2727ee85054SArec Kao 	{0x380c, 0x04},
2737ee85054SArec Kao 	{0x380d, 0x98},
2747ee85054SArec Kao 	{0x380e, 0x0c},
2757ee85054SArec Kao 	{0x380f, 0x7c},
2767ee85054SArec Kao 	{0x3810, 0x00},
2777ee85054SArec Kao 	{0x3811, 0x0f},
2787ee85054SArec Kao 	{0x3812, 0x00},
2797ee85054SArec Kao 	{0x3813, 0x09},
2807ee85054SArec Kao 	{0x3814, 0x01},
2817ee85054SArec Kao 	{0x3816, 0x01},
2827ee85054SArec Kao 	{0x3820, 0x88},
2837ee85054SArec Kao 	{0x3c8c, 0x19},
2847ee85054SArec Kao 	{0x4008, 0x02},
2857ee85054SArec Kao 	{0x4009, 0x0f},
2867ee85054SArec Kao 	{0x4050, 0x02},
2877ee85054SArec Kao 	{0x4051, 0x09},
2887ee85054SArec Kao 	{0x4501, 0x00},
2897ee85054SArec Kao 	{0x4505, 0x00},
2907ee85054SArec Kao 	{0x4837, 0x0e},
2917ee85054SArec Kao 	{0x5000, 0xff},
2927ee85054SArec Kao 	{0x5001, 0x0f},
2937ee85054SArec Kao };
2947ee85054SArec Kao 
2957ee85054SArec Kao static const struct ov13b10_reg mode_4160x3120_regs[] = {
2967ee85054SArec Kao 	{0x0305, 0xaf},
2977ee85054SArec Kao 	{0x3501, 0x0c},
2987ee85054SArec Kao 	{0x3662, 0x92},
2997ee85054SArec Kao 	{0x3714, 0x24},
3007ee85054SArec Kao 	{0x3739, 0x12},
3017ee85054SArec Kao 	{0x37c2, 0x04},
3027ee85054SArec Kao 	{0x37d9, 0x0c},
3037ee85054SArec Kao 	{0x37e2, 0x0a},
3047ee85054SArec Kao 	{0x3800, 0x00},
3057ee85054SArec Kao 	{0x3801, 0x00},
3067ee85054SArec Kao 	{0x3802, 0x00},
3077ee85054SArec Kao 	{0x3803, 0x08},
3087ee85054SArec Kao 	{0x3804, 0x10},
3097ee85054SArec Kao 	{0x3805, 0x8f},
3107ee85054SArec Kao 	{0x3806, 0x0c},
3117ee85054SArec Kao 	{0x3807, 0x47},
3127ee85054SArec Kao 	{0x3808, 0x10},
3137ee85054SArec Kao 	{0x3809, 0x40},
3147ee85054SArec Kao 	{0x380a, 0x0c},
3157ee85054SArec Kao 	{0x380b, 0x30},
3167ee85054SArec Kao 	{0x380c, 0x04},
3177ee85054SArec Kao 	{0x380d, 0x98},
3187ee85054SArec Kao 	{0x380e, 0x0c},
3197ee85054SArec Kao 	{0x380f, 0x7c},
3207ee85054SArec Kao 	{0x3810, 0x00},
3217ee85054SArec Kao 	{0x3811, 0x27},
3227ee85054SArec Kao 	{0x3812, 0x00},
3237ee85054SArec Kao 	{0x3813, 0x09},
3247ee85054SArec Kao 	{0x3814, 0x01},
3257ee85054SArec Kao 	{0x3816, 0x01},
3267ee85054SArec Kao 	{0x3820, 0x88},
3277ee85054SArec Kao 	{0x3c8c, 0x19},
3287ee85054SArec Kao 	{0x4008, 0x02},
3297ee85054SArec Kao 	{0x4009, 0x0f},
3307ee85054SArec Kao 	{0x4050, 0x02},
3317ee85054SArec Kao 	{0x4051, 0x09},
3327ee85054SArec Kao 	{0x4501, 0x00},
3337ee85054SArec Kao 	{0x4505, 0x00},
3347ee85054SArec Kao 	{0x4837, 0x0e},
3357ee85054SArec Kao 	{0x5000, 0xff},
3367ee85054SArec Kao 	{0x5001, 0x0f},
3377ee85054SArec Kao };
3387ee85054SArec Kao 
3397ee85054SArec Kao static const struct ov13b10_reg mode_4160x2340_regs[] = {
3407ee85054SArec Kao 	{0x0305, 0xaf},
3417ee85054SArec Kao 	{0x3501, 0x0c},
3427ee85054SArec Kao 	{0x3662, 0x92},
3437ee85054SArec Kao 	{0x3714, 0x24},
3447ee85054SArec Kao 	{0x3739, 0x12},
3457ee85054SArec Kao 	{0x37c2, 0x04},
3467ee85054SArec Kao 	{0x37d9, 0x0c},
3477ee85054SArec Kao 	{0x37e2, 0x0a},
3487ee85054SArec Kao 	{0x3800, 0x00},
3497ee85054SArec Kao 	{0x3801, 0x00},
3507ee85054SArec Kao 	{0x3802, 0x00},
3517ee85054SArec Kao 	{0x3803, 0x08},
3527ee85054SArec Kao 	{0x3804, 0x10},
3537ee85054SArec Kao 	{0x3805, 0x8f},
3547ee85054SArec Kao 	{0x3806, 0x0c},
3557ee85054SArec Kao 	{0x3807, 0x47},
3567ee85054SArec Kao 	{0x3808, 0x10},
3577ee85054SArec Kao 	{0x3809, 0x40},
3587ee85054SArec Kao 	{0x380a, 0x09},
3597ee85054SArec Kao 	{0x380b, 0x24},
3607ee85054SArec Kao 	{0x380c, 0x04},
3617ee85054SArec Kao 	{0x380d, 0x98},
3627ee85054SArec Kao 	{0x380e, 0x0c},
3637ee85054SArec Kao 	{0x380f, 0x7c},
3647ee85054SArec Kao 	{0x3810, 0x00},
3657ee85054SArec Kao 	{0x3811, 0x27},
3667ee85054SArec Kao 	{0x3812, 0x01},
3677ee85054SArec Kao 	{0x3813, 0x8f},
3687ee85054SArec Kao 	{0x3814, 0x01},
3697ee85054SArec Kao 	{0x3816, 0x01},
3707ee85054SArec Kao 	{0x3820, 0x88},
3717ee85054SArec Kao 	{0x3c8c, 0x19},
3727ee85054SArec Kao 	{0x4008, 0x02},
3737ee85054SArec Kao 	{0x4009, 0x0f},
3747ee85054SArec Kao 	{0x4050, 0x02},
3757ee85054SArec Kao 	{0x4051, 0x09},
3767ee85054SArec Kao 	{0x4501, 0x00},
3777ee85054SArec Kao 	{0x4505, 0x00},
3787ee85054SArec Kao 	{0x4837, 0x0e},
3797ee85054SArec Kao 	{0x5000, 0xff},
3807ee85054SArec Kao 	{0x5001, 0x0f},
3817ee85054SArec Kao };
3827ee85054SArec Kao 
3837ee85054SArec Kao static const struct ov13b10_reg mode_2104x1560_regs[] = {
3847ee85054SArec Kao 	{0x0305, 0xaf},
3857ee85054SArec Kao 	{0x3501, 0x06},
3867ee85054SArec Kao 	{0x3662, 0x88},
3877ee85054SArec Kao 	{0x3714, 0x28},
3887ee85054SArec Kao 	{0x3739, 0x10},
3897ee85054SArec Kao 	{0x37c2, 0x14},
3907ee85054SArec Kao 	{0x37d9, 0x06},
3917ee85054SArec Kao 	{0x37e2, 0x0c},
3927ee85054SArec Kao 	{0x3800, 0x00},
3937ee85054SArec Kao 	{0x3801, 0x00},
3947ee85054SArec Kao 	{0x3802, 0x00},
3957ee85054SArec Kao 	{0x3803, 0x08},
3967ee85054SArec Kao 	{0x3804, 0x10},
3977ee85054SArec Kao 	{0x3805, 0x8f},
3987ee85054SArec Kao 	{0x3806, 0x0c},
3997ee85054SArec Kao 	{0x3807, 0x47},
4007ee85054SArec Kao 	{0x3808, 0x08},
4017ee85054SArec Kao 	{0x3809, 0x38},
4027ee85054SArec Kao 	{0x380a, 0x06},
4037ee85054SArec Kao 	{0x380b, 0x18},
4047ee85054SArec Kao 	{0x380c, 0x04},
4057ee85054SArec Kao 	{0x380d, 0x98},
4067ee85054SArec Kao 	{0x380e, 0x06},
4077ee85054SArec Kao 	{0x380f, 0x3e},
4087ee85054SArec Kao 	{0x3810, 0x00},
4097ee85054SArec Kao 	{0x3811, 0x07},
4107ee85054SArec Kao 	{0x3812, 0x00},
4117ee85054SArec Kao 	{0x3813, 0x05},
4127ee85054SArec Kao 	{0x3814, 0x03},
4137ee85054SArec Kao 	{0x3816, 0x03},
4147ee85054SArec Kao 	{0x3820, 0x8b},
4157ee85054SArec Kao 	{0x3c8c, 0x18},
4167ee85054SArec Kao 	{0x4008, 0x00},
4177ee85054SArec Kao 	{0x4009, 0x05},
4187ee85054SArec Kao 	{0x4050, 0x00},
4197ee85054SArec Kao 	{0x4051, 0x05},
4207ee85054SArec Kao 	{0x4501, 0x08},
4217ee85054SArec Kao 	{0x4505, 0x00},
4227ee85054SArec Kao 	{0x4837, 0x0e},
4237ee85054SArec Kao 	{0x5000, 0xfd},
4247ee85054SArec Kao 	{0x5001, 0x0d},
4257ee85054SArec Kao };
4267ee85054SArec Kao 
4277ee85054SArec Kao static const struct ov13b10_reg mode_2080x1170_regs[] = {
4287ee85054SArec Kao 	{0x0305, 0xaf},
4297ee85054SArec Kao 	{0x3501, 0x06},
4307ee85054SArec Kao 	{0x3662, 0x88},
4317ee85054SArec Kao 	{0x3714, 0x28},
4327ee85054SArec Kao 	{0x3739, 0x10},
4337ee85054SArec Kao 	{0x37c2, 0x14},
4347ee85054SArec Kao 	{0x37d9, 0x06},
4357ee85054SArec Kao 	{0x37e2, 0x0c},
4367ee85054SArec Kao 	{0x3800, 0x00},
4377ee85054SArec Kao 	{0x3801, 0x00},
4387ee85054SArec Kao 	{0x3802, 0x00},
4397ee85054SArec Kao 	{0x3803, 0x08},
4407ee85054SArec Kao 	{0x3804, 0x10},
4417ee85054SArec Kao 	{0x3805, 0x8f},
4427ee85054SArec Kao 	{0x3806, 0x0c},
4437ee85054SArec Kao 	{0x3807, 0x47},
4447ee85054SArec Kao 	{0x3808, 0x08},
4457ee85054SArec Kao 	{0x3809, 0x20},
4467ee85054SArec Kao 	{0x380a, 0x04},
4477ee85054SArec Kao 	{0x380b, 0x92},
4487ee85054SArec Kao 	{0x380c, 0x04},
4497ee85054SArec Kao 	{0x380d, 0x98},
4507ee85054SArec Kao 	{0x380e, 0x06},
4517ee85054SArec Kao 	{0x380f, 0x3e},
4527ee85054SArec Kao 	{0x3810, 0x00},
4537ee85054SArec Kao 	{0x3811, 0x13},
4547ee85054SArec Kao 	{0x3812, 0x00},
4557ee85054SArec Kao 	{0x3813, 0xc9},
4567ee85054SArec Kao 	{0x3814, 0x03},
4577ee85054SArec Kao 	{0x3816, 0x03},
4587ee85054SArec Kao 	{0x3820, 0x8b},
4597ee85054SArec Kao 	{0x3c8c, 0x18},
4607ee85054SArec Kao 	{0x4008, 0x00},
4617ee85054SArec Kao 	{0x4009, 0x05},
4627ee85054SArec Kao 	{0x4050, 0x00},
4637ee85054SArec Kao 	{0x4051, 0x05},
4647ee85054SArec Kao 	{0x4501, 0x08},
4657ee85054SArec Kao 	{0x4505, 0x00},
4667ee85054SArec Kao 	{0x4837, 0x0e},
4677ee85054SArec Kao 	{0x5000, 0xfd},
4687ee85054SArec Kao 	{0x5001, 0x0d},
4697ee85054SArec Kao };
4707ee85054SArec Kao 
4717ee85054SArec Kao static const char * const ov13b10_test_pattern_menu[] = {
4727ee85054SArec Kao 	"Disabled",
4737ee85054SArec Kao 	"Vertical Color Bar Type 1",
4747ee85054SArec Kao 	"Vertical Color Bar Type 2",
4757ee85054SArec Kao 	"Vertical Color Bar Type 3",
4767ee85054SArec Kao 	"Vertical Color Bar Type 4"
4777ee85054SArec Kao };
4787ee85054SArec Kao 
4797ee85054SArec Kao /* Configurations for supported link frequencies */
4807ee85054SArec Kao #define OV13B10_LINK_FREQ_560MHZ	560000000ULL
4817ee85054SArec Kao #define OV13B10_LINK_FREQ_INDEX_0	0
4827ee85054SArec Kao 
4837ee85054SArec Kao #define OV13B10_EXT_CLK			19200000
4847ee85054SArec Kao #define OV13B10_DATA_LANES		4
4857ee85054SArec Kao 
4867ee85054SArec Kao /*
4877ee85054SArec Kao  * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
4887ee85054SArec Kao  * data rate => double data rate; number of lanes => 4; bits per pixel => 10
4897ee85054SArec Kao  */
link_freq_to_pixel_rate(u64 f)4907ee85054SArec Kao static u64 link_freq_to_pixel_rate(u64 f)
4917ee85054SArec Kao {
4927ee85054SArec Kao 	f *= 2 * OV13B10_DATA_LANES;
4937ee85054SArec Kao 	do_div(f, 10);
4947ee85054SArec Kao 
4957ee85054SArec Kao 	return f;
4967ee85054SArec Kao }
4977ee85054SArec Kao 
4987ee85054SArec Kao /* Menu items for LINK_FREQ V4L2 control */
4997ee85054SArec Kao static const s64 link_freq_menu_items[] = {
5007ee85054SArec Kao 	OV13B10_LINK_FREQ_560MHZ
5017ee85054SArec Kao };
5027ee85054SArec Kao 
5037ee85054SArec Kao /* Link frequency configs */
5047ee85054SArec Kao static const struct ov13b10_link_freq_config
5057ee85054SArec Kao 			link_freq_configs[] = {
5067ee85054SArec Kao 	{
5077ee85054SArec Kao 		.pixels_per_line = OV13B10_PPL_560MHZ,
5087ee85054SArec Kao 		.reg_list = {
5097ee85054SArec Kao 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_1120mbps),
5107ee85054SArec Kao 			.regs = mipi_data_rate_1120mbps,
5117ee85054SArec Kao 		}
5127ee85054SArec Kao 	}
5137ee85054SArec Kao };
5147ee85054SArec Kao 
5157ee85054SArec Kao /* Mode configs */
5167ee85054SArec Kao static const struct ov13b10_mode supported_modes[] = {
5177ee85054SArec Kao 	{
5187ee85054SArec Kao 		.width = 4208,
5197ee85054SArec Kao 		.height = 3120,
5207ee85054SArec Kao 		.vts_def = OV13B10_VTS_30FPS,
5217ee85054SArec Kao 		.vts_min = OV13B10_VTS_30FPS,
5227ee85054SArec Kao 		.reg_list = {
5237ee85054SArec Kao 			.num_of_regs = ARRAY_SIZE(mode_4208x3120_regs),
5247ee85054SArec Kao 			.regs = mode_4208x3120_regs,
5257ee85054SArec Kao 		},
5267ee85054SArec Kao 		.link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
5277ee85054SArec Kao 	},
5287ee85054SArec Kao 	{
5297ee85054SArec Kao 		.width = 4160,
5307ee85054SArec Kao 		.height = 3120,
5317ee85054SArec Kao 		.vts_def = OV13B10_VTS_30FPS,
5327ee85054SArec Kao 		.vts_min = OV13B10_VTS_30FPS,
5337ee85054SArec Kao 		.reg_list = {
5347ee85054SArec Kao 			.num_of_regs = ARRAY_SIZE(mode_4160x3120_regs),
5357ee85054SArec Kao 			.regs = mode_4160x3120_regs,
5367ee85054SArec Kao 		},
5377ee85054SArec Kao 		.link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
5387ee85054SArec Kao 	},
5397ee85054SArec Kao 	{
5407ee85054SArec Kao 		.width = 4160,
5417ee85054SArec Kao 		.height = 2340,
5427ee85054SArec Kao 		.vts_def = OV13B10_VTS_30FPS,
5437ee85054SArec Kao 		.vts_min = OV13B10_VTS_30FPS,
5447ee85054SArec Kao 		.reg_list = {
5457ee85054SArec Kao 			.num_of_regs = ARRAY_SIZE(mode_4160x2340_regs),
5467ee85054SArec Kao 			.regs = mode_4160x2340_regs,
5477ee85054SArec Kao 		},
5487ee85054SArec Kao 		.link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
5497ee85054SArec Kao 	},
5507ee85054SArec Kao 	{
5517ee85054SArec Kao 		.width = 2104,
5527ee85054SArec Kao 		.height = 1560,
5537ee85054SArec Kao 		.vts_def = OV13B10_VTS_60FPS,
5547ee85054SArec Kao 		.vts_min = OV13B10_VTS_60FPS,
5557ee85054SArec Kao 		.reg_list = {
5567ee85054SArec Kao 			.num_of_regs = ARRAY_SIZE(mode_2104x1560_regs),
5577ee85054SArec Kao 			.regs = mode_2104x1560_regs,
5587ee85054SArec Kao 		},
5597ee85054SArec Kao 		.link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
5607ee85054SArec Kao 	},
5617ee85054SArec Kao 	{
5627ee85054SArec Kao 		.width = 2080,
5637ee85054SArec Kao 		.height = 1170,
5647ee85054SArec Kao 		.vts_def = OV13B10_VTS_60FPS,
5657ee85054SArec Kao 		.vts_min = OV13B10_VTS_60FPS,
5667ee85054SArec Kao 		.reg_list = {
5677ee85054SArec Kao 			.num_of_regs = ARRAY_SIZE(mode_2080x1170_regs),
5687ee85054SArec Kao 			.regs = mode_2080x1170_regs,
5697ee85054SArec Kao 		},
5707ee85054SArec Kao 		.link_freq_index = OV13B10_LINK_FREQ_INDEX_0,
5717ee85054SArec Kao 	}
5727ee85054SArec Kao };
5737ee85054SArec Kao 
5747ee85054SArec Kao struct ov13b10 {
5757ee85054SArec Kao 	struct v4l2_subdev sd;
5767ee85054SArec Kao 	struct media_pad pad;
5777ee85054SArec Kao 
5787ee85054SArec Kao 	struct v4l2_ctrl_handler ctrl_handler;
5796e28afd1SBingbu Cao 
5806e28afd1SBingbu Cao 	struct clk *img_clk;
5816e28afd1SBingbu Cao 	struct regulator *avdd;
5826e28afd1SBingbu Cao 	struct gpio_desc *reset;
5836e28afd1SBingbu Cao 
5847ee85054SArec Kao 	/* V4L2 Controls */
5857ee85054SArec Kao 	struct v4l2_ctrl *link_freq;
5867ee85054SArec Kao 	struct v4l2_ctrl *pixel_rate;
5877ee85054SArec Kao 	struct v4l2_ctrl *vblank;
5887ee85054SArec Kao 	struct v4l2_ctrl *hblank;
5897ee85054SArec Kao 	struct v4l2_ctrl *exposure;
5907ee85054SArec Kao 
5917ee85054SArec Kao 	/* Current mode */
5927ee85054SArec Kao 	const struct ov13b10_mode *cur_mode;
5937ee85054SArec Kao 
5947ee85054SArec Kao 	/* Mutex for serialized access */
5957ee85054SArec Kao 	struct mutex mutex;
5967ee85054SArec Kao 
5977ee85054SArec Kao 	/* Streaming on/off */
5987ee85054SArec Kao 	bool streaming;
5991af2f618SArec Kao 
6001af2f618SArec Kao 	/* True if the device has been identified */
6011af2f618SArec Kao 	bool identified;
6027ee85054SArec Kao };
6037ee85054SArec Kao 
6047ee85054SArec Kao #define to_ov13b10(_sd)	container_of(_sd, struct ov13b10, sd)
6057ee85054SArec Kao 
6067ee85054SArec Kao /* Read registers up to 4 at a time */
ov13b10_read_reg(struct ov13b10 * ov13b,u16 reg,u32 len,u32 * val)6077ee85054SArec Kao static int ov13b10_read_reg(struct ov13b10 *ov13b,
6087ee85054SArec Kao 			    u16 reg, u32 len, u32 *val)
6097ee85054SArec Kao {
6107ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
6117ee85054SArec Kao 	struct i2c_msg msgs[2];
6127ee85054SArec Kao 	u8 *data_be_p;
6137ee85054SArec Kao 	int ret;
6147ee85054SArec Kao 	__be32 data_be = 0;
6157ee85054SArec Kao 	__be16 reg_addr_be = cpu_to_be16(reg);
6167ee85054SArec Kao 
6177ee85054SArec Kao 	if (len > 4)
6187ee85054SArec Kao 		return -EINVAL;
6197ee85054SArec Kao 
6207ee85054SArec Kao 	data_be_p = (u8 *)&data_be;
6217ee85054SArec Kao 	/* Write register address */
6227ee85054SArec Kao 	msgs[0].addr = client->addr;
6237ee85054SArec Kao 	msgs[0].flags = 0;
6247ee85054SArec Kao 	msgs[0].len = 2;
6257ee85054SArec Kao 	msgs[0].buf = (u8 *)&reg_addr_be;
6267ee85054SArec Kao 
6277ee85054SArec Kao 	/* Read data from register */
6287ee85054SArec Kao 	msgs[1].addr = client->addr;
6297ee85054SArec Kao 	msgs[1].flags = I2C_M_RD;
6307ee85054SArec Kao 	msgs[1].len = len;
6317ee85054SArec Kao 	msgs[1].buf = &data_be_p[4 - len];
6327ee85054SArec Kao 
6337ee85054SArec Kao 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
6347ee85054SArec Kao 	if (ret != ARRAY_SIZE(msgs))
6357ee85054SArec Kao 		return -EIO;
6367ee85054SArec Kao 
6377ee85054SArec Kao 	*val = be32_to_cpu(data_be);
6387ee85054SArec Kao 
6397ee85054SArec Kao 	return 0;
6407ee85054SArec Kao }
6417ee85054SArec Kao 
6427ee85054SArec Kao /* Write registers up to 4 at a time */
ov13b10_write_reg(struct ov13b10 * ov13b,u16 reg,u32 len,u32 __val)6437ee85054SArec Kao static int ov13b10_write_reg(struct ov13b10 *ov13b,
6447ee85054SArec Kao 			     u16 reg, u32 len, u32 __val)
6457ee85054SArec Kao {
6467ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
6477ee85054SArec Kao 	int buf_i, val_i;
6487ee85054SArec Kao 	u8 buf[6], *val_p;
6497ee85054SArec Kao 	__be32 val;
6507ee85054SArec Kao 
6517ee85054SArec Kao 	if (len > 4)
6527ee85054SArec Kao 		return -EINVAL;
6537ee85054SArec Kao 
6547ee85054SArec Kao 	buf[0] = reg >> 8;
6557ee85054SArec Kao 	buf[1] = reg & 0xff;
6567ee85054SArec Kao 
6577ee85054SArec Kao 	val = cpu_to_be32(__val);
6587ee85054SArec Kao 	val_p = (u8 *)&val;
6597ee85054SArec Kao 	buf_i = 2;
6607ee85054SArec Kao 	val_i = 4 - len;
6617ee85054SArec Kao 
6627ee85054SArec Kao 	while (val_i < 4)
6637ee85054SArec Kao 		buf[buf_i++] = val_p[val_i++];
6647ee85054SArec Kao 
6657ee85054SArec Kao 	if (i2c_master_send(client, buf, len + 2) != len + 2)
6667ee85054SArec Kao 		return -EIO;
6677ee85054SArec Kao 
6687ee85054SArec Kao 	return 0;
6697ee85054SArec Kao }
6707ee85054SArec Kao 
6717ee85054SArec Kao /* Write a list of registers */
ov13b10_write_regs(struct ov13b10 * ov13b,const struct ov13b10_reg * regs,u32 len)6727ee85054SArec Kao static int ov13b10_write_regs(struct ov13b10 *ov13b,
6737ee85054SArec Kao 			      const struct ov13b10_reg *regs, u32 len)
6747ee85054SArec Kao {
6757ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
6767ee85054SArec Kao 	int ret;
6777ee85054SArec Kao 	u32 i;
6787ee85054SArec Kao 
6797ee85054SArec Kao 	for (i = 0; i < len; i++) {
6807ee85054SArec Kao 		ret = ov13b10_write_reg(ov13b, regs[i].address, 1,
6817ee85054SArec Kao 					regs[i].val);
6827ee85054SArec Kao 		if (ret) {
6837ee85054SArec Kao 			dev_err_ratelimited(&client->dev,
6847ee85054SArec Kao 					    "Failed to write reg 0x%4.4x. error = %d\n",
6857ee85054SArec Kao 					    regs[i].address, ret);
6867ee85054SArec Kao 
6877ee85054SArec Kao 			return ret;
6887ee85054SArec Kao 		}
6897ee85054SArec Kao 	}
6907ee85054SArec Kao 
6917ee85054SArec Kao 	return 0;
6927ee85054SArec Kao }
6937ee85054SArec Kao 
ov13b10_write_reg_list(struct ov13b10 * ov13b,const struct ov13b10_reg_list * r_list)6947ee85054SArec Kao static int ov13b10_write_reg_list(struct ov13b10 *ov13b,
6957ee85054SArec Kao 				  const struct ov13b10_reg_list *r_list)
6967ee85054SArec Kao {
6977ee85054SArec Kao 	return ov13b10_write_regs(ov13b, r_list->regs, r_list->num_of_regs);
6987ee85054SArec Kao }
6997ee85054SArec Kao 
7007ee85054SArec Kao /* Open sub-device */
ov13b10_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)7017ee85054SArec Kao static int ov13b10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
7027ee85054SArec Kao {
7037ee85054SArec Kao 	const struct ov13b10_mode *default_mode = &supported_modes[0];
7047ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
7057ee85054SArec Kao 	struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(sd,
7067ee85054SArec Kao 									fh->state,
7077ee85054SArec Kao 									0);
7087ee85054SArec Kao 
7097ee85054SArec Kao 	mutex_lock(&ov13b->mutex);
7107ee85054SArec Kao 
7117ee85054SArec Kao 	/* Initialize try_fmt */
7127ee85054SArec Kao 	try_fmt->width = default_mode->width;
7137ee85054SArec Kao 	try_fmt->height = default_mode->height;
7147ee85054SArec Kao 	try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
7157ee85054SArec Kao 	try_fmt->field = V4L2_FIELD_NONE;
7167ee85054SArec Kao 
7177ee85054SArec Kao 	/* No crop or compose */
7187ee85054SArec Kao 	mutex_unlock(&ov13b->mutex);
7197ee85054SArec Kao 
7207ee85054SArec Kao 	return 0;
7217ee85054SArec Kao }
7227ee85054SArec Kao 
ov13b10_update_digital_gain(struct ov13b10 * ov13b,u32 d_gain)7237ee85054SArec Kao static int ov13b10_update_digital_gain(struct ov13b10 *ov13b, u32 d_gain)
7247ee85054SArec Kao {
7257ee85054SArec Kao 	int ret;
7267ee85054SArec Kao 	u32 val;
7277ee85054SArec Kao 
7287ee85054SArec Kao 	/*
7297ee85054SArec Kao 	 * 0x350C[7:6], 0x350B[7:0], 0x350A[1:0]
7307ee85054SArec Kao 	 */
7317ee85054SArec Kao 
7327ee85054SArec Kao 	val = (d_gain & OV13B10_DGTL_GAIN_L_MASK) << OV13B10_DGTL_GAIN_L_SHIFT;
7337ee85054SArec Kao 	ret = ov13b10_write_reg(ov13b, OV13B10_REG_DGTL_GAIN_L,
7347ee85054SArec Kao 				OV13B10_REG_VALUE_08BIT, val);
7357ee85054SArec Kao 	if (ret)
7367ee85054SArec Kao 		return ret;
7377ee85054SArec Kao 
7387ee85054SArec Kao 	val = (d_gain >> OV13B10_DGTL_GAIN_M_SHIFT) & OV13B10_DGTL_GAIN_M_MASK;
7397ee85054SArec Kao 	ret = ov13b10_write_reg(ov13b, OV13B10_REG_DGTL_GAIN_M,
7407ee85054SArec Kao 				OV13B10_REG_VALUE_08BIT, val);
7417ee85054SArec Kao 	if (ret)
7427ee85054SArec Kao 		return ret;
7437ee85054SArec Kao 
7447ee85054SArec Kao 	val = (d_gain >> OV13B10_DGTL_GAIN_H_SHIFT) & OV13B10_DGTL_GAIN_H_MASK;
7457ee85054SArec Kao 	ret = ov13b10_write_reg(ov13b, OV13B10_REG_DGTL_GAIN_H,
7467ee85054SArec Kao 				OV13B10_REG_VALUE_08BIT, val);
7477ee85054SArec Kao 
7487ee85054SArec Kao 	return ret;
7497ee85054SArec Kao }
7507ee85054SArec Kao 
ov13b10_enable_test_pattern(struct ov13b10 * ov13b,u32 pattern)7517ee85054SArec Kao static int ov13b10_enable_test_pattern(struct ov13b10 *ov13b, u32 pattern)
7527ee85054SArec Kao {
7537ee85054SArec Kao 	int ret;
7547ee85054SArec Kao 	u32 val;
7557ee85054SArec Kao 
7567ee85054SArec Kao 	ret = ov13b10_read_reg(ov13b, OV13B10_REG_TEST_PATTERN,
7577ee85054SArec Kao 			       OV13B10_REG_VALUE_08BIT, &val);
7587ee85054SArec Kao 	if (ret)
7597ee85054SArec Kao 		return ret;
7607ee85054SArec Kao 
7617ee85054SArec Kao 	if (pattern) {
7627ee85054SArec Kao 		val &= OV13B10_TEST_PATTERN_MASK;
7637ee85054SArec Kao 		val |= ((pattern - 1) << OV13B10_TEST_PATTERN_BAR_SHIFT) |
7647ee85054SArec Kao 		     OV13B10_TEST_PATTERN_ENABLE;
7657ee85054SArec Kao 	} else {
7667ee85054SArec Kao 		val &= ~OV13B10_TEST_PATTERN_ENABLE;
7677ee85054SArec Kao 	}
7687ee85054SArec Kao 
7697ee85054SArec Kao 	return ov13b10_write_reg(ov13b, OV13B10_REG_TEST_PATTERN,
7707ee85054SArec Kao 				 OV13B10_REG_VALUE_08BIT, val);
7717ee85054SArec Kao }
7727ee85054SArec Kao 
ov13b10_set_ctrl_hflip(struct ov13b10 * ov13b,u32 ctrl_val)7737ee85054SArec Kao static int ov13b10_set_ctrl_hflip(struct ov13b10 *ov13b, u32 ctrl_val)
7747ee85054SArec Kao {
7757ee85054SArec Kao 	int ret;
7767ee85054SArec Kao 	u32 val;
7777ee85054SArec Kao 
7787ee85054SArec Kao 	ret = ov13b10_read_reg(ov13b, OV13B10_REG_FORMAT1,
7797ee85054SArec Kao 			       OV13B10_REG_VALUE_08BIT, &val);
7807ee85054SArec Kao 	if (ret)
7817ee85054SArec Kao 		return ret;
7827ee85054SArec Kao 
7837ee85054SArec Kao 	ret = ov13b10_write_reg(ov13b, OV13B10_REG_FORMAT1,
7847ee85054SArec Kao 				OV13B10_REG_VALUE_08BIT,
7857ee85054SArec Kao 				ctrl_val ? val & ~BIT(3) : val);
7867ee85054SArec Kao 
7877ee85054SArec Kao 	if (ret)
7887ee85054SArec Kao 		return ret;
7897ee85054SArec Kao 
7907ee85054SArec Kao 	ret = ov13b10_read_reg(ov13b, OV13B10_REG_H_WIN_OFFSET,
7917ee85054SArec Kao 			       OV13B10_REG_VALUE_08BIT, &val);
7927ee85054SArec Kao 	if (ret)
7937ee85054SArec Kao 		return ret;
7947ee85054SArec Kao 
7957ee85054SArec Kao 	/*
7967ee85054SArec Kao 	 * Applying cropping offset to reverse the change of Bayer order
7977ee85054SArec Kao 	 * after mirroring image
7987ee85054SArec Kao 	 */
7997ee85054SArec Kao 	return ov13b10_write_reg(ov13b, OV13B10_REG_H_WIN_OFFSET,
8007ee85054SArec Kao 				 OV13B10_REG_VALUE_08BIT,
8017ee85054SArec Kao 				 ctrl_val ? ++val : val);
8027ee85054SArec Kao }
8037ee85054SArec Kao 
ov13b10_set_ctrl_vflip(struct ov13b10 * ov13b,u32 ctrl_val)8047ee85054SArec Kao static int ov13b10_set_ctrl_vflip(struct ov13b10 *ov13b, u32 ctrl_val)
8057ee85054SArec Kao {
8067ee85054SArec Kao 	int ret;
8077ee85054SArec Kao 	u32 val;
8087ee85054SArec Kao 
8097ee85054SArec Kao 	ret = ov13b10_read_reg(ov13b, OV13B10_REG_FORMAT1,
8107ee85054SArec Kao 			       OV13B10_REG_VALUE_08BIT, &val);
8117ee85054SArec Kao 	if (ret)
8127ee85054SArec Kao 		return ret;
8137ee85054SArec Kao 
8147ee85054SArec Kao 	ret = ov13b10_write_reg(ov13b, OV13B10_REG_FORMAT1,
8157ee85054SArec Kao 				OV13B10_REG_VALUE_08BIT,
8167ee85054SArec Kao 				ctrl_val ? val | BIT(4) | BIT(5)  : val);
8177ee85054SArec Kao 
8187ee85054SArec Kao 	if (ret)
8197ee85054SArec Kao 		return ret;
8207ee85054SArec Kao 
8217ee85054SArec Kao 	ret = ov13b10_read_reg(ov13b, OV13B10_REG_V_WIN_OFFSET,
8227ee85054SArec Kao 			       OV13B10_REG_VALUE_08BIT, &val);
8237ee85054SArec Kao 	if (ret)
8247ee85054SArec Kao 		return ret;
8257ee85054SArec Kao 
8267ee85054SArec Kao 	/*
8277ee85054SArec Kao 	 * Applying cropping offset to reverse the change of Bayer order
8287ee85054SArec Kao 	 * after flipping image
8297ee85054SArec Kao 	 */
8307ee85054SArec Kao 	return ov13b10_write_reg(ov13b, OV13B10_REG_V_WIN_OFFSET,
8317ee85054SArec Kao 				 OV13B10_REG_VALUE_08BIT,
8327ee85054SArec Kao 				 ctrl_val ? --val : val);
8337ee85054SArec Kao }
8347ee85054SArec Kao 
ov13b10_set_ctrl(struct v4l2_ctrl * ctrl)8357ee85054SArec Kao static int ov13b10_set_ctrl(struct v4l2_ctrl *ctrl)
8367ee85054SArec Kao {
8377ee85054SArec Kao 	struct ov13b10 *ov13b = container_of(ctrl->handler,
8387ee85054SArec Kao 					     struct ov13b10, ctrl_handler);
8397ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
8407ee85054SArec Kao 	s64 max;
8417ee85054SArec Kao 	int ret;
8427ee85054SArec Kao 
8437ee85054SArec Kao 	/* Propagate change of current control to all related controls */
8447ee85054SArec Kao 	switch (ctrl->id) {
8457ee85054SArec Kao 	case V4L2_CID_VBLANK:
8467ee85054SArec Kao 		/* Update max exposure while meeting expected vblanking */
8477ee85054SArec Kao 		max = ov13b->cur_mode->height + ctrl->val - 8;
8487ee85054SArec Kao 		__v4l2_ctrl_modify_range(ov13b->exposure,
8497ee85054SArec Kao 					 ov13b->exposure->minimum,
8507ee85054SArec Kao 					 max, ov13b->exposure->step, max);
8517ee85054SArec Kao 		break;
8527ee85054SArec Kao 	}
8537ee85054SArec Kao 
8547ee85054SArec Kao 	/*
8557ee85054SArec Kao 	 * Applying V4L2 control value only happens
8567ee85054SArec Kao 	 * when power is up for streaming
8577ee85054SArec Kao 	 */
8587ee85054SArec Kao 	if (!pm_runtime_get_if_in_use(&client->dev))
8597ee85054SArec Kao 		return 0;
8607ee85054SArec Kao 
8617ee85054SArec Kao 	ret = 0;
8627ee85054SArec Kao 	switch (ctrl->id) {
8637ee85054SArec Kao 	case V4L2_CID_ANALOGUE_GAIN:
8647ee85054SArec Kao 		ret = ov13b10_write_reg(ov13b, OV13B10_REG_ANALOG_GAIN,
8657ee85054SArec Kao 					OV13B10_REG_VALUE_16BIT,
8667ee85054SArec Kao 					ctrl->val << 1);
8677ee85054SArec Kao 		break;
8687ee85054SArec Kao 	case V4L2_CID_DIGITAL_GAIN:
8697ee85054SArec Kao 		ret = ov13b10_update_digital_gain(ov13b, ctrl->val);
8707ee85054SArec Kao 		break;
8717ee85054SArec Kao 	case V4L2_CID_EXPOSURE:
8727ee85054SArec Kao 		ret = ov13b10_write_reg(ov13b, OV13B10_REG_EXPOSURE,
8737ee85054SArec Kao 					OV13B10_REG_VALUE_24BIT,
8747ee85054SArec Kao 					ctrl->val);
8757ee85054SArec Kao 		break;
8767ee85054SArec Kao 	case V4L2_CID_VBLANK:
8777ee85054SArec Kao 		ret = ov13b10_write_reg(ov13b, OV13B10_REG_VTS,
8787ee85054SArec Kao 					OV13B10_REG_VALUE_16BIT,
8797ee85054SArec Kao 					ov13b->cur_mode->height
8807ee85054SArec Kao 					+ ctrl->val);
8817ee85054SArec Kao 		break;
8827ee85054SArec Kao 	case V4L2_CID_TEST_PATTERN:
8837ee85054SArec Kao 		ret = ov13b10_enable_test_pattern(ov13b, ctrl->val);
8847ee85054SArec Kao 		break;
8857ee85054SArec Kao 	case V4L2_CID_HFLIP:
8867ee85054SArec Kao 		ov13b10_set_ctrl_hflip(ov13b, ctrl->val);
8877ee85054SArec Kao 		break;
8887ee85054SArec Kao 	case V4L2_CID_VFLIP:
8897ee85054SArec Kao 		ov13b10_set_ctrl_vflip(ov13b, ctrl->val);
8907ee85054SArec Kao 		break;
8917ee85054SArec Kao 	default:
8927ee85054SArec Kao 		dev_info(&client->dev,
8937ee85054SArec Kao 			 "ctrl(id:0x%x,val:0x%x) is not handled\n",
8947ee85054SArec Kao 			 ctrl->id, ctrl->val);
8957ee85054SArec Kao 		break;
8967ee85054SArec Kao 	}
8977ee85054SArec Kao 
8987ee85054SArec Kao 	pm_runtime_put(&client->dev);
8997ee85054SArec Kao 
9007ee85054SArec Kao 	return ret;
9017ee85054SArec Kao }
9027ee85054SArec Kao 
9037ee85054SArec Kao static const struct v4l2_ctrl_ops ov13b10_ctrl_ops = {
9047ee85054SArec Kao 	.s_ctrl = ov13b10_set_ctrl,
9057ee85054SArec Kao };
9067ee85054SArec Kao 
ov13b10_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)9077ee85054SArec Kao static int ov13b10_enum_mbus_code(struct v4l2_subdev *sd,
9087ee85054SArec Kao 				  struct v4l2_subdev_state *sd_state,
9097ee85054SArec Kao 				  struct v4l2_subdev_mbus_code_enum *code)
9107ee85054SArec Kao {
9117ee85054SArec Kao 	/* Only one bayer order(GRBG) is supported */
9127ee85054SArec Kao 	if (code->index > 0)
9137ee85054SArec Kao 		return -EINVAL;
9147ee85054SArec Kao 
9157ee85054SArec Kao 	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
9167ee85054SArec Kao 
9177ee85054SArec Kao 	return 0;
9187ee85054SArec Kao }
9197ee85054SArec Kao 
ov13b10_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)9207ee85054SArec Kao static int ov13b10_enum_frame_size(struct v4l2_subdev *sd,
9217ee85054SArec Kao 				   struct v4l2_subdev_state *sd_state,
9227ee85054SArec Kao 				   struct v4l2_subdev_frame_size_enum *fse)
9237ee85054SArec Kao {
9247ee85054SArec Kao 	if (fse->index >= ARRAY_SIZE(supported_modes))
9257ee85054SArec Kao 		return -EINVAL;
9267ee85054SArec Kao 
9277ee85054SArec Kao 	if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
9287ee85054SArec Kao 		return -EINVAL;
9297ee85054SArec Kao 
9307ee85054SArec Kao 	fse->min_width = supported_modes[fse->index].width;
9317ee85054SArec Kao 	fse->max_width = fse->min_width;
9327ee85054SArec Kao 	fse->min_height = supported_modes[fse->index].height;
9337ee85054SArec Kao 	fse->max_height = fse->min_height;
9347ee85054SArec Kao 
9357ee85054SArec Kao 	return 0;
9367ee85054SArec Kao }
9377ee85054SArec Kao 
ov13b10_update_pad_format(const struct ov13b10_mode * mode,struct v4l2_subdev_format * fmt)9387ee85054SArec Kao static void ov13b10_update_pad_format(const struct ov13b10_mode *mode,
9397ee85054SArec Kao 				      struct v4l2_subdev_format *fmt)
9407ee85054SArec Kao {
9417ee85054SArec Kao 	fmt->format.width = mode->width;
9427ee85054SArec Kao 	fmt->format.height = mode->height;
9437ee85054SArec Kao 	fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
9447ee85054SArec Kao 	fmt->format.field = V4L2_FIELD_NONE;
9457ee85054SArec Kao }
9467ee85054SArec Kao 
ov13b10_do_get_pad_format(struct ov13b10 * ov13b,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)9477ee85054SArec Kao static int ov13b10_do_get_pad_format(struct ov13b10 *ov13b,
9487ee85054SArec Kao 				     struct v4l2_subdev_state *sd_state,
9497ee85054SArec Kao 				     struct v4l2_subdev_format *fmt)
9507ee85054SArec Kao {
9517ee85054SArec Kao 	struct v4l2_mbus_framefmt *framefmt;
9527ee85054SArec Kao 	struct v4l2_subdev *sd = &ov13b->sd;
9537ee85054SArec Kao 
9547ee85054SArec Kao 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
9557ee85054SArec Kao 		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
9567ee85054SArec Kao 		fmt->format = *framefmt;
9577ee85054SArec Kao 	} else {
9587ee85054SArec Kao 		ov13b10_update_pad_format(ov13b->cur_mode, fmt);
9597ee85054SArec Kao 	}
9607ee85054SArec Kao 
9617ee85054SArec Kao 	return 0;
9627ee85054SArec Kao }
9637ee85054SArec Kao 
ov13b10_get_pad_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)9647ee85054SArec Kao static int ov13b10_get_pad_format(struct v4l2_subdev *sd,
9657ee85054SArec Kao 				  struct v4l2_subdev_state *sd_state,
9667ee85054SArec Kao 				  struct v4l2_subdev_format *fmt)
9677ee85054SArec Kao {
9687ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
9697ee85054SArec Kao 	int ret;
9707ee85054SArec Kao 
9717ee85054SArec Kao 	mutex_lock(&ov13b->mutex);
9727ee85054SArec Kao 	ret = ov13b10_do_get_pad_format(ov13b, sd_state, fmt);
9737ee85054SArec Kao 	mutex_unlock(&ov13b->mutex);
9747ee85054SArec Kao 
9757ee85054SArec Kao 	return ret;
9767ee85054SArec Kao }
9777ee85054SArec Kao 
9787ee85054SArec Kao static int
ov13b10_set_pad_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)9797ee85054SArec Kao ov13b10_set_pad_format(struct v4l2_subdev *sd,
9807ee85054SArec Kao 		       struct v4l2_subdev_state *sd_state,
9817ee85054SArec Kao 		       struct v4l2_subdev_format *fmt)
9827ee85054SArec Kao {
9837ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
9847ee85054SArec Kao 	const struct ov13b10_mode *mode;
9857ee85054SArec Kao 	struct v4l2_mbus_framefmt *framefmt;
9867ee85054SArec Kao 	s32 vblank_def;
9877ee85054SArec Kao 	s32 vblank_min;
9887ee85054SArec Kao 	s64 h_blank;
9897ee85054SArec Kao 	s64 pixel_rate;
9907ee85054SArec Kao 	s64 link_freq;
9917ee85054SArec Kao 
9927ee85054SArec Kao 	mutex_lock(&ov13b->mutex);
9937ee85054SArec Kao 
9947ee85054SArec Kao 	/* Only one raw bayer(GRBG) order is supported */
9957ee85054SArec Kao 	if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10)
9967ee85054SArec Kao 		fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
9977ee85054SArec Kao 
9987ee85054SArec Kao 	mode = v4l2_find_nearest_size(supported_modes,
9997ee85054SArec Kao 				      ARRAY_SIZE(supported_modes),
10007ee85054SArec Kao 				      width, height,
10017ee85054SArec Kao 				      fmt->format.width, fmt->format.height);
10027ee85054SArec Kao 	ov13b10_update_pad_format(mode, fmt);
10037ee85054SArec Kao 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
10047ee85054SArec Kao 		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
10057ee85054SArec Kao 		*framefmt = fmt->format;
10067ee85054SArec Kao 	} else {
10077ee85054SArec Kao 		ov13b->cur_mode = mode;
10087ee85054SArec Kao 		__v4l2_ctrl_s_ctrl(ov13b->link_freq, mode->link_freq_index);
10097ee85054SArec Kao 		link_freq = link_freq_menu_items[mode->link_freq_index];
10107ee85054SArec Kao 		pixel_rate = link_freq_to_pixel_rate(link_freq);
10117ee85054SArec Kao 		__v4l2_ctrl_s_ctrl_int64(ov13b->pixel_rate, pixel_rate);
10127ee85054SArec Kao 
10137ee85054SArec Kao 		/* Update limits and set FPS to default */
10147ee85054SArec Kao 		vblank_def = ov13b->cur_mode->vts_def -
10157ee85054SArec Kao 			     ov13b->cur_mode->height;
10167ee85054SArec Kao 		vblank_min = ov13b->cur_mode->vts_min -
10177ee85054SArec Kao 			     ov13b->cur_mode->height;
10187ee85054SArec Kao 		__v4l2_ctrl_modify_range(ov13b->vblank, vblank_min,
10197ee85054SArec Kao 					 OV13B10_VTS_MAX
10207ee85054SArec Kao 					 - ov13b->cur_mode->height,
10217ee85054SArec Kao 					 1,
10227ee85054SArec Kao 					 vblank_def);
10237ee85054SArec Kao 		__v4l2_ctrl_s_ctrl(ov13b->vblank, vblank_def);
10247ee85054SArec Kao 		h_blank =
10257ee85054SArec Kao 			link_freq_configs[mode->link_freq_index].pixels_per_line
10267ee85054SArec Kao 			 - ov13b->cur_mode->width;
10277ee85054SArec Kao 		__v4l2_ctrl_modify_range(ov13b->hblank, h_blank,
10287ee85054SArec Kao 					 h_blank, 1, h_blank);
10297ee85054SArec Kao 	}
10307ee85054SArec Kao 
10317ee85054SArec Kao 	mutex_unlock(&ov13b->mutex);
10327ee85054SArec Kao 
10337ee85054SArec Kao 	return 0;
10347ee85054SArec Kao }
10357ee85054SArec Kao 
10361af2f618SArec Kao /* Verify chip ID */
ov13b10_identify_module(struct ov13b10 * ov13b)10371af2f618SArec Kao static int ov13b10_identify_module(struct ov13b10 *ov13b)
10381af2f618SArec Kao {
10391af2f618SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
10401af2f618SArec Kao 	int ret;
10411af2f618SArec Kao 	u32 val;
10421af2f618SArec Kao 
10431af2f618SArec Kao 	if (ov13b->identified)
10441af2f618SArec Kao 		return 0;
10451af2f618SArec Kao 
10461af2f618SArec Kao 	ret = ov13b10_read_reg(ov13b, OV13B10_REG_CHIP_ID,
10471af2f618SArec Kao 			       OV13B10_REG_VALUE_24BIT, &val);
10481af2f618SArec Kao 	if (ret)
10491af2f618SArec Kao 		return ret;
10501af2f618SArec Kao 
10511af2f618SArec Kao 	if (val != OV13B10_CHIP_ID) {
10521af2f618SArec Kao 		dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
10531af2f618SArec Kao 			OV13B10_CHIP_ID, val);
10541af2f618SArec Kao 		return -EIO;
10551af2f618SArec Kao 	}
10561af2f618SArec Kao 
10571af2f618SArec Kao 	ov13b->identified = true;
10581af2f618SArec Kao 
10591af2f618SArec Kao 	return 0;
10601af2f618SArec Kao }
10611af2f618SArec Kao 
ov13b10_power_off(struct device * dev)10626e28afd1SBingbu Cao static int ov13b10_power_off(struct device *dev)
10636e28afd1SBingbu Cao {
10646e28afd1SBingbu Cao 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
10656e28afd1SBingbu Cao 	struct ov13b10 *ov13b10 = to_ov13b10(sd);
10666e28afd1SBingbu Cao 
10676e28afd1SBingbu Cao 	gpiod_set_value_cansleep(ov13b10->reset, 1);
10686e28afd1SBingbu Cao 
10696e28afd1SBingbu Cao 	if (ov13b10->avdd)
10706e28afd1SBingbu Cao 		regulator_disable(ov13b10->avdd);
10716e28afd1SBingbu Cao 
10726e28afd1SBingbu Cao 	clk_disable_unprepare(ov13b10->img_clk);
10736e28afd1SBingbu Cao 
10746e28afd1SBingbu Cao 	return 0;
10756e28afd1SBingbu Cao }
10766e28afd1SBingbu Cao 
ov13b10_power_on(struct device * dev)10776e28afd1SBingbu Cao static int ov13b10_power_on(struct device *dev)
10786e28afd1SBingbu Cao {
10796e28afd1SBingbu Cao 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
10806e28afd1SBingbu Cao 	struct ov13b10 *ov13b10 = to_ov13b10(sd);
10816e28afd1SBingbu Cao 	int ret;
10826e28afd1SBingbu Cao 
10836e28afd1SBingbu Cao 	ret = clk_prepare_enable(ov13b10->img_clk);
10846e28afd1SBingbu Cao 	if (ret < 0) {
10856e28afd1SBingbu Cao 		dev_err(dev, "failed to enable imaging clock: %d", ret);
10866e28afd1SBingbu Cao 		return ret;
10876e28afd1SBingbu Cao 	}
10886e28afd1SBingbu Cao 
10896e28afd1SBingbu Cao 	if (ov13b10->avdd) {
10906e28afd1SBingbu Cao 		ret = regulator_enable(ov13b10->avdd);
10916e28afd1SBingbu Cao 		if (ret < 0) {
10926e28afd1SBingbu Cao 			dev_err(dev, "failed to enable avdd: %d", ret);
10936e28afd1SBingbu Cao 			clk_disable_unprepare(ov13b10->img_clk);
10946e28afd1SBingbu Cao 			return ret;
10956e28afd1SBingbu Cao 		}
10966e28afd1SBingbu Cao 	}
10976e28afd1SBingbu Cao 
10986e28afd1SBingbu Cao 	gpiod_set_value_cansleep(ov13b10->reset, 0);
10996e28afd1SBingbu Cao 	/* 5ms to wait ready after XSHUTDN assert */
11006e28afd1SBingbu Cao 	usleep_range(5000, 5500);
11016e28afd1SBingbu Cao 
11026e28afd1SBingbu Cao 	return 0;
11036e28afd1SBingbu Cao }
11046e28afd1SBingbu Cao 
ov13b10_start_streaming(struct ov13b10 * ov13b)11057ee85054SArec Kao static int ov13b10_start_streaming(struct ov13b10 *ov13b)
11067ee85054SArec Kao {
11077ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
11087ee85054SArec Kao 	const struct ov13b10_reg_list *reg_list;
11097ee85054SArec Kao 	int ret, link_freq_index;
11107ee85054SArec Kao 
11111af2f618SArec Kao 	ret = ov13b10_identify_module(ov13b);
11121af2f618SArec Kao 	if (ret)
11131af2f618SArec Kao 		return ret;
11141af2f618SArec Kao 
11157ee85054SArec Kao 	/* Get out of from software reset */
11167ee85054SArec Kao 	ret = ov13b10_write_reg(ov13b, OV13B10_REG_SOFTWARE_RST,
11177ee85054SArec Kao 				OV13B10_REG_VALUE_08BIT, OV13B10_SOFTWARE_RST);
11187ee85054SArec Kao 	if (ret) {
11197ee85054SArec Kao 		dev_err(&client->dev, "%s failed to set powerup registers\n",
11207ee85054SArec Kao 			__func__);
11217ee85054SArec Kao 		return ret;
11227ee85054SArec Kao 	}
11237ee85054SArec Kao 
11247ee85054SArec Kao 	link_freq_index = ov13b->cur_mode->link_freq_index;
11257ee85054SArec Kao 	reg_list = &link_freq_configs[link_freq_index].reg_list;
11267ee85054SArec Kao 	ret = ov13b10_write_reg_list(ov13b, reg_list);
11277ee85054SArec Kao 	if (ret) {
11287ee85054SArec Kao 		dev_err(&client->dev, "%s failed to set plls\n", __func__);
11297ee85054SArec Kao 		return ret;
11307ee85054SArec Kao 	}
11317ee85054SArec Kao 
11327ee85054SArec Kao 	/* Apply default values of current mode */
11337ee85054SArec Kao 	reg_list = &ov13b->cur_mode->reg_list;
11347ee85054SArec Kao 	ret = ov13b10_write_reg_list(ov13b, reg_list);
11357ee85054SArec Kao 	if (ret) {
11367ee85054SArec Kao 		dev_err(&client->dev, "%s failed to set mode\n", __func__);
11377ee85054SArec Kao 		return ret;
11387ee85054SArec Kao 	}
11397ee85054SArec Kao 
11407ee85054SArec Kao 	/* Apply customized values from user */
11417ee85054SArec Kao 	ret =  __v4l2_ctrl_handler_setup(ov13b->sd.ctrl_handler);
11427ee85054SArec Kao 	if (ret)
11437ee85054SArec Kao 		return ret;
11447ee85054SArec Kao 
11457ee85054SArec Kao 	return ov13b10_write_reg(ov13b, OV13B10_REG_MODE_SELECT,
11467ee85054SArec Kao 				 OV13B10_REG_VALUE_08BIT,
11477ee85054SArec Kao 				 OV13B10_MODE_STREAMING);
11487ee85054SArec Kao }
11497ee85054SArec Kao 
11507ee85054SArec Kao /* Stop streaming */
ov13b10_stop_streaming(struct ov13b10 * ov13b)11517ee85054SArec Kao static int ov13b10_stop_streaming(struct ov13b10 *ov13b)
11527ee85054SArec Kao {
11537ee85054SArec Kao 	return ov13b10_write_reg(ov13b, OV13B10_REG_MODE_SELECT,
11547ee85054SArec Kao 				 OV13B10_REG_VALUE_08BIT, OV13B10_MODE_STANDBY);
11557ee85054SArec Kao }
11567ee85054SArec Kao 
ov13b10_set_stream(struct v4l2_subdev * sd,int enable)11577ee85054SArec Kao static int ov13b10_set_stream(struct v4l2_subdev *sd, int enable)
11587ee85054SArec Kao {
11597ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
11607ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(sd);
11617ee85054SArec Kao 	int ret = 0;
11627ee85054SArec Kao 
11637ee85054SArec Kao 	mutex_lock(&ov13b->mutex);
11647ee85054SArec Kao 	if (ov13b->streaming == enable) {
11657ee85054SArec Kao 		mutex_unlock(&ov13b->mutex);
11667ee85054SArec Kao 		return 0;
11677ee85054SArec Kao 	}
11687ee85054SArec Kao 
11697ee85054SArec Kao 	if (enable) {
11707ee85054SArec Kao 		ret = pm_runtime_resume_and_get(&client->dev);
11717ee85054SArec Kao 		if (ret < 0)
11727ee85054SArec Kao 			goto err_unlock;
11737ee85054SArec Kao 
11747ee85054SArec Kao 		/*
11757ee85054SArec Kao 		 * Apply default & customized values
11767ee85054SArec Kao 		 * and then start streaming.
11777ee85054SArec Kao 		 */
11787ee85054SArec Kao 		ret = ov13b10_start_streaming(ov13b);
11797ee85054SArec Kao 		if (ret)
11807ee85054SArec Kao 			goto err_rpm_put;
11817ee85054SArec Kao 	} else {
11827ee85054SArec Kao 		ov13b10_stop_streaming(ov13b);
11837ee85054SArec Kao 		pm_runtime_put(&client->dev);
11847ee85054SArec Kao 	}
11857ee85054SArec Kao 
11867ee85054SArec Kao 	ov13b->streaming = enable;
11877ee85054SArec Kao 	mutex_unlock(&ov13b->mutex);
11887ee85054SArec Kao 
11897ee85054SArec Kao 	return ret;
11907ee85054SArec Kao 
11917ee85054SArec Kao err_rpm_put:
11927ee85054SArec Kao 	pm_runtime_put(&client->dev);
11937ee85054SArec Kao err_unlock:
11947ee85054SArec Kao 	mutex_unlock(&ov13b->mutex);
11957ee85054SArec Kao 
11967ee85054SArec Kao 	return ret;
11977ee85054SArec Kao }
11987ee85054SArec Kao 
ov13b10_suspend(struct device * dev)11996e28afd1SBingbu Cao static int ov13b10_suspend(struct device *dev)
12007ee85054SArec Kao {
12017ee85054SArec Kao 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
12027ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
12037ee85054SArec Kao 
12047ee85054SArec Kao 	if (ov13b->streaming)
12057ee85054SArec Kao 		ov13b10_stop_streaming(ov13b);
12067ee85054SArec Kao 
12076e28afd1SBingbu Cao 	ov13b10_power_off(dev);
12086e28afd1SBingbu Cao 
12097ee85054SArec Kao 	return 0;
12107ee85054SArec Kao }
12117ee85054SArec Kao 
ov13b10_resume(struct device * dev)12126e28afd1SBingbu Cao static int ov13b10_resume(struct device *dev)
12137ee85054SArec Kao {
12147ee85054SArec Kao 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
12157ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
12167ee85054SArec Kao 	int ret;
12177ee85054SArec Kao 
12186e28afd1SBingbu Cao 	ret = ov13b10_power_on(dev);
12196e28afd1SBingbu Cao 	if (ret)
12206e28afd1SBingbu Cao 		goto pm_fail;
12216e28afd1SBingbu Cao 
12227ee85054SArec Kao 	if (ov13b->streaming) {
12237ee85054SArec Kao 		ret = ov13b10_start_streaming(ov13b);
12247ee85054SArec Kao 		if (ret)
12256e28afd1SBingbu Cao 			goto stop_streaming;
12267ee85054SArec Kao 	}
12277ee85054SArec Kao 
12287ee85054SArec Kao 	return 0;
12297ee85054SArec Kao 
12306e28afd1SBingbu Cao stop_streaming:
12317ee85054SArec Kao 	ov13b10_stop_streaming(ov13b);
12326e28afd1SBingbu Cao 	ov13b10_power_off(dev);
12336e28afd1SBingbu Cao pm_fail:
12347ee85054SArec Kao 	ov13b->streaming = false;
12356e28afd1SBingbu Cao 
12367ee85054SArec Kao 	return ret;
12377ee85054SArec Kao }
12387ee85054SArec Kao 
12397ee85054SArec Kao static const struct v4l2_subdev_video_ops ov13b10_video_ops = {
12407ee85054SArec Kao 	.s_stream = ov13b10_set_stream,
12417ee85054SArec Kao };
12427ee85054SArec Kao 
12437ee85054SArec Kao static const struct v4l2_subdev_pad_ops ov13b10_pad_ops = {
12447ee85054SArec Kao 	.enum_mbus_code = ov13b10_enum_mbus_code,
12457ee85054SArec Kao 	.get_fmt = ov13b10_get_pad_format,
12467ee85054SArec Kao 	.set_fmt = ov13b10_set_pad_format,
12477ee85054SArec Kao 	.enum_frame_size = ov13b10_enum_frame_size,
12487ee85054SArec Kao };
12497ee85054SArec Kao 
12507ee85054SArec Kao static const struct v4l2_subdev_ops ov13b10_subdev_ops = {
12517ee85054SArec Kao 	.video = &ov13b10_video_ops,
12527ee85054SArec Kao 	.pad = &ov13b10_pad_ops,
12537ee85054SArec Kao };
12547ee85054SArec Kao 
12557ee85054SArec Kao static const struct media_entity_operations ov13b10_subdev_entity_ops = {
12567ee85054SArec Kao 	.link_validate = v4l2_subdev_link_validate,
12577ee85054SArec Kao };
12587ee85054SArec Kao 
12597ee85054SArec Kao static const struct v4l2_subdev_internal_ops ov13b10_internal_ops = {
12607ee85054SArec Kao 	.open = ov13b10_open,
12617ee85054SArec Kao };
12627ee85054SArec Kao 
12637ee85054SArec Kao /* Initialize control handlers */
ov13b10_init_controls(struct ov13b10 * ov13b)12647ee85054SArec Kao static int ov13b10_init_controls(struct ov13b10 *ov13b)
12657ee85054SArec Kao {
12667ee85054SArec Kao 	struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
12677ee85054SArec Kao 	struct v4l2_fwnode_device_properties props;
12687ee85054SArec Kao 	struct v4l2_ctrl_handler *ctrl_hdlr;
12697ee85054SArec Kao 	s64 exposure_max;
12707ee85054SArec Kao 	s64 vblank_def;
12717ee85054SArec Kao 	s64 vblank_min;
12727ee85054SArec Kao 	s64 hblank;
12737ee85054SArec Kao 	s64 pixel_rate_min;
12747ee85054SArec Kao 	s64 pixel_rate_max;
12757ee85054SArec Kao 	const struct ov13b10_mode *mode;
12767ee85054SArec Kao 	u32 max;
12777ee85054SArec Kao 	int ret;
12787ee85054SArec Kao 
12797ee85054SArec Kao 	ctrl_hdlr = &ov13b->ctrl_handler;
12807ee85054SArec Kao 	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
12817ee85054SArec Kao 	if (ret)
12827ee85054SArec Kao 		return ret;
12837ee85054SArec Kao 
12847ee85054SArec Kao 	mutex_init(&ov13b->mutex);
12857ee85054SArec Kao 	ctrl_hdlr->lock = &ov13b->mutex;
12867ee85054SArec Kao 	max = ARRAY_SIZE(link_freq_menu_items) - 1;
12877ee85054SArec Kao 	ov13b->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
12887ee85054SArec Kao 						  &ov13b10_ctrl_ops,
12897ee85054SArec Kao 						  V4L2_CID_LINK_FREQ,
12907ee85054SArec Kao 						  max,
12917ee85054SArec Kao 						  0,
12927ee85054SArec Kao 						  link_freq_menu_items);
12937ee85054SArec Kao 	if (ov13b->link_freq)
12947ee85054SArec Kao 		ov13b->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
12957ee85054SArec Kao 
12967ee85054SArec Kao 	pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
12977ee85054SArec Kao 	pixel_rate_min = 0;
12987ee85054SArec Kao 	/* By default, PIXEL_RATE is read only */
12997ee85054SArec Kao 	ov13b->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
13007ee85054SArec Kao 					      V4L2_CID_PIXEL_RATE,
13017ee85054SArec Kao 					      pixel_rate_min, pixel_rate_max,
13027ee85054SArec Kao 					      1, pixel_rate_max);
13037ee85054SArec Kao 
13047ee85054SArec Kao 	mode = ov13b->cur_mode;
13057ee85054SArec Kao 	vblank_def = mode->vts_def - mode->height;
13067ee85054SArec Kao 	vblank_min = mode->vts_min - mode->height;
13077ee85054SArec Kao 	ov13b->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
13087ee85054SArec Kao 					  V4L2_CID_VBLANK,
13097ee85054SArec Kao 					  vblank_min,
13107ee85054SArec Kao 					  OV13B10_VTS_MAX - mode->height, 1,
13117ee85054SArec Kao 					  vblank_def);
13127ee85054SArec Kao 
13137ee85054SArec Kao 	hblank = link_freq_configs[mode->link_freq_index].pixels_per_line -
13147ee85054SArec Kao 		 mode->width;
13157ee85054SArec Kao 	ov13b->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
13167ee85054SArec Kao 					  V4L2_CID_HBLANK,
13177ee85054SArec Kao 					  hblank, hblank, 1, hblank);
13187ee85054SArec Kao 	if (ov13b->hblank)
13197ee85054SArec Kao 		ov13b->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
13207ee85054SArec Kao 
13217ee85054SArec Kao 	exposure_max = mode->vts_def - 8;
13227ee85054SArec Kao 	ov13b->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
13237ee85054SArec Kao 					    V4L2_CID_EXPOSURE,
13247ee85054SArec Kao 					    OV13B10_EXPOSURE_MIN,
13257ee85054SArec Kao 					    exposure_max, OV13B10_EXPOSURE_STEP,
13267ee85054SArec Kao 					    exposure_max);
13277ee85054SArec Kao 
13287ee85054SArec Kao 	v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
13297ee85054SArec Kao 			  OV13B10_ANA_GAIN_MIN, OV13B10_ANA_GAIN_MAX,
13307ee85054SArec Kao 			  OV13B10_ANA_GAIN_STEP, OV13B10_ANA_GAIN_DEFAULT);
13317ee85054SArec Kao 
13327ee85054SArec Kao 	/* Digital gain */
13337ee85054SArec Kao 	v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
13347ee85054SArec Kao 			  OV13B10_DGTL_GAIN_MIN, OV13B10_DGTL_GAIN_MAX,
13357ee85054SArec Kao 			  OV13B10_DGTL_GAIN_STEP, OV13B10_DGTL_GAIN_DEFAULT);
13367ee85054SArec Kao 
13377ee85054SArec Kao 	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov13b10_ctrl_ops,
13387ee85054SArec Kao 				     V4L2_CID_TEST_PATTERN,
13397ee85054SArec Kao 				     ARRAY_SIZE(ov13b10_test_pattern_menu) - 1,
13407ee85054SArec Kao 				     0, 0, ov13b10_test_pattern_menu);
13417ee85054SArec Kao 
13427ee85054SArec Kao 	v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
13437ee85054SArec Kao 			  V4L2_CID_HFLIP, 0, 1, 1, 0);
13447ee85054SArec Kao 	v4l2_ctrl_new_std(ctrl_hdlr, &ov13b10_ctrl_ops,
13457ee85054SArec Kao 			  V4L2_CID_VFLIP, 0, 1, 1, 0);
13467ee85054SArec Kao 
13477ee85054SArec Kao 	if (ctrl_hdlr->error) {
13487ee85054SArec Kao 		ret = ctrl_hdlr->error;
13497ee85054SArec Kao 		dev_err(&client->dev, "%s control init failed (%d)\n",
13507ee85054SArec Kao 			__func__, ret);
13517ee85054SArec Kao 		goto error;
13527ee85054SArec Kao 	}
13537ee85054SArec Kao 
13547ee85054SArec Kao 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
13557ee85054SArec Kao 	if (ret)
13567ee85054SArec Kao 		goto error;
13577ee85054SArec Kao 
13587ee85054SArec Kao 	ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov13b10_ctrl_ops,
13597ee85054SArec Kao 					      &props);
13607ee85054SArec Kao 	if (ret)
13617ee85054SArec Kao 		goto error;
13627ee85054SArec Kao 
13637ee85054SArec Kao 	ov13b->sd.ctrl_handler = ctrl_hdlr;
13647ee85054SArec Kao 
13657ee85054SArec Kao 	return 0;
13667ee85054SArec Kao 
13677ee85054SArec Kao error:
13687ee85054SArec Kao 	v4l2_ctrl_handler_free(ctrl_hdlr);
13697ee85054SArec Kao 	mutex_destroy(&ov13b->mutex);
13707ee85054SArec Kao 
13717ee85054SArec Kao 	return ret;
13727ee85054SArec Kao }
13737ee85054SArec Kao 
ov13b10_free_controls(struct ov13b10 * ov13b)13747ee85054SArec Kao static void ov13b10_free_controls(struct ov13b10 *ov13b)
13757ee85054SArec Kao {
13767ee85054SArec Kao 	v4l2_ctrl_handler_free(ov13b->sd.ctrl_handler);
13777ee85054SArec Kao 	mutex_destroy(&ov13b->mutex);
13787ee85054SArec Kao }
13797ee85054SArec Kao 
ov13b10_get_pm_resources(struct device * dev)13806e28afd1SBingbu Cao static int ov13b10_get_pm_resources(struct device *dev)
13816e28afd1SBingbu Cao {
13826e28afd1SBingbu Cao 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
13836e28afd1SBingbu Cao 	struct ov13b10 *ov13b = to_ov13b10(sd);
13846e28afd1SBingbu Cao 	int ret;
13856e28afd1SBingbu Cao 
13866e28afd1SBingbu Cao 	ov13b->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
13876e28afd1SBingbu Cao 	if (IS_ERR(ov13b->reset))
13886e28afd1SBingbu Cao 		return dev_err_probe(dev, PTR_ERR(ov13b->reset),
13896e28afd1SBingbu Cao 				     "failed to get reset gpio\n");
13906e28afd1SBingbu Cao 
13916e28afd1SBingbu Cao 	ov13b->img_clk = devm_clk_get_optional(dev, NULL);
13926e28afd1SBingbu Cao 	if (IS_ERR(ov13b->img_clk))
13936e28afd1SBingbu Cao 		return dev_err_probe(dev, PTR_ERR(ov13b->img_clk),
13946e28afd1SBingbu Cao 				     "failed to get imaging clock\n");
13956e28afd1SBingbu Cao 
13966e28afd1SBingbu Cao 	ov13b->avdd = devm_regulator_get_optional(dev, "avdd");
13976e28afd1SBingbu Cao 	if (IS_ERR(ov13b->avdd)) {
13986e28afd1SBingbu Cao 		ret = PTR_ERR(ov13b->avdd);
13996e28afd1SBingbu Cao 		ov13b->avdd = NULL;
14006e28afd1SBingbu Cao 		if (ret != -ENODEV)
14016e28afd1SBingbu Cao 			return dev_err_probe(dev, ret,
14026e28afd1SBingbu Cao 					     "failed to get avdd regulator\n");
14036e28afd1SBingbu Cao 	}
14046e28afd1SBingbu Cao 
14056e28afd1SBingbu Cao 	return 0;
14066e28afd1SBingbu Cao }
14076e28afd1SBingbu Cao 
ov13b10_check_hwcfg(struct device * dev)14087ee85054SArec Kao static int ov13b10_check_hwcfg(struct device *dev)
14097ee85054SArec Kao {
14107ee85054SArec Kao 	struct v4l2_fwnode_endpoint bus_cfg = {
14117ee85054SArec Kao 		.bus_type = V4L2_MBUS_CSI2_DPHY
14127ee85054SArec Kao 	};
14137ee85054SArec Kao 	struct fwnode_handle *ep;
14147ee85054SArec Kao 	struct fwnode_handle *fwnode = dev_fwnode(dev);
14157ee85054SArec Kao 	unsigned int i, j;
14167ee85054SArec Kao 	int ret;
14177ee85054SArec Kao 	u32 ext_clk;
14187ee85054SArec Kao 
14197ee85054SArec Kao 	if (!fwnode)
14207ee85054SArec Kao 		return -ENXIO;
14217ee85054SArec Kao 
1422b7602d62SBingbu Cao 	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
1423b7602d62SBingbu Cao 	if (!ep)
1424b7602d62SBingbu Cao 		return -EPROBE_DEFER;
1425b7602d62SBingbu Cao 
14267ee85054SArec Kao 	ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
14277ee85054SArec Kao 				       &ext_clk);
14287ee85054SArec Kao 	if (ret) {
14297ee85054SArec Kao 		dev_err(dev, "can't get clock frequency");
14307ee85054SArec Kao 		return ret;
14317ee85054SArec Kao 	}
14327ee85054SArec Kao 
14337ee85054SArec Kao 	if (ext_clk != OV13B10_EXT_CLK) {
14347ee85054SArec Kao 		dev_err(dev, "external clock %d is not supported",
14357ee85054SArec Kao 			ext_clk);
14367ee85054SArec Kao 		return -EINVAL;
14377ee85054SArec Kao 	}
14387ee85054SArec Kao 
14397ee85054SArec Kao 	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
14407ee85054SArec Kao 	fwnode_handle_put(ep);
14417ee85054SArec Kao 	if (ret)
14427ee85054SArec Kao 		return ret;
14437ee85054SArec Kao 
14447ee85054SArec Kao 	if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV13B10_DATA_LANES) {
14457ee85054SArec Kao 		dev_err(dev, "number of CSI2 data lanes %d is not supported",
14467ee85054SArec Kao 			bus_cfg.bus.mipi_csi2.num_data_lanes);
14477ee85054SArec Kao 		ret = -EINVAL;
14487ee85054SArec Kao 		goto out_err;
14497ee85054SArec Kao 	}
14507ee85054SArec Kao 
14517ee85054SArec Kao 	if (!bus_cfg.nr_of_link_frequencies) {
14527ee85054SArec Kao 		dev_err(dev, "no link frequencies defined");
14537ee85054SArec Kao 		ret = -EINVAL;
14547ee85054SArec Kao 		goto out_err;
14557ee85054SArec Kao 	}
14567ee85054SArec Kao 
14577ee85054SArec Kao 	for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {
14587ee85054SArec Kao 		for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {
14597ee85054SArec Kao 			if (link_freq_menu_items[i] ==
14607ee85054SArec Kao 				bus_cfg.link_frequencies[j])
14617ee85054SArec Kao 				break;
14627ee85054SArec Kao 		}
14637ee85054SArec Kao 
14647ee85054SArec Kao 		if (j == bus_cfg.nr_of_link_frequencies) {
14657ee85054SArec Kao 			dev_err(dev, "no link frequency %lld supported",
14667ee85054SArec Kao 				link_freq_menu_items[i]);
14677ee85054SArec Kao 			ret = -EINVAL;
14687ee85054SArec Kao 			goto out_err;
14697ee85054SArec Kao 		}
14707ee85054SArec Kao 	}
14717ee85054SArec Kao 
14727ee85054SArec Kao out_err:
14737ee85054SArec Kao 	v4l2_fwnode_endpoint_free(&bus_cfg);
14747ee85054SArec Kao 
14757ee85054SArec Kao 	return ret;
14767ee85054SArec Kao }
14777ee85054SArec Kao 
ov13b10_probe(struct i2c_client * client)14787ee85054SArec Kao static int ov13b10_probe(struct i2c_client *client)
14797ee85054SArec Kao {
14807ee85054SArec Kao 	struct ov13b10 *ov13b;
14811af2f618SArec Kao 	bool full_power;
14827ee85054SArec Kao 	int ret;
14837ee85054SArec Kao 
14847ee85054SArec Kao 	/* Check HW config */
14857ee85054SArec Kao 	ret = ov13b10_check_hwcfg(&client->dev);
14867ee85054SArec Kao 	if (ret) {
14877ee85054SArec Kao 		dev_err(&client->dev, "failed to check hwcfg: %d", ret);
14887ee85054SArec Kao 		return ret;
14897ee85054SArec Kao 	}
14907ee85054SArec Kao 
14917ee85054SArec Kao 	ov13b = devm_kzalloc(&client->dev, sizeof(*ov13b), GFP_KERNEL);
14927ee85054SArec Kao 	if (!ov13b)
14937ee85054SArec Kao 		return -ENOMEM;
14947ee85054SArec Kao 
14957ee85054SArec Kao 	/* Initialize subdev */
14967ee85054SArec Kao 	v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
14977ee85054SArec Kao 
14986e28afd1SBingbu Cao 	ret = ov13b10_get_pm_resources(&client->dev);
14996e28afd1SBingbu Cao 	if (ret)
15006e28afd1SBingbu Cao 		return ret;
15016e28afd1SBingbu Cao 
15021af2f618SArec Kao 	full_power = acpi_dev_state_d0(&client->dev);
15031af2f618SArec Kao 	if (full_power) {
1504adf4abf7SDan Carpenter 		ret = ov13b10_power_on(&client->dev);
15056e28afd1SBingbu Cao 		if (ret) {
15066e28afd1SBingbu Cao 			dev_err(&client->dev, "failed to power on\n");
15076e28afd1SBingbu Cao 			return ret;
15086e28afd1SBingbu Cao 		}
15096e28afd1SBingbu Cao 
15107ee85054SArec Kao 		/* Check module identity */
15117ee85054SArec Kao 		ret = ov13b10_identify_module(ov13b);
15127ee85054SArec Kao 		if (ret) {
15137ee85054SArec Kao 			dev_err(&client->dev, "failed to find sensor: %d\n", ret);
15146e28afd1SBingbu Cao 			goto error_power_off;
15157ee85054SArec Kao 		}
15161af2f618SArec Kao 	}
15177ee85054SArec Kao 
15187ee85054SArec Kao 	/* Set default mode to max resolution */
15197ee85054SArec Kao 	ov13b->cur_mode = &supported_modes[0];
15207ee85054SArec Kao 
15217ee85054SArec Kao 	ret = ov13b10_init_controls(ov13b);
15227ee85054SArec Kao 	if (ret)
15236e28afd1SBingbu Cao 		goto error_power_off;
15247ee85054SArec Kao 
15257ee85054SArec Kao 	/* Initialize subdev */
15267ee85054SArec Kao 	ov13b->sd.internal_ops = &ov13b10_internal_ops;
15277ee85054SArec Kao 	ov13b->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
15287ee85054SArec Kao 	ov13b->sd.entity.ops = &ov13b10_subdev_entity_ops;
15297ee85054SArec Kao 	ov13b->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
15307ee85054SArec Kao 
15317ee85054SArec Kao 	/* Initialize source pad */
15327ee85054SArec Kao 	ov13b->pad.flags = MEDIA_PAD_FL_SOURCE;
15337ee85054SArec Kao 	ret = media_entity_pads_init(&ov13b->sd.entity, 1, &ov13b->pad);
15347ee85054SArec Kao 	if (ret) {
15357ee85054SArec Kao 		dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
15367ee85054SArec Kao 		goto error_handler_free;
15377ee85054SArec Kao 	}
15387ee85054SArec Kao 
15397ee85054SArec Kao 
15407ee85054SArec Kao 	/*
15417ee85054SArec Kao 	 * Device is already turned on by i2c-core with ACPI domain PM.
15427ee85054SArec Kao 	 * Enable runtime PM and turn off the device.
15437ee85054SArec Kao 	 */
15441af2f618SArec Kao 	/* Set the device's state to active if it's in D0 state. */
15451af2f618SArec Kao 	if (full_power)
15467ee85054SArec Kao 		pm_runtime_set_active(&client->dev);
15477ee85054SArec Kao 	pm_runtime_enable(&client->dev);
15487ee85054SArec Kao 	pm_runtime_idle(&client->dev);
15497ee85054SArec Kao 
1550*000339cbSBingbu Cao 	ret = v4l2_async_register_subdev_sensor(&ov13b->sd);
1551*000339cbSBingbu Cao 	if (ret < 0)
1552*000339cbSBingbu Cao 		goto error_media_entity_runtime_pm;
1553*000339cbSBingbu Cao 
15547ee85054SArec Kao 	return 0;
15557ee85054SArec Kao 
1556*000339cbSBingbu Cao error_media_entity_runtime_pm:
1557*000339cbSBingbu Cao 	pm_runtime_disable(&client->dev);
1558*000339cbSBingbu Cao 	if (full_power)
1559*000339cbSBingbu Cao 		pm_runtime_set_suspended(&client->dev);
15607ee85054SArec Kao 	media_entity_cleanup(&ov13b->sd.entity);
15617ee85054SArec Kao 
15627ee85054SArec Kao error_handler_free:
15637ee85054SArec Kao 	ov13b10_free_controls(ov13b);
15647ee85054SArec Kao 	dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
15657ee85054SArec Kao 
15666e28afd1SBingbu Cao error_power_off:
15676e28afd1SBingbu Cao 	ov13b10_power_off(&client->dev);
15686e28afd1SBingbu Cao 
15697ee85054SArec Kao 	return ret;
15707ee85054SArec Kao }
15717ee85054SArec Kao 
ov13b10_remove(struct i2c_client * client)1572ed5c2f5fSUwe Kleine-König static void ov13b10_remove(struct i2c_client *client)
15737ee85054SArec Kao {
15747ee85054SArec Kao 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
15757ee85054SArec Kao 	struct ov13b10 *ov13b = to_ov13b10(sd);
15767ee85054SArec Kao 
15777ee85054SArec Kao 	v4l2_async_unregister_subdev(sd);
15787ee85054SArec Kao 	media_entity_cleanup(&sd->entity);
15797ee85054SArec Kao 	ov13b10_free_controls(ov13b);
15807ee85054SArec Kao 
15817ee85054SArec Kao 	pm_runtime_disable(&client->dev);
1582*000339cbSBingbu Cao 	pm_runtime_set_suspended(&client->dev);
15837ee85054SArec Kao }
15847ee85054SArec Kao 
15856e28afd1SBingbu Cao static DEFINE_RUNTIME_DEV_PM_OPS(ov13b10_pm_ops, ov13b10_suspend,
15866e28afd1SBingbu Cao 				 ov13b10_resume, NULL);
15877ee85054SArec Kao 
15887ee85054SArec Kao #ifdef CONFIG_ACPI
15897ee85054SArec Kao static const struct acpi_device_id ov13b10_acpi_ids[] = {
15907ee85054SArec Kao 	{"OVTIDB10"},
15919f71a7baSBingbu Cao 	{"OVTI13B1"},
15927ee85054SArec Kao 	{ /* sentinel */ }
15937ee85054SArec Kao };
15947ee85054SArec Kao 
15957ee85054SArec Kao MODULE_DEVICE_TABLE(acpi, ov13b10_acpi_ids);
15967ee85054SArec Kao #endif
15977ee85054SArec Kao 
15987ee85054SArec Kao static struct i2c_driver ov13b10_i2c_driver = {
15997ee85054SArec Kao 	.driver = {
16007ee85054SArec Kao 		.name = "ov13b10",
16016e28afd1SBingbu Cao 		.pm = pm_ptr(&ov13b10_pm_ops),
16027ee85054SArec Kao 		.acpi_match_table = ACPI_PTR(ov13b10_acpi_ids),
16037ee85054SArec Kao 	},
1604aaeb31c0SUwe Kleine-König 	.probe = ov13b10_probe,
16057ee85054SArec Kao 	.remove = ov13b10_remove,
16061af2f618SArec Kao 	.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
16077ee85054SArec Kao };
16087ee85054SArec Kao 
16097ee85054SArec Kao module_i2c_driver(ov13b10_i2c_driver);
16107ee85054SArec Kao 
16117ee85054SArec Kao MODULE_AUTHOR("Kao, Arec <arec.kao@intel.com>");
16127ee85054SArec Kao MODULE_DESCRIPTION("Omnivision ov13b10 sensor driver");
16137ee85054SArec Kao MODULE_LICENSE("GPL v2");
1614