xref: /openbmc/linux/drivers/media/i2c/imx208.c (revision d953e3cb)
1*d953e3cbSShawn Tu // SPDX-License-Identifier: GPL-2.0
2*d953e3cbSShawn Tu // Copyright (C) 2021 Intel Corporation
3*d953e3cbSShawn Tu 
4*d953e3cbSShawn Tu #include <linux/acpi.h>
5*d953e3cbSShawn Tu #include <linux/delay.h>
6*d953e3cbSShawn Tu #include <linux/i2c.h>
7*d953e3cbSShawn Tu #include <linux/module.h>
8*d953e3cbSShawn Tu #include <linux/pm_runtime.h>
9*d953e3cbSShawn Tu #include <media/v4l2-ctrls.h>
10*d953e3cbSShawn Tu #include <media/v4l2-device.h>
11*d953e3cbSShawn Tu #include <asm/unaligned.h>
12*d953e3cbSShawn Tu 
13*d953e3cbSShawn Tu #define IMX208_REG_MODE_SELECT		0x0100
14*d953e3cbSShawn Tu #define IMX208_MODE_STANDBY		0x00
15*d953e3cbSShawn Tu #define IMX208_MODE_STREAMING		0x01
16*d953e3cbSShawn Tu 
17*d953e3cbSShawn Tu /* Chip ID */
18*d953e3cbSShawn Tu #define IMX208_REG_CHIP_ID		0x0000
19*d953e3cbSShawn Tu #define IMX208_CHIP_ID			0x0208
20*d953e3cbSShawn Tu 
21*d953e3cbSShawn Tu /* V_TIMING internal */
22*d953e3cbSShawn Tu #define IMX208_REG_VTS			0x0340
23*d953e3cbSShawn Tu #define IMX208_VTS_60FPS		0x0472
24*d953e3cbSShawn Tu #define IMX208_VTS_BINNING		0x0239
25*d953e3cbSShawn Tu #define IMX208_VTS_60FPS_MIN		0x0458
26*d953e3cbSShawn Tu #define IMX208_VTS_BINNING_MIN		0x0230
27*d953e3cbSShawn Tu #define IMX208_VTS_MAX			0xffff
28*d953e3cbSShawn Tu 
29*d953e3cbSShawn Tu /* HBLANK control - read only */
30*d953e3cbSShawn Tu #define IMX208_PPL_384MHZ		2248
31*d953e3cbSShawn Tu #define IMX208_PPL_96MHZ		2248
32*d953e3cbSShawn Tu 
33*d953e3cbSShawn Tu /* Exposure control */
34*d953e3cbSShawn Tu #define IMX208_REG_EXPOSURE		0x0202
35*d953e3cbSShawn Tu #define IMX208_EXPOSURE_MIN		4
36*d953e3cbSShawn Tu #define IMX208_EXPOSURE_STEP		1
37*d953e3cbSShawn Tu #define IMX208_EXPOSURE_DEFAULT		0x190
38*d953e3cbSShawn Tu #define IMX208_EXPOSURE_MAX		65535
39*d953e3cbSShawn Tu 
40*d953e3cbSShawn Tu /* Analog gain control */
41*d953e3cbSShawn Tu #define IMX208_REG_ANALOG_GAIN		0x0204
42*d953e3cbSShawn Tu #define IMX208_ANA_GAIN_MIN		0
43*d953e3cbSShawn Tu #define IMX208_ANA_GAIN_MAX		0x00e0
44*d953e3cbSShawn Tu #define IMX208_ANA_GAIN_STEP		1
45*d953e3cbSShawn Tu #define IMX208_ANA_GAIN_DEFAULT		0x0
46*d953e3cbSShawn Tu 
47*d953e3cbSShawn Tu /* Digital gain control */
48*d953e3cbSShawn Tu #define IMX208_REG_GR_DIGITAL_GAIN	0x020e
49*d953e3cbSShawn Tu #define IMX208_REG_R_DIGITAL_GAIN	0x0210
50*d953e3cbSShawn Tu #define IMX208_REG_B_DIGITAL_GAIN	0x0212
51*d953e3cbSShawn Tu #define IMX208_REG_GB_DIGITAL_GAIN	0x0214
52*d953e3cbSShawn Tu #define IMX208_DIGITAL_GAIN_SHIFT	8
53*d953e3cbSShawn Tu 
54*d953e3cbSShawn Tu /* Orientation */
55*d953e3cbSShawn Tu #define IMX208_REG_ORIENTATION_CONTROL	0x0101
56*d953e3cbSShawn Tu 
57*d953e3cbSShawn Tu /* Test Pattern Control */
58*d953e3cbSShawn Tu #define IMX208_REG_TEST_PATTERN_MODE	0x0600
59*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_DISABLE	0x0
60*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_SOLID_COLOR	0x1
61*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_COLOR_BARS	0x2
62*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_GREY_COLOR	0x3
63*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_PN9		0x4
64*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_FIX_1	0x100
65*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_FIX_2	0x101
66*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_FIX_3	0x102
67*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_FIX_4	0x103
68*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_FIX_5	0x104
69*d953e3cbSShawn Tu #define IMX208_TEST_PATTERN_FIX_6	0x105
70*d953e3cbSShawn Tu 
71*d953e3cbSShawn Tu /* OTP Access */
72*d953e3cbSShawn Tu #define IMX208_OTP_BASE			0x3500
73*d953e3cbSShawn Tu #define IMX208_OTP_SIZE			40
74*d953e3cbSShawn Tu 
75*d953e3cbSShawn Tu struct imx208_reg {
76*d953e3cbSShawn Tu 	u16 address;
77*d953e3cbSShawn Tu 	u8 val;
78*d953e3cbSShawn Tu };
79*d953e3cbSShawn Tu 
80*d953e3cbSShawn Tu struct imx208_reg_list {
81*d953e3cbSShawn Tu 	u32 num_of_regs;
82*d953e3cbSShawn Tu 	const struct imx208_reg *regs;
83*d953e3cbSShawn Tu };
84*d953e3cbSShawn Tu 
85*d953e3cbSShawn Tu /* Link frequency config */
86*d953e3cbSShawn Tu struct imx208_link_freq_config {
87*d953e3cbSShawn Tu 	u32 pixels_per_line;
88*d953e3cbSShawn Tu 
89*d953e3cbSShawn Tu 	/* PLL registers for this link frequency */
90*d953e3cbSShawn Tu 	struct imx208_reg_list reg_list;
91*d953e3cbSShawn Tu };
92*d953e3cbSShawn Tu 
93*d953e3cbSShawn Tu /* Mode : resolution and related config&values */
94*d953e3cbSShawn Tu struct imx208_mode {
95*d953e3cbSShawn Tu 	/* Frame width */
96*d953e3cbSShawn Tu 	u32 width;
97*d953e3cbSShawn Tu 	/* Frame height */
98*d953e3cbSShawn Tu 	u32 height;
99*d953e3cbSShawn Tu 
100*d953e3cbSShawn Tu 	/* V-timing */
101*d953e3cbSShawn Tu 	u32 vts_def;
102*d953e3cbSShawn Tu 	u32 vts_min;
103*d953e3cbSShawn Tu 
104*d953e3cbSShawn Tu 	/* Index of Link frequency config to be used */
105*d953e3cbSShawn Tu 	u32 link_freq_index;
106*d953e3cbSShawn Tu 	/* Default register values */
107*d953e3cbSShawn Tu 	struct imx208_reg_list reg_list;
108*d953e3cbSShawn Tu };
109*d953e3cbSShawn Tu 
110*d953e3cbSShawn Tu static const struct imx208_reg pll_ctrl_reg[] = {
111*d953e3cbSShawn Tu 	{0x0305, 0x02},
112*d953e3cbSShawn Tu 	{0x0307, 0x50},
113*d953e3cbSShawn Tu 	{0x303C, 0x3C},
114*d953e3cbSShawn Tu };
115*d953e3cbSShawn Tu 
116*d953e3cbSShawn Tu static const struct imx208_reg mode_1936x1096_60fps_regs[] = {
117*d953e3cbSShawn Tu 	{0x0340, 0x04},
118*d953e3cbSShawn Tu 	{0x0341, 0x72},
119*d953e3cbSShawn Tu 	{0x0342, 0x04},
120*d953e3cbSShawn Tu 	{0x0343, 0x64},
121*d953e3cbSShawn Tu 	{0x034C, 0x07},
122*d953e3cbSShawn Tu 	{0x034D, 0x90},
123*d953e3cbSShawn Tu 	{0x034E, 0x04},
124*d953e3cbSShawn Tu 	{0x034F, 0x48},
125*d953e3cbSShawn Tu 	{0x0381, 0x01},
126*d953e3cbSShawn Tu 	{0x0383, 0x01},
127*d953e3cbSShawn Tu 	{0x0385, 0x01},
128*d953e3cbSShawn Tu 	{0x0387, 0x01},
129*d953e3cbSShawn Tu 	{0x3048, 0x00},
130*d953e3cbSShawn Tu 	{0x3050, 0x01},
131*d953e3cbSShawn Tu 	{0x30D5, 0x00},
132*d953e3cbSShawn Tu 	{0x3301, 0x00},
133*d953e3cbSShawn Tu 	{0x3318, 0x62},
134*d953e3cbSShawn Tu 	{0x0202, 0x01},
135*d953e3cbSShawn Tu 	{0x0203, 0x90},
136*d953e3cbSShawn Tu 	{0x0205, 0x00},
137*d953e3cbSShawn Tu };
138*d953e3cbSShawn Tu 
139*d953e3cbSShawn Tu static const struct imx208_reg mode_968_548_60fps_regs[] = {
140*d953e3cbSShawn Tu 	{0x0340, 0x02},
141*d953e3cbSShawn Tu 	{0x0341, 0x39},
142*d953e3cbSShawn Tu 	{0x0342, 0x08},
143*d953e3cbSShawn Tu 	{0x0343, 0xC8},
144*d953e3cbSShawn Tu 	{0x034C, 0x03},
145*d953e3cbSShawn Tu 	{0x034D, 0xC8},
146*d953e3cbSShawn Tu 	{0x034E, 0x02},
147*d953e3cbSShawn Tu 	{0x034F, 0x24},
148*d953e3cbSShawn Tu 	{0x0381, 0x01},
149*d953e3cbSShawn Tu 	{0x0383, 0x03},
150*d953e3cbSShawn Tu 	{0x0385, 0x01},
151*d953e3cbSShawn Tu 	{0x0387, 0x03},
152*d953e3cbSShawn Tu 	{0x3048, 0x01},
153*d953e3cbSShawn Tu 	{0x3050, 0x02},
154*d953e3cbSShawn Tu 	{0x30D5, 0x03},
155*d953e3cbSShawn Tu 	{0x3301, 0x10},
156*d953e3cbSShawn Tu 	{0x3318, 0x75},
157*d953e3cbSShawn Tu 	{0x0202, 0x01},
158*d953e3cbSShawn Tu 	{0x0203, 0x90},
159*d953e3cbSShawn Tu 	{0x0205, 0x00},
160*d953e3cbSShawn Tu };
161*d953e3cbSShawn Tu 
162*d953e3cbSShawn Tu static const s64 imx208_discrete_digital_gain[] = {
163*d953e3cbSShawn Tu 	1, 2, 4, 8, 16,
164*d953e3cbSShawn Tu };
165*d953e3cbSShawn Tu 
166*d953e3cbSShawn Tu static const char * const imx208_test_pattern_menu[] = {
167*d953e3cbSShawn Tu 	"Disabled",
168*d953e3cbSShawn Tu 	"Solid Color",
169*d953e3cbSShawn Tu 	"100% Color Bar",
170*d953e3cbSShawn Tu 	"Fade to Grey Color Bar",
171*d953e3cbSShawn Tu 	"PN9",
172*d953e3cbSShawn Tu 	"Fixed Pattern1",
173*d953e3cbSShawn Tu 	"Fixed Pattern2",
174*d953e3cbSShawn Tu 	"Fixed Pattern3",
175*d953e3cbSShawn Tu 	"Fixed Pattern4",
176*d953e3cbSShawn Tu 	"Fixed Pattern5",
177*d953e3cbSShawn Tu 	"Fixed Pattern6"
178*d953e3cbSShawn Tu };
179*d953e3cbSShawn Tu 
180*d953e3cbSShawn Tu static const int imx208_test_pattern_val[] = {
181*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_DISABLE,
182*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_SOLID_COLOR,
183*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_COLOR_BARS,
184*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_GREY_COLOR,
185*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_PN9,
186*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_FIX_1,
187*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_FIX_2,
188*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_FIX_3,
189*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_FIX_4,
190*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_FIX_5,
191*d953e3cbSShawn Tu 	IMX208_TEST_PATTERN_FIX_6,
192*d953e3cbSShawn Tu };
193*d953e3cbSShawn Tu 
194*d953e3cbSShawn Tu /* Configurations for supported link frequencies */
195*d953e3cbSShawn Tu #define IMX208_MHZ			(1000 * 1000ULL)
196*d953e3cbSShawn Tu #define IMX208_LINK_FREQ_384MHZ		(384ULL * IMX208_MHZ)
197*d953e3cbSShawn Tu #define IMX208_LINK_FREQ_96MHZ		(96ULL * IMX208_MHZ)
198*d953e3cbSShawn Tu 
199*d953e3cbSShawn Tu #define IMX208_DATA_RATE_DOUBLE		2
200*d953e3cbSShawn Tu #define IMX208_NUM_OF_LANES		2
201*d953e3cbSShawn Tu #define IMX208_PIXEL_BITS		10
202*d953e3cbSShawn Tu 
203*d953e3cbSShawn Tu enum {
204*d953e3cbSShawn Tu 	IMX208_LINK_FREQ_384MHZ_INDEX,
205*d953e3cbSShawn Tu 	IMX208_LINK_FREQ_96MHZ_INDEX,
206*d953e3cbSShawn Tu };
207*d953e3cbSShawn Tu 
208*d953e3cbSShawn Tu /*
209*d953e3cbSShawn Tu  * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
210*d953e3cbSShawn Tu  * data rate => double data rate; number of lanes => 2; bits per pixel => 10
211*d953e3cbSShawn Tu  */
212*d953e3cbSShawn Tu static u64 link_freq_to_pixel_rate(u64 f)
213*d953e3cbSShawn Tu {
214*d953e3cbSShawn Tu 	f *= IMX208_DATA_RATE_DOUBLE * IMX208_NUM_OF_LANES;
215*d953e3cbSShawn Tu 	do_div(f, IMX208_PIXEL_BITS);
216*d953e3cbSShawn Tu 
217*d953e3cbSShawn Tu 	return f;
218*d953e3cbSShawn Tu }
219*d953e3cbSShawn Tu 
220*d953e3cbSShawn Tu /* Menu items for LINK_FREQ V4L2 control */
221*d953e3cbSShawn Tu static const s64 link_freq_menu_items[] = {
222*d953e3cbSShawn Tu 	[IMX208_LINK_FREQ_384MHZ_INDEX] = IMX208_LINK_FREQ_384MHZ,
223*d953e3cbSShawn Tu 	[IMX208_LINK_FREQ_96MHZ_INDEX] = IMX208_LINK_FREQ_96MHZ,
224*d953e3cbSShawn Tu };
225*d953e3cbSShawn Tu 
226*d953e3cbSShawn Tu /* Link frequency configs */
227*d953e3cbSShawn Tu static const struct imx208_link_freq_config link_freq_configs[] = {
228*d953e3cbSShawn Tu 	[IMX208_LINK_FREQ_384MHZ_INDEX] = {
229*d953e3cbSShawn Tu 		.pixels_per_line = IMX208_PPL_384MHZ,
230*d953e3cbSShawn Tu 		.reg_list = {
231*d953e3cbSShawn Tu 			.num_of_regs = ARRAY_SIZE(pll_ctrl_reg),
232*d953e3cbSShawn Tu 			.regs = pll_ctrl_reg,
233*d953e3cbSShawn Tu 		}
234*d953e3cbSShawn Tu 	},
235*d953e3cbSShawn Tu 	[IMX208_LINK_FREQ_96MHZ_INDEX] = {
236*d953e3cbSShawn Tu 		.pixels_per_line = IMX208_PPL_96MHZ,
237*d953e3cbSShawn Tu 		.reg_list = {
238*d953e3cbSShawn Tu 			.num_of_regs = ARRAY_SIZE(pll_ctrl_reg),
239*d953e3cbSShawn Tu 			.regs = pll_ctrl_reg,
240*d953e3cbSShawn Tu 		}
241*d953e3cbSShawn Tu 	},
242*d953e3cbSShawn Tu };
243*d953e3cbSShawn Tu 
244*d953e3cbSShawn Tu /* Mode configs */
245*d953e3cbSShawn Tu static const struct imx208_mode supported_modes[] = {
246*d953e3cbSShawn Tu 	{
247*d953e3cbSShawn Tu 		.width = 1936,
248*d953e3cbSShawn Tu 		.height = 1096,
249*d953e3cbSShawn Tu 		.vts_def = IMX208_VTS_60FPS,
250*d953e3cbSShawn Tu 		.vts_min = IMX208_VTS_60FPS_MIN,
251*d953e3cbSShawn Tu 		.reg_list = {
252*d953e3cbSShawn Tu 			.num_of_regs = ARRAY_SIZE(mode_1936x1096_60fps_regs),
253*d953e3cbSShawn Tu 			.regs = mode_1936x1096_60fps_regs,
254*d953e3cbSShawn Tu 		},
255*d953e3cbSShawn Tu 		.link_freq_index = IMX208_LINK_FREQ_384MHZ_INDEX,
256*d953e3cbSShawn Tu 	},
257*d953e3cbSShawn Tu 	{
258*d953e3cbSShawn Tu 		.width = 968,
259*d953e3cbSShawn Tu 		.height = 548,
260*d953e3cbSShawn Tu 		.vts_def = IMX208_VTS_BINNING,
261*d953e3cbSShawn Tu 		.vts_min = IMX208_VTS_BINNING_MIN,
262*d953e3cbSShawn Tu 		.reg_list = {
263*d953e3cbSShawn Tu 			.num_of_regs = ARRAY_SIZE(mode_968_548_60fps_regs),
264*d953e3cbSShawn Tu 			.regs = mode_968_548_60fps_regs,
265*d953e3cbSShawn Tu 		},
266*d953e3cbSShawn Tu 		.link_freq_index = IMX208_LINK_FREQ_96MHZ_INDEX,
267*d953e3cbSShawn Tu 	},
268*d953e3cbSShawn Tu };
269*d953e3cbSShawn Tu 
270*d953e3cbSShawn Tu struct imx208 {
271*d953e3cbSShawn Tu 	struct v4l2_subdev sd;
272*d953e3cbSShawn Tu 	struct media_pad pad;
273*d953e3cbSShawn Tu 
274*d953e3cbSShawn Tu 	struct v4l2_ctrl_handler ctrl_handler;
275*d953e3cbSShawn Tu 	/* V4L2 Controls */
276*d953e3cbSShawn Tu 	struct v4l2_ctrl *link_freq;
277*d953e3cbSShawn Tu 	struct v4l2_ctrl *pixel_rate;
278*d953e3cbSShawn Tu 	struct v4l2_ctrl *vblank;
279*d953e3cbSShawn Tu 	struct v4l2_ctrl *hblank;
280*d953e3cbSShawn Tu 	struct v4l2_ctrl *vflip;
281*d953e3cbSShawn Tu 	struct v4l2_ctrl *hflip;
282*d953e3cbSShawn Tu 
283*d953e3cbSShawn Tu 	/* Current mode */
284*d953e3cbSShawn Tu 	const struct imx208_mode *cur_mode;
285*d953e3cbSShawn Tu 
286*d953e3cbSShawn Tu 	/*
287*d953e3cbSShawn Tu 	 * Mutex for serialized access:
288*d953e3cbSShawn Tu 	 * Protect sensor set pad format and start/stop streaming safely.
289*d953e3cbSShawn Tu 	 * Protect access to sensor v4l2 controls.
290*d953e3cbSShawn Tu 	 */
291*d953e3cbSShawn Tu 	struct mutex imx208_mx;
292*d953e3cbSShawn Tu 
293*d953e3cbSShawn Tu 	/* Streaming on/off */
294*d953e3cbSShawn Tu 	bool streaming;
295*d953e3cbSShawn Tu 
296*d953e3cbSShawn Tu 	/* OTP data */
297*d953e3cbSShawn Tu 	bool otp_read;
298*d953e3cbSShawn Tu 	char otp_data[IMX208_OTP_SIZE];
299*d953e3cbSShawn Tu };
300*d953e3cbSShawn Tu 
301*d953e3cbSShawn Tu static inline struct imx208 *to_imx208(struct v4l2_subdev *_sd)
302*d953e3cbSShawn Tu {
303*d953e3cbSShawn Tu 	return container_of(_sd, struct imx208, sd);
304*d953e3cbSShawn Tu }
305*d953e3cbSShawn Tu 
306*d953e3cbSShawn Tu /* Get bayer order based on flip setting. */
307*d953e3cbSShawn Tu static u32 imx208_get_format_code(struct imx208 *imx208)
308*d953e3cbSShawn Tu {
309*d953e3cbSShawn Tu 	/*
310*d953e3cbSShawn Tu 	 * Only one bayer order is supported.
311*d953e3cbSShawn Tu 	 * It depends on the flip settings.
312*d953e3cbSShawn Tu 	 */
313*d953e3cbSShawn Tu 	static const u32 codes[2][2] = {
314*d953e3cbSShawn Tu 		{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },
315*d953e3cbSShawn Tu 		{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },
316*d953e3cbSShawn Tu 	};
317*d953e3cbSShawn Tu 
318*d953e3cbSShawn Tu 	return codes[imx208->vflip->val][imx208->hflip->val];
319*d953e3cbSShawn Tu }
320*d953e3cbSShawn Tu 
321*d953e3cbSShawn Tu /* Read registers up to 4 at a time */
322*d953e3cbSShawn Tu static int imx208_read_reg(struct imx208 *imx208, u16 reg, u32 len, u32 *val)
323*d953e3cbSShawn Tu {
324*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
325*d953e3cbSShawn Tu 	struct i2c_msg msgs[2];
326*d953e3cbSShawn Tu 	u8 addr_buf[2] = { reg >> 8, reg & 0xff };
327*d953e3cbSShawn Tu 	u8 data_buf[4] = { 0, };
328*d953e3cbSShawn Tu 	int ret;
329*d953e3cbSShawn Tu 
330*d953e3cbSShawn Tu 	if (len > 4)
331*d953e3cbSShawn Tu 		return -EINVAL;
332*d953e3cbSShawn Tu 
333*d953e3cbSShawn Tu 	/* Write register address */
334*d953e3cbSShawn Tu 	msgs[0].addr = client->addr;
335*d953e3cbSShawn Tu 	msgs[0].flags = 0;
336*d953e3cbSShawn Tu 	msgs[0].len = ARRAY_SIZE(addr_buf);
337*d953e3cbSShawn Tu 	msgs[0].buf = addr_buf;
338*d953e3cbSShawn Tu 
339*d953e3cbSShawn Tu 	/* Read data from register */
340*d953e3cbSShawn Tu 	msgs[1].addr = client->addr;
341*d953e3cbSShawn Tu 	msgs[1].flags = I2C_M_RD;
342*d953e3cbSShawn Tu 	msgs[1].len = len;
343*d953e3cbSShawn Tu 	msgs[1].buf = &data_buf[4 - len];
344*d953e3cbSShawn Tu 
345*d953e3cbSShawn Tu 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
346*d953e3cbSShawn Tu 	if (ret != ARRAY_SIZE(msgs))
347*d953e3cbSShawn Tu 		return -EIO;
348*d953e3cbSShawn Tu 
349*d953e3cbSShawn Tu 	*val = get_unaligned_be32(data_buf);
350*d953e3cbSShawn Tu 
351*d953e3cbSShawn Tu 	return 0;
352*d953e3cbSShawn Tu }
353*d953e3cbSShawn Tu 
354*d953e3cbSShawn Tu /* Write registers up to 4 at a time */
355*d953e3cbSShawn Tu static int imx208_write_reg(struct imx208 *imx208, u16 reg, u32 len, u32 val)
356*d953e3cbSShawn Tu {
357*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
358*d953e3cbSShawn Tu 	u8 buf[6];
359*d953e3cbSShawn Tu 
360*d953e3cbSShawn Tu 	if (len > 4)
361*d953e3cbSShawn Tu 		return -EINVAL;
362*d953e3cbSShawn Tu 
363*d953e3cbSShawn Tu 	put_unaligned_be16(reg, buf);
364*d953e3cbSShawn Tu 	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
365*d953e3cbSShawn Tu 	if (i2c_master_send(client, buf, len + 2) != len + 2)
366*d953e3cbSShawn Tu 		return -EIO;
367*d953e3cbSShawn Tu 
368*d953e3cbSShawn Tu 	return 0;
369*d953e3cbSShawn Tu }
370*d953e3cbSShawn Tu 
371*d953e3cbSShawn Tu /* Write a list of registers */
372*d953e3cbSShawn Tu static int imx208_write_regs(struct imx208 *imx208,
373*d953e3cbSShawn Tu 			     const struct imx208_reg *regs, u32 len)
374*d953e3cbSShawn Tu {
375*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
376*d953e3cbSShawn Tu 	unsigned int i;
377*d953e3cbSShawn Tu 	int ret;
378*d953e3cbSShawn Tu 
379*d953e3cbSShawn Tu 	for (i = 0; i < len; i++) {
380*d953e3cbSShawn Tu 		ret = imx208_write_reg(imx208, regs[i].address, 1,
381*d953e3cbSShawn Tu 				       regs[i].val);
382*d953e3cbSShawn Tu 		if (ret) {
383*d953e3cbSShawn Tu 			dev_err_ratelimited(&client->dev,
384*d953e3cbSShawn Tu 					    "Failed to write reg 0x%4.4x. error = %d\n",
385*d953e3cbSShawn Tu 					    regs[i].address, ret);
386*d953e3cbSShawn Tu 
387*d953e3cbSShawn Tu 			return ret;
388*d953e3cbSShawn Tu 		}
389*d953e3cbSShawn Tu 	}
390*d953e3cbSShawn Tu 
391*d953e3cbSShawn Tu 	return 0;
392*d953e3cbSShawn Tu }
393*d953e3cbSShawn Tu 
394*d953e3cbSShawn Tu /* Open sub-device */
395*d953e3cbSShawn Tu static int imx208_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
396*d953e3cbSShawn Tu {
397*d953e3cbSShawn Tu 	struct v4l2_mbus_framefmt *try_fmt =
398*d953e3cbSShawn Tu 		v4l2_subdev_get_try_format(sd, fh->pad, 0);
399*d953e3cbSShawn Tu 
400*d953e3cbSShawn Tu 	/* Initialize try_fmt */
401*d953e3cbSShawn Tu 	try_fmt->width = supported_modes[0].width;
402*d953e3cbSShawn Tu 	try_fmt->height = supported_modes[0].height;
403*d953e3cbSShawn Tu 	try_fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
404*d953e3cbSShawn Tu 	try_fmt->field = V4L2_FIELD_NONE;
405*d953e3cbSShawn Tu 
406*d953e3cbSShawn Tu 	return 0;
407*d953e3cbSShawn Tu }
408*d953e3cbSShawn Tu 
409*d953e3cbSShawn Tu static int imx208_update_digital_gain(struct imx208 *imx208, u32 len, u32 val)
410*d953e3cbSShawn Tu {
411*d953e3cbSShawn Tu 	int ret;
412*d953e3cbSShawn Tu 
413*d953e3cbSShawn Tu 	val = imx208_discrete_digital_gain[val] << IMX208_DIGITAL_GAIN_SHIFT;
414*d953e3cbSShawn Tu 
415*d953e3cbSShawn Tu 	ret = imx208_write_reg(imx208, IMX208_REG_GR_DIGITAL_GAIN, 2, val);
416*d953e3cbSShawn Tu 	if (ret)
417*d953e3cbSShawn Tu 		return ret;
418*d953e3cbSShawn Tu 
419*d953e3cbSShawn Tu 	ret = imx208_write_reg(imx208, IMX208_REG_GB_DIGITAL_GAIN, 2, val);
420*d953e3cbSShawn Tu 	if (ret)
421*d953e3cbSShawn Tu 		return ret;
422*d953e3cbSShawn Tu 
423*d953e3cbSShawn Tu 	ret = imx208_write_reg(imx208, IMX208_REG_R_DIGITAL_GAIN, 2, val);
424*d953e3cbSShawn Tu 	if (ret)
425*d953e3cbSShawn Tu 		return ret;
426*d953e3cbSShawn Tu 
427*d953e3cbSShawn Tu 	return imx208_write_reg(imx208, IMX208_REG_B_DIGITAL_GAIN, 2, val);
428*d953e3cbSShawn Tu }
429*d953e3cbSShawn Tu 
430*d953e3cbSShawn Tu static int imx208_set_ctrl(struct v4l2_ctrl *ctrl)
431*d953e3cbSShawn Tu {
432*d953e3cbSShawn Tu 	struct imx208 *imx208 =
433*d953e3cbSShawn Tu 		container_of(ctrl->handler, struct imx208, ctrl_handler);
434*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
435*d953e3cbSShawn Tu 	int ret;
436*d953e3cbSShawn Tu 
437*d953e3cbSShawn Tu 	/*
438*d953e3cbSShawn Tu 	 * Applying V4L2 control value only happens
439*d953e3cbSShawn Tu 	 * when power is up for streaming
440*d953e3cbSShawn Tu 	 */
441*d953e3cbSShawn Tu 	if (!pm_runtime_get_if_in_use(&client->dev))
442*d953e3cbSShawn Tu 		return 0;
443*d953e3cbSShawn Tu 
444*d953e3cbSShawn Tu 	switch (ctrl->id) {
445*d953e3cbSShawn Tu 	case V4L2_CID_ANALOGUE_GAIN:
446*d953e3cbSShawn Tu 		ret = imx208_write_reg(imx208, IMX208_REG_ANALOG_GAIN,
447*d953e3cbSShawn Tu 				       2, ctrl->val);
448*d953e3cbSShawn Tu 		break;
449*d953e3cbSShawn Tu 	case V4L2_CID_EXPOSURE:
450*d953e3cbSShawn Tu 		ret = imx208_write_reg(imx208, IMX208_REG_EXPOSURE,
451*d953e3cbSShawn Tu 				       2, ctrl->val);
452*d953e3cbSShawn Tu 		break;
453*d953e3cbSShawn Tu 	case V4L2_CID_DIGITAL_GAIN:
454*d953e3cbSShawn Tu 		ret = imx208_update_digital_gain(imx208, 2, ctrl->val);
455*d953e3cbSShawn Tu 		break;
456*d953e3cbSShawn Tu 	case V4L2_CID_VBLANK:
457*d953e3cbSShawn Tu 		/* Update VTS that meets expected vertical blanking */
458*d953e3cbSShawn Tu 		ret = imx208_write_reg(imx208, IMX208_REG_VTS, 2,
459*d953e3cbSShawn Tu 				       imx208->cur_mode->height + ctrl->val);
460*d953e3cbSShawn Tu 		break;
461*d953e3cbSShawn Tu 	case V4L2_CID_TEST_PATTERN:
462*d953e3cbSShawn Tu 		ret = imx208_write_reg(imx208, IMX208_REG_TEST_PATTERN_MODE,
463*d953e3cbSShawn Tu 				       2, imx208_test_pattern_val[ctrl->val]);
464*d953e3cbSShawn Tu 		break;
465*d953e3cbSShawn Tu 	case V4L2_CID_HFLIP:
466*d953e3cbSShawn Tu 	case V4L2_CID_VFLIP:
467*d953e3cbSShawn Tu 		ret = imx208_write_reg(imx208, IMX208_REG_ORIENTATION_CONTROL,
468*d953e3cbSShawn Tu 				       1,
469*d953e3cbSShawn Tu 				       imx208->hflip->val |
470*d953e3cbSShawn Tu 				       imx208->vflip->val << 1);
471*d953e3cbSShawn Tu 		break;
472*d953e3cbSShawn Tu 	default:
473*d953e3cbSShawn Tu 		ret = -EINVAL;
474*d953e3cbSShawn Tu 		dev_err(&client->dev,
475*d953e3cbSShawn Tu 			"ctrl(id:0x%x,val:0x%x) is not handled\n",
476*d953e3cbSShawn Tu 			ctrl->id, ctrl->val);
477*d953e3cbSShawn Tu 		break;
478*d953e3cbSShawn Tu 	}
479*d953e3cbSShawn Tu 
480*d953e3cbSShawn Tu 	pm_runtime_put(&client->dev);
481*d953e3cbSShawn Tu 
482*d953e3cbSShawn Tu 	return ret;
483*d953e3cbSShawn Tu }
484*d953e3cbSShawn Tu 
485*d953e3cbSShawn Tu static const struct v4l2_ctrl_ops imx208_ctrl_ops = {
486*d953e3cbSShawn Tu 	.s_ctrl = imx208_set_ctrl,
487*d953e3cbSShawn Tu };
488*d953e3cbSShawn Tu 
489*d953e3cbSShawn Tu static const struct v4l2_ctrl_config imx208_digital_gain_control = {
490*d953e3cbSShawn Tu 	.ops = &imx208_ctrl_ops,
491*d953e3cbSShawn Tu 	.id = V4L2_CID_DIGITAL_GAIN,
492*d953e3cbSShawn Tu 	.name = "Digital Gain",
493*d953e3cbSShawn Tu 	.type = V4L2_CTRL_TYPE_INTEGER_MENU,
494*d953e3cbSShawn Tu 	.min = 0,
495*d953e3cbSShawn Tu 	.max = ARRAY_SIZE(imx208_discrete_digital_gain) - 1,
496*d953e3cbSShawn Tu 	.step = 0,
497*d953e3cbSShawn Tu 	.def = 0,
498*d953e3cbSShawn Tu 	.menu_skip_mask = 0,
499*d953e3cbSShawn Tu 	.qmenu_int = imx208_discrete_digital_gain,
500*d953e3cbSShawn Tu };
501*d953e3cbSShawn Tu 
502*d953e3cbSShawn Tu static int imx208_enum_mbus_code(struct v4l2_subdev *sd,
503*d953e3cbSShawn Tu 				 struct v4l2_subdev_pad_config *cfg,
504*d953e3cbSShawn Tu 				 struct v4l2_subdev_mbus_code_enum *code)
505*d953e3cbSShawn Tu {
506*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
507*d953e3cbSShawn Tu 
508*d953e3cbSShawn Tu 	if (code->index > 0)
509*d953e3cbSShawn Tu 		return -EINVAL;
510*d953e3cbSShawn Tu 
511*d953e3cbSShawn Tu 	code->code = imx208_get_format_code(imx208);
512*d953e3cbSShawn Tu 
513*d953e3cbSShawn Tu 	return 0;
514*d953e3cbSShawn Tu }
515*d953e3cbSShawn Tu 
516*d953e3cbSShawn Tu static int imx208_enum_frame_size(struct v4l2_subdev *sd,
517*d953e3cbSShawn Tu 				  struct v4l2_subdev_pad_config *cfg,
518*d953e3cbSShawn Tu 				  struct v4l2_subdev_frame_size_enum *fse)
519*d953e3cbSShawn Tu {
520*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
521*d953e3cbSShawn Tu 
522*d953e3cbSShawn Tu 	if (fse->index >= ARRAY_SIZE(supported_modes))
523*d953e3cbSShawn Tu 		return -EINVAL;
524*d953e3cbSShawn Tu 
525*d953e3cbSShawn Tu 	if (fse->code != imx208_get_format_code(imx208))
526*d953e3cbSShawn Tu 		return -EINVAL;
527*d953e3cbSShawn Tu 
528*d953e3cbSShawn Tu 	fse->min_width = supported_modes[fse->index].width;
529*d953e3cbSShawn Tu 	fse->max_width = fse->min_width;
530*d953e3cbSShawn Tu 	fse->min_height = supported_modes[fse->index].height;
531*d953e3cbSShawn Tu 	fse->max_height = fse->min_height;
532*d953e3cbSShawn Tu 
533*d953e3cbSShawn Tu 	return 0;
534*d953e3cbSShawn Tu }
535*d953e3cbSShawn Tu 
536*d953e3cbSShawn Tu static void imx208_mode_to_pad_format(struct imx208 *imx208,
537*d953e3cbSShawn Tu 				      const struct imx208_mode *mode,
538*d953e3cbSShawn Tu 				      struct v4l2_subdev_format *fmt)
539*d953e3cbSShawn Tu {
540*d953e3cbSShawn Tu 	fmt->format.width = mode->width;
541*d953e3cbSShawn Tu 	fmt->format.height = mode->height;
542*d953e3cbSShawn Tu 	fmt->format.code = imx208_get_format_code(imx208);
543*d953e3cbSShawn Tu 	fmt->format.field = V4L2_FIELD_NONE;
544*d953e3cbSShawn Tu }
545*d953e3cbSShawn Tu 
546*d953e3cbSShawn Tu static int __imx208_get_pad_format(struct imx208 *imx208,
547*d953e3cbSShawn Tu 				   struct v4l2_subdev_pad_config *cfg,
548*d953e3cbSShawn Tu 				   struct v4l2_subdev_format *fmt)
549*d953e3cbSShawn Tu {
550*d953e3cbSShawn Tu 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
551*d953e3cbSShawn Tu 		fmt->format = *v4l2_subdev_get_try_format(&imx208->sd, cfg,
552*d953e3cbSShawn Tu 							  fmt->pad);
553*d953e3cbSShawn Tu 	else
554*d953e3cbSShawn Tu 		imx208_mode_to_pad_format(imx208, imx208->cur_mode, fmt);
555*d953e3cbSShawn Tu 
556*d953e3cbSShawn Tu 	return 0;
557*d953e3cbSShawn Tu }
558*d953e3cbSShawn Tu 
559*d953e3cbSShawn Tu static int imx208_get_pad_format(struct v4l2_subdev *sd,
560*d953e3cbSShawn Tu 				 struct v4l2_subdev_pad_config *cfg,
561*d953e3cbSShawn Tu 				 struct v4l2_subdev_format *fmt)
562*d953e3cbSShawn Tu {
563*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
564*d953e3cbSShawn Tu 	int ret;
565*d953e3cbSShawn Tu 
566*d953e3cbSShawn Tu 	mutex_lock(&imx208->imx208_mx);
567*d953e3cbSShawn Tu 	ret = __imx208_get_pad_format(imx208, cfg, fmt);
568*d953e3cbSShawn Tu 	mutex_unlock(&imx208->imx208_mx);
569*d953e3cbSShawn Tu 
570*d953e3cbSShawn Tu 	return ret;
571*d953e3cbSShawn Tu }
572*d953e3cbSShawn Tu 
573*d953e3cbSShawn Tu static int imx208_set_pad_format(struct v4l2_subdev *sd,
574*d953e3cbSShawn Tu 				 struct v4l2_subdev_pad_config *cfg,
575*d953e3cbSShawn Tu 				 struct v4l2_subdev_format *fmt)
576*d953e3cbSShawn Tu {
577*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
578*d953e3cbSShawn Tu 	const struct imx208_mode *mode;
579*d953e3cbSShawn Tu 	s32 vblank_def;
580*d953e3cbSShawn Tu 	s32 vblank_min;
581*d953e3cbSShawn Tu 	s64 h_blank;
582*d953e3cbSShawn Tu 	s64 pixel_rate;
583*d953e3cbSShawn Tu 	s64 link_freq;
584*d953e3cbSShawn Tu 
585*d953e3cbSShawn Tu 	mutex_lock(&imx208->imx208_mx);
586*d953e3cbSShawn Tu 
587*d953e3cbSShawn Tu 	fmt->format.code = imx208_get_format_code(imx208);
588*d953e3cbSShawn Tu 	mode = v4l2_find_nearest_size(supported_modes,
589*d953e3cbSShawn Tu 				      ARRAY_SIZE(supported_modes), width, height,
590*d953e3cbSShawn Tu 				      fmt->format.width, fmt->format.height);
591*d953e3cbSShawn Tu 	imx208_mode_to_pad_format(imx208, mode, fmt);
592*d953e3cbSShawn Tu 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
593*d953e3cbSShawn Tu 		*v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
594*d953e3cbSShawn Tu 	} else {
595*d953e3cbSShawn Tu 		imx208->cur_mode = mode;
596*d953e3cbSShawn Tu 		__v4l2_ctrl_s_ctrl(imx208->link_freq, mode->link_freq_index);
597*d953e3cbSShawn Tu 		link_freq = link_freq_menu_items[mode->link_freq_index];
598*d953e3cbSShawn Tu 		pixel_rate = link_freq_to_pixel_rate(link_freq);
599*d953e3cbSShawn Tu 		__v4l2_ctrl_s_ctrl_int64(imx208->pixel_rate, pixel_rate);
600*d953e3cbSShawn Tu 		/* Update limits and set FPS to default */
601*d953e3cbSShawn Tu 		vblank_def = imx208->cur_mode->vts_def -
602*d953e3cbSShawn Tu 			     imx208->cur_mode->height;
603*d953e3cbSShawn Tu 		vblank_min = imx208->cur_mode->vts_min -
604*d953e3cbSShawn Tu 			     imx208->cur_mode->height;
605*d953e3cbSShawn Tu 		__v4l2_ctrl_modify_range(imx208->vblank, vblank_min,
606*d953e3cbSShawn Tu 					 IMX208_VTS_MAX - imx208->cur_mode->height,
607*d953e3cbSShawn Tu 					 1, vblank_def);
608*d953e3cbSShawn Tu 		__v4l2_ctrl_s_ctrl(imx208->vblank, vblank_def);
609*d953e3cbSShawn Tu 		h_blank =
610*d953e3cbSShawn Tu 			link_freq_configs[mode->link_freq_index].pixels_per_line
611*d953e3cbSShawn Tu 			 - imx208->cur_mode->width;
612*d953e3cbSShawn Tu 		__v4l2_ctrl_modify_range(imx208->hblank, h_blank,
613*d953e3cbSShawn Tu 					 h_blank, 1, h_blank);
614*d953e3cbSShawn Tu 	}
615*d953e3cbSShawn Tu 
616*d953e3cbSShawn Tu 	mutex_unlock(&imx208->imx208_mx);
617*d953e3cbSShawn Tu 
618*d953e3cbSShawn Tu 	return 0;
619*d953e3cbSShawn Tu }
620*d953e3cbSShawn Tu 
621*d953e3cbSShawn Tu /* Start streaming */
622*d953e3cbSShawn Tu static int imx208_start_streaming(struct imx208 *imx208)
623*d953e3cbSShawn Tu {
624*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
625*d953e3cbSShawn Tu 	const struct imx208_reg_list *reg_list;
626*d953e3cbSShawn Tu 	int ret, link_freq_index;
627*d953e3cbSShawn Tu 
628*d953e3cbSShawn Tu 	/* Setup PLL */
629*d953e3cbSShawn Tu 	link_freq_index = imx208->cur_mode->link_freq_index;
630*d953e3cbSShawn Tu 	reg_list = &link_freq_configs[link_freq_index].reg_list;
631*d953e3cbSShawn Tu 	ret = imx208_write_regs(imx208, reg_list->regs, reg_list->num_of_regs);
632*d953e3cbSShawn Tu 	if (ret) {
633*d953e3cbSShawn Tu 		dev_err(&client->dev, "%s failed to set plls\n", __func__);
634*d953e3cbSShawn Tu 		return ret;
635*d953e3cbSShawn Tu 	}
636*d953e3cbSShawn Tu 
637*d953e3cbSShawn Tu 	/* Apply default values of current mode */
638*d953e3cbSShawn Tu 	reg_list = &imx208->cur_mode->reg_list;
639*d953e3cbSShawn Tu 	ret = imx208_write_regs(imx208, reg_list->regs, reg_list->num_of_regs);
640*d953e3cbSShawn Tu 	if (ret) {
641*d953e3cbSShawn Tu 		dev_err(&client->dev, "%s failed to set mode\n", __func__);
642*d953e3cbSShawn Tu 		return ret;
643*d953e3cbSShawn Tu 	}
644*d953e3cbSShawn Tu 
645*d953e3cbSShawn Tu 	/* Apply customized values from user */
646*d953e3cbSShawn Tu 	ret =  __v4l2_ctrl_handler_setup(imx208->sd.ctrl_handler);
647*d953e3cbSShawn Tu 	if (ret)
648*d953e3cbSShawn Tu 		return ret;
649*d953e3cbSShawn Tu 
650*d953e3cbSShawn Tu 	/* set stream on register */
651*d953e3cbSShawn Tu 	return imx208_write_reg(imx208, IMX208_REG_MODE_SELECT,
652*d953e3cbSShawn Tu 				1, IMX208_MODE_STREAMING);
653*d953e3cbSShawn Tu }
654*d953e3cbSShawn Tu 
655*d953e3cbSShawn Tu /* Stop streaming */
656*d953e3cbSShawn Tu static int imx208_stop_streaming(struct imx208 *imx208)
657*d953e3cbSShawn Tu {
658*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
659*d953e3cbSShawn Tu 	int ret;
660*d953e3cbSShawn Tu 
661*d953e3cbSShawn Tu 	/* set stream off register */
662*d953e3cbSShawn Tu 	ret = imx208_write_reg(imx208, IMX208_REG_MODE_SELECT,
663*d953e3cbSShawn Tu 			       1, IMX208_MODE_STANDBY);
664*d953e3cbSShawn Tu 	if (ret)
665*d953e3cbSShawn Tu 		dev_err(&client->dev, "%s failed to set stream\n", __func__);
666*d953e3cbSShawn Tu 
667*d953e3cbSShawn Tu 	/*
668*d953e3cbSShawn Tu 	 * Return success even if it was an error, as there is nothing the
669*d953e3cbSShawn Tu 	 * caller can do about it.
670*d953e3cbSShawn Tu 	 */
671*d953e3cbSShawn Tu 	return 0;
672*d953e3cbSShawn Tu }
673*d953e3cbSShawn Tu 
674*d953e3cbSShawn Tu static int imx208_set_stream(struct v4l2_subdev *sd, int enable)
675*d953e3cbSShawn Tu {
676*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
677*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(sd);
678*d953e3cbSShawn Tu 	int ret = 0;
679*d953e3cbSShawn Tu 
680*d953e3cbSShawn Tu 	mutex_lock(&imx208->imx208_mx);
681*d953e3cbSShawn Tu 	if (imx208->streaming == enable) {
682*d953e3cbSShawn Tu 		mutex_unlock(&imx208->imx208_mx);
683*d953e3cbSShawn Tu 		return 0;
684*d953e3cbSShawn Tu 	}
685*d953e3cbSShawn Tu 
686*d953e3cbSShawn Tu 	if (enable) {
687*d953e3cbSShawn Tu 		ret = pm_runtime_get_sync(&client->dev);
688*d953e3cbSShawn Tu 		if (ret < 0)
689*d953e3cbSShawn Tu 			goto err_rpm_put;
690*d953e3cbSShawn Tu 
691*d953e3cbSShawn Tu 		/*
692*d953e3cbSShawn Tu 		 * Apply default & customized values
693*d953e3cbSShawn Tu 		 * and then start streaming.
694*d953e3cbSShawn Tu 		 */
695*d953e3cbSShawn Tu 		ret = imx208_start_streaming(imx208);
696*d953e3cbSShawn Tu 		if (ret)
697*d953e3cbSShawn Tu 			goto err_rpm_put;
698*d953e3cbSShawn Tu 	} else {
699*d953e3cbSShawn Tu 		imx208_stop_streaming(imx208);
700*d953e3cbSShawn Tu 		pm_runtime_put(&client->dev);
701*d953e3cbSShawn Tu 	}
702*d953e3cbSShawn Tu 
703*d953e3cbSShawn Tu 	imx208->streaming = enable;
704*d953e3cbSShawn Tu 	mutex_unlock(&imx208->imx208_mx);
705*d953e3cbSShawn Tu 
706*d953e3cbSShawn Tu 	/* vflip and hflip cannot change during streaming */
707*d953e3cbSShawn Tu 	v4l2_ctrl_grab(imx208->vflip, enable);
708*d953e3cbSShawn Tu 	v4l2_ctrl_grab(imx208->hflip, enable);
709*d953e3cbSShawn Tu 
710*d953e3cbSShawn Tu 	return ret;
711*d953e3cbSShawn Tu 
712*d953e3cbSShawn Tu err_rpm_put:
713*d953e3cbSShawn Tu 	pm_runtime_put(&client->dev);
714*d953e3cbSShawn Tu 	mutex_unlock(&imx208->imx208_mx);
715*d953e3cbSShawn Tu 
716*d953e3cbSShawn Tu 	return ret;
717*d953e3cbSShawn Tu }
718*d953e3cbSShawn Tu 
719*d953e3cbSShawn Tu static int __maybe_unused imx208_suspend(struct device *dev)
720*d953e3cbSShawn Tu {
721*d953e3cbSShawn Tu 	struct i2c_client *client = to_i2c_client(dev);
722*d953e3cbSShawn Tu 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
723*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
724*d953e3cbSShawn Tu 
725*d953e3cbSShawn Tu 	if (imx208->streaming)
726*d953e3cbSShawn Tu 		imx208_stop_streaming(imx208);
727*d953e3cbSShawn Tu 
728*d953e3cbSShawn Tu 	return 0;
729*d953e3cbSShawn Tu }
730*d953e3cbSShawn Tu 
731*d953e3cbSShawn Tu static int __maybe_unused imx208_resume(struct device *dev)
732*d953e3cbSShawn Tu {
733*d953e3cbSShawn Tu 	struct i2c_client *client = to_i2c_client(dev);
734*d953e3cbSShawn Tu 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
735*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
736*d953e3cbSShawn Tu 	int ret;
737*d953e3cbSShawn Tu 
738*d953e3cbSShawn Tu 	if (imx208->streaming) {
739*d953e3cbSShawn Tu 		ret = imx208_start_streaming(imx208);
740*d953e3cbSShawn Tu 		if (ret)
741*d953e3cbSShawn Tu 			goto error;
742*d953e3cbSShawn Tu 	}
743*d953e3cbSShawn Tu 
744*d953e3cbSShawn Tu 	return 0;
745*d953e3cbSShawn Tu 
746*d953e3cbSShawn Tu error:
747*d953e3cbSShawn Tu 	imx208_stop_streaming(imx208);
748*d953e3cbSShawn Tu 	imx208->streaming = 0;
749*d953e3cbSShawn Tu 
750*d953e3cbSShawn Tu 	return ret;
751*d953e3cbSShawn Tu }
752*d953e3cbSShawn Tu 
753*d953e3cbSShawn Tu /* Verify chip ID */
754*d953e3cbSShawn Tu static int imx208_identify_module(struct imx208 *imx208)
755*d953e3cbSShawn Tu {
756*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
757*d953e3cbSShawn Tu 	int ret;
758*d953e3cbSShawn Tu 	u32 val;
759*d953e3cbSShawn Tu 
760*d953e3cbSShawn Tu 	ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
761*d953e3cbSShawn Tu 			      2, &val);
762*d953e3cbSShawn Tu 	if (ret) {
763*d953e3cbSShawn Tu 		dev_err(&client->dev, "failed to read chip id %x\n",
764*d953e3cbSShawn Tu 			IMX208_CHIP_ID);
765*d953e3cbSShawn Tu 		return ret;
766*d953e3cbSShawn Tu 	}
767*d953e3cbSShawn Tu 
768*d953e3cbSShawn Tu 	if (val != IMX208_CHIP_ID) {
769*d953e3cbSShawn Tu 		dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
770*d953e3cbSShawn Tu 			IMX208_CHIP_ID, val);
771*d953e3cbSShawn Tu 		return -EIO;
772*d953e3cbSShawn Tu 	}
773*d953e3cbSShawn Tu 
774*d953e3cbSShawn Tu 	return 0;
775*d953e3cbSShawn Tu }
776*d953e3cbSShawn Tu 
777*d953e3cbSShawn Tu static const struct v4l2_subdev_video_ops imx208_video_ops = {
778*d953e3cbSShawn Tu 	.s_stream = imx208_set_stream,
779*d953e3cbSShawn Tu };
780*d953e3cbSShawn Tu 
781*d953e3cbSShawn Tu static const struct v4l2_subdev_pad_ops imx208_pad_ops = {
782*d953e3cbSShawn Tu 	.enum_mbus_code = imx208_enum_mbus_code,
783*d953e3cbSShawn Tu 	.get_fmt = imx208_get_pad_format,
784*d953e3cbSShawn Tu 	.set_fmt = imx208_set_pad_format,
785*d953e3cbSShawn Tu 	.enum_frame_size = imx208_enum_frame_size,
786*d953e3cbSShawn Tu };
787*d953e3cbSShawn Tu 
788*d953e3cbSShawn Tu static const struct v4l2_subdev_ops imx208_subdev_ops = {
789*d953e3cbSShawn Tu 	.video = &imx208_video_ops,
790*d953e3cbSShawn Tu 	.pad = &imx208_pad_ops,
791*d953e3cbSShawn Tu };
792*d953e3cbSShawn Tu 
793*d953e3cbSShawn Tu static const struct v4l2_subdev_internal_ops imx208_internal_ops = {
794*d953e3cbSShawn Tu 	.open = imx208_open,
795*d953e3cbSShawn Tu };
796*d953e3cbSShawn Tu 
797*d953e3cbSShawn Tu static int imx208_read_otp(struct imx208 *imx208)
798*d953e3cbSShawn Tu {
799*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
800*d953e3cbSShawn Tu 	struct i2c_msg msgs[2];
801*d953e3cbSShawn Tu 	u8 addr_buf[2] = { IMX208_OTP_BASE >> 8, IMX208_OTP_BASE & 0xff };
802*d953e3cbSShawn Tu 	int ret = 0;
803*d953e3cbSShawn Tu 
804*d953e3cbSShawn Tu 	mutex_lock(&imx208->imx208_mx);
805*d953e3cbSShawn Tu 
806*d953e3cbSShawn Tu 	if (imx208->otp_read)
807*d953e3cbSShawn Tu 		goto out_unlock;
808*d953e3cbSShawn Tu 
809*d953e3cbSShawn Tu 	ret = pm_runtime_get_sync(&client->dev);
810*d953e3cbSShawn Tu 	if (ret < 0) {
811*d953e3cbSShawn Tu 		pm_runtime_put_noidle(&client->dev);
812*d953e3cbSShawn Tu 		goto out_unlock;
813*d953e3cbSShawn Tu 	}
814*d953e3cbSShawn Tu 
815*d953e3cbSShawn Tu 	/* Write register address */
816*d953e3cbSShawn Tu 	msgs[0].addr = client->addr;
817*d953e3cbSShawn Tu 	msgs[0].flags = 0;
818*d953e3cbSShawn Tu 	msgs[0].len = ARRAY_SIZE(addr_buf);
819*d953e3cbSShawn Tu 	msgs[0].buf = addr_buf;
820*d953e3cbSShawn Tu 
821*d953e3cbSShawn Tu 	/* Read data from registers */
822*d953e3cbSShawn Tu 	msgs[1].addr = client->addr;
823*d953e3cbSShawn Tu 	msgs[1].flags = I2C_M_RD;
824*d953e3cbSShawn Tu 	msgs[1].len = sizeof(imx208->otp_data);
825*d953e3cbSShawn Tu 	msgs[1].buf = imx208->otp_data;
826*d953e3cbSShawn Tu 
827*d953e3cbSShawn Tu 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
828*d953e3cbSShawn Tu 	if (ret == ARRAY_SIZE(msgs)) {
829*d953e3cbSShawn Tu 		imx208->otp_read = true;
830*d953e3cbSShawn Tu 		ret = 0;
831*d953e3cbSShawn Tu 	}
832*d953e3cbSShawn Tu 
833*d953e3cbSShawn Tu 	pm_runtime_put(&client->dev);
834*d953e3cbSShawn Tu 
835*d953e3cbSShawn Tu out_unlock:
836*d953e3cbSShawn Tu 	mutex_unlock(&imx208->imx208_mx);
837*d953e3cbSShawn Tu 
838*d953e3cbSShawn Tu 	return ret;
839*d953e3cbSShawn Tu }
840*d953e3cbSShawn Tu 
841*d953e3cbSShawn Tu static ssize_t otp_read(struct file *filp, struct kobject *kobj,
842*d953e3cbSShawn Tu 			struct bin_attribute *bin_attr,
843*d953e3cbSShawn Tu 			char *buf, loff_t off, size_t count)
844*d953e3cbSShawn Tu {
845*d953e3cbSShawn Tu 	struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj));
846*d953e3cbSShawn Tu 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
847*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
848*d953e3cbSShawn Tu 	int ret;
849*d953e3cbSShawn Tu 
850*d953e3cbSShawn Tu 	ret = imx208_read_otp(imx208);
851*d953e3cbSShawn Tu 	if (ret)
852*d953e3cbSShawn Tu 		return ret;
853*d953e3cbSShawn Tu 
854*d953e3cbSShawn Tu 	memcpy(buf, &imx208->otp_data[off], count);
855*d953e3cbSShawn Tu 	return count;
856*d953e3cbSShawn Tu }
857*d953e3cbSShawn Tu 
858*d953e3cbSShawn Tu static const BIN_ATTR_RO(otp, IMX208_OTP_SIZE);
859*d953e3cbSShawn Tu 
860*d953e3cbSShawn Tu /* Initialize control handlers */
861*d953e3cbSShawn Tu static int imx208_init_controls(struct imx208 *imx208)
862*d953e3cbSShawn Tu {
863*d953e3cbSShawn Tu 	struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
864*d953e3cbSShawn Tu 	struct v4l2_ctrl_handler *ctrl_hdlr = &imx208->ctrl_handler;
865*d953e3cbSShawn Tu 	s64 exposure_max;
866*d953e3cbSShawn Tu 	s64 vblank_def;
867*d953e3cbSShawn Tu 	s64 vblank_min;
868*d953e3cbSShawn Tu 	s64 pixel_rate_min;
869*d953e3cbSShawn Tu 	s64 pixel_rate_max;
870*d953e3cbSShawn Tu 	int ret;
871*d953e3cbSShawn Tu 
872*d953e3cbSShawn Tu 	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
873*d953e3cbSShawn Tu 	if (ret)
874*d953e3cbSShawn Tu 		return ret;
875*d953e3cbSShawn Tu 
876*d953e3cbSShawn Tu 	mutex_init(&imx208->imx208_mx);
877*d953e3cbSShawn Tu 	ctrl_hdlr->lock = &imx208->imx208_mx;
878*d953e3cbSShawn Tu 	imx208->link_freq =
879*d953e3cbSShawn Tu 		v4l2_ctrl_new_int_menu(ctrl_hdlr,
880*d953e3cbSShawn Tu 				       &imx208_ctrl_ops,
881*d953e3cbSShawn Tu 				       V4L2_CID_LINK_FREQ,
882*d953e3cbSShawn Tu 				       ARRAY_SIZE(link_freq_menu_items) - 1,
883*d953e3cbSShawn Tu 				       0, link_freq_menu_items);
884*d953e3cbSShawn Tu 
885*d953e3cbSShawn Tu 	if (imx208->link_freq)
886*d953e3cbSShawn Tu 		imx208->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
887*d953e3cbSShawn Tu 
888*d953e3cbSShawn Tu 	pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
889*d953e3cbSShawn Tu 	pixel_rate_min =
890*d953e3cbSShawn Tu 		link_freq_to_pixel_rate(link_freq_menu_items[ARRAY_SIZE(link_freq_menu_items) - 1]);
891*d953e3cbSShawn Tu 	/* By default, PIXEL_RATE is read only */
892*d953e3cbSShawn Tu 	imx208->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops,
893*d953e3cbSShawn Tu 					       V4L2_CID_PIXEL_RATE,
894*d953e3cbSShawn Tu 					       pixel_rate_min, pixel_rate_max,
895*d953e3cbSShawn Tu 					       1, pixel_rate_max);
896*d953e3cbSShawn Tu 
897*d953e3cbSShawn Tu 	vblank_def = imx208->cur_mode->vts_def - imx208->cur_mode->height;
898*d953e3cbSShawn Tu 	vblank_min = imx208->cur_mode->vts_min - imx208->cur_mode->height;
899*d953e3cbSShawn Tu 	imx208->vblank =
900*d953e3cbSShawn Tu 		v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_VBLANK,
901*d953e3cbSShawn Tu 				  vblank_min,
902*d953e3cbSShawn Tu 				  IMX208_VTS_MAX - imx208->cur_mode->height, 1,
903*d953e3cbSShawn Tu 				  vblank_def);
904*d953e3cbSShawn Tu 
905*d953e3cbSShawn Tu 	imx208->hblank =
906*d953e3cbSShawn Tu 		v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_HBLANK,
907*d953e3cbSShawn Tu 				  IMX208_PPL_384MHZ - imx208->cur_mode->width,
908*d953e3cbSShawn Tu 				  IMX208_PPL_384MHZ - imx208->cur_mode->width,
909*d953e3cbSShawn Tu 				  1,
910*d953e3cbSShawn Tu 				  IMX208_PPL_384MHZ - imx208->cur_mode->width);
911*d953e3cbSShawn Tu 
912*d953e3cbSShawn Tu 	if (imx208->hblank)
913*d953e3cbSShawn Tu 		imx208->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
914*d953e3cbSShawn Tu 
915*d953e3cbSShawn Tu 	exposure_max = imx208->cur_mode->vts_def - 8;
916*d953e3cbSShawn Tu 	v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_EXPOSURE,
917*d953e3cbSShawn Tu 			  IMX208_EXPOSURE_MIN, exposure_max,
918*d953e3cbSShawn Tu 			  IMX208_EXPOSURE_STEP, IMX208_EXPOSURE_DEFAULT);
919*d953e3cbSShawn Tu 
920*d953e3cbSShawn Tu 	imx208->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops,
921*d953e3cbSShawn Tu 					  V4L2_CID_HFLIP, 0, 1, 1, 0);
922*d953e3cbSShawn Tu 	imx208->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops,
923*d953e3cbSShawn Tu 					  V4L2_CID_VFLIP, 0, 1, 1, 0);
924*d953e3cbSShawn Tu 
925*d953e3cbSShawn Tu 	v4l2_ctrl_new_std(ctrl_hdlr, &imx208_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
926*d953e3cbSShawn Tu 			  IMX208_ANA_GAIN_MIN, IMX208_ANA_GAIN_MAX,
927*d953e3cbSShawn Tu 			  IMX208_ANA_GAIN_STEP, IMX208_ANA_GAIN_DEFAULT);
928*d953e3cbSShawn Tu 
929*d953e3cbSShawn Tu 	v4l2_ctrl_new_custom(ctrl_hdlr, &imx208_digital_gain_control, NULL);
930*d953e3cbSShawn Tu 
931*d953e3cbSShawn Tu 	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx208_ctrl_ops,
932*d953e3cbSShawn Tu 				     V4L2_CID_TEST_PATTERN,
933*d953e3cbSShawn Tu 				     ARRAY_SIZE(imx208_test_pattern_menu) - 1,
934*d953e3cbSShawn Tu 				     0, 0, imx208_test_pattern_menu);
935*d953e3cbSShawn Tu 
936*d953e3cbSShawn Tu 	if (ctrl_hdlr->error) {
937*d953e3cbSShawn Tu 		ret = ctrl_hdlr->error;
938*d953e3cbSShawn Tu 		dev_err(&client->dev, "%s control init failed (%d)\n",
939*d953e3cbSShawn Tu 			__func__, ret);
940*d953e3cbSShawn Tu 		goto error;
941*d953e3cbSShawn Tu 	}
942*d953e3cbSShawn Tu 
943*d953e3cbSShawn Tu 	imx208->sd.ctrl_handler = ctrl_hdlr;
944*d953e3cbSShawn Tu 
945*d953e3cbSShawn Tu 	return 0;
946*d953e3cbSShawn Tu 
947*d953e3cbSShawn Tu error:
948*d953e3cbSShawn Tu 	v4l2_ctrl_handler_free(ctrl_hdlr);
949*d953e3cbSShawn Tu 	mutex_destroy(&imx208->imx208_mx);
950*d953e3cbSShawn Tu 
951*d953e3cbSShawn Tu 	return ret;
952*d953e3cbSShawn Tu }
953*d953e3cbSShawn Tu 
954*d953e3cbSShawn Tu static void imx208_free_controls(struct imx208 *imx208)
955*d953e3cbSShawn Tu {
956*d953e3cbSShawn Tu 	v4l2_ctrl_handler_free(imx208->sd.ctrl_handler);
957*d953e3cbSShawn Tu }
958*d953e3cbSShawn Tu 
959*d953e3cbSShawn Tu static int imx208_probe(struct i2c_client *client)
960*d953e3cbSShawn Tu {
961*d953e3cbSShawn Tu 	struct imx208 *imx208;
962*d953e3cbSShawn Tu 	int ret;
963*d953e3cbSShawn Tu 	u32 val = 0;
964*d953e3cbSShawn Tu 
965*d953e3cbSShawn Tu 	device_property_read_u32(&client->dev, "clock-frequency", &val);
966*d953e3cbSShawn Tu 	if (val != 19200000) {
967*d953e3cbSShawn Tu 		dev_err(&client->dev,
968*d953e3cbSShawn Tu 			"Unsupported clock-frequency %u. Expected 19200000.\n",
969*d953e3cbSShawn Tu 			val);
970*d953e3cbSShawn Tu 		return -EINVAL;
971*d953e3cbSShawn Tu 	}
972*d953e3cbSShawn Tu 
973*d953e3cbSShawn Tu 	imx208 = devm_kzalloc(&client->dev, sizeof(*imx208), GFP_KERNEL);
974*d953e3cbSShawn Tu 	if (!imx208)
975*d953e3cbSShawn Tu 		return -ENOMEM;
976*d953e3cbSShawn Tu 
977*d953e3cbSShawn Tu 	/* Initialize subdev */
978*d953e3cbSShawn Tu 	v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops);
979*d953e3cbSShawn Tu 
980*d953e3cbSShawn Tu 	/* Check module identity */
981*d953e3cbSShawn Tu 	ret = imx208_identify_module(imx208);
982*d953e3cbSShawn Tu 	if (ret) {
983*d953e3cbSShawn Tu 		dev_err(&client->dev, "failed to find sensor: %d", ret);
984*d953e3cbSShawn Tu 		goto error_probe;
985*d953e3cbSShawn Tu 	}
986*d953e3cbSShawn Tu 
987*d953e3cbSShawn Tu 	/* Set default mode to max resolution */
988*d953e3cbSShawn Tu 	imx208->cur_mode = &supported_modes[0];
989*d953e3cbSShawn Tu 
990*d953e3cbSShawn Tu 	ret = imx208_init_controls(imx208);
991*d953e3cbSShawn Tu 	if (ret) {
992*d953e3cbSShawn Tu 		dev_err(&client->dev, "failed to init controls: %d", ret);
993*d953e3cbSShawn Tu 		goto error_probe;
994*d953e3cbSShawn Tu 	}
995*d953e3cbSShawn Tu 
996*d953e3cbSShawn Tu 	/* Initialize subdev */
997*d953e3cbSShawn Tu 	imx208->sd.internal_ops = &imx208_internal_ops;
998*d953e3cbSShawn Tu 	imx208->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
999*d953e3cbSShawn Tu 	imx208->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1000*d953e3cbSShawn Tu 
1001*d953e3cbSShawn Tu 	/* Initialize source pad */
1002*d953e3cbSShawn Tu 	imx208->pad.flags = MEDIA_PAD_FL_SOURCE;
1003*d953e3cbSShawn Tu 	ret = media_entity_pads_init(&imx208->sd.entity, 1, &imx208->pad);
1004*d953e3cbSShawn Tu 	if (ret) {
1005*d953e3cbSShawn Tu 		dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
1006*d953e3cbSShawn Tu 		goto error_handler_free;
1007*d953e3cbSShawn Tu 	}
1008*d953e3cbSShawn Tu 
1009*d953e3cbSShawn Tu 	ret = v4l2_async_register_subdev_sensor(&imx208->sd);
1010*d953e3cbSShawn Tu 	if (ret < 0)
1011*d953e3cbSShawn Tu 		goto error_media_entity;
1012*d953e3cbSShawn Tu 
1013*d953e3cbSShawn Tu 	ret = device_create_bin_file(&client->dev, &bin_attr_otp);
1014*d953e3cbSShawn Tu 	if (ret) {
1015*d953e3cbSShawn Tu 		dev_err(&client->dev, "sysfs otp creation failed\n");
1016*d953e3cbSShawn Tu 		goto error_async_subdev;
1017*d953e3cbSShawn Tu 	}
1018*d953e3cbSShawn Tu 
1019*d953e3cbSShawn Tu 	pm_runtime_set_active(&client->dev);
1020*d953e3cbSShawn Tu 	pm_runtime_enable(&client->dev);
1021*d953e3cbSShawn Tu 	pm_runtime_idle(&client->dev);
1022*d953e3cbSShawn Tu 
1023*d953e3cbSShawn Tu 	return 0;
1024*d953e3cbSShawn Tu 
1025*d953e3cbSShawn Tu error_async_subdev:
1026*d953e3cbSShawn Tu 	v4l2_async_unregister_subdev(&imx208->sd);
1027*d953e3cbSShawn Tu 
1028*d953e3cbSShawn Tu error_media_entity:
1029*d953e3cbSShawn Tu 	media_entity_cleanup(&imx208->sd.entity);
1030*d953e3cbSShawn Tu 
1031*d953e3cbSShawn Tu error_handler_free:
1032*d953e3cbSShawn Tu 	imx208_free_controls(imx208);
1033*d953e3cbSShawn Tu 
1034*d953e3cbSShawn Tu error_probe:
1035*d953e3cbSShawn Tu 	mutex_destroy(&imx208->imx208_mx);
1036*d953e3cbSShawn Tu 
1037*d953e3cbSShawn Tu 	return ret;
1038*d953e3cbSShawn Tu }
1039*d953e3cbSShawn Tu 
1040*d953e3cbSShawn Tu static int imx208_remove(struct i2c_client *client)
1041*d953e3cbSShawn Tu {
1042*d953e3cbSShawn Tu 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1043*d953e3cbSShawn Tu 	struct imx208 *imx208 = to_imx208(sd);
1044*d953e3cbSShawn Tu 
1045*d953e3cbSShawn Tu 	device_remove_bin_file(&client->dev, &bin_attr_otp);
1046*d953e3cbSShawn Tu 	v4l2_async_unregister_subdev(sd);
1047*d953e3cbSShawn Tu 	media_entity_cleanup(&sd->entity);
1048*d953e3cbSShawn Tu 	imx208_free_controls(imx208);
1049*d953e3cbSShawn Tu 
1050*d953e3cbSShawn Tu 	pm_runtime_disable(&client->dev);
1051*d953e3cbSShawn Tu 	pm_runtime_set_suspended(&client->dev);
1052*d953e3cbSShawn Tu 
1053*d953e3cbSShawn Tu 	mutex_destroy(&imx208->imx208_mx);
1054*d953e3cbSShawn Tu 
1055*d953e3cbSShawn Tu 	return 0;
1056*d953e3cbSShawn Tu }
1057*d953e3cbSShawn Tu 
1058*d953e3cbSShawn Tu static const struct dev_pm_ops imx208_pm_ops = {
1059*d953e3cbSShawn Tu 	SET_SYSTEM_SLEEP_PM_OPS(imx208_suspend, imx208_resume)
1060*d953e3cbSShawn Tu };
1061*d953e3cbSShawn Tu 
1062*d953e3cbSShawn Tu #ifdef CONFIG_ACPI
1063*d953e3cbSShawn Tu static const struct acpi_device_id imx208_acpi_ids[] = {
1064*d953e3cbSShawn Tu 	{ "INT3478" },
1065*d953e3cbSShawn Tu 	{ /* sentinel */ }
1066*d953e3cbSShawn Tu };
1067*d953e3cbSShawn Tu 
1068*d953e3cbSShawn Tu MODULE_DEVICE_TABLE(acpi, imx208_acpi_ids);
1069*d953e3cbSShawn Tu #endif
1070*d953e3cbSShawn Tu 
1071*d953e3cbSShawn Tu static struct i2c_driver imx208_i2c_driver = {
1072*d953e3cbSShawn Tu 	.driver = {
1073*d953e3cbSShawn Tu 		.name = "imx208",
1074*d953e3cbSShawn Tu 		.pm = &imx208_pm_ops,
1075*d953e3cbSShawn Tu 		.acpi_match_table = ACPI_PTR(imx208_acpi_ids),
1076*d953e3cbSShawn Tu 	},
1077*d953e3cbSShawn Tu 	.probe_new = imx208_probe,
1078*d953e3cbSShawn Tu 	.remove = imx208_remove,
1079*d953e3cbSShawn Tu };
1080*d953e3cbSShawn Tu 
1081*d953e3cbSShawn Tu module_i2c_driver(imx208_i2c_driver);
1082*d953e3cbSShawn Tu 
1083*d953e3cbSShawn Tu MODULE_AUTHOR("Yeh, Andy <andy.yeh@intel.com>");
1084*d953e3cbSShawn Tu MODULE_AUTHOR("Chen, Ping-chung <ping-chung.chen@intel.com>");
1085*d953e3cbSShawn Tu MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
1086*d953e3cbSShawn Tu MODULE_DESCRIPTION("Sony IMX208 sensor driver");
1087*d953e3cbSShawn Tu MODULE_LICENSE("GPL v2");
1088