xref: /openbmc/linux/drivers/media/i2c/imx334.c (revision 9746b11715c3949241e2d88cb9057da4adab7e02)
1*9746b117SMartina Krasteva // SPDX-License-Identifier: GPL-2.0-only
2*9746b117SMartina Krasteva /*
3*9746b117SMartina Krasteva  * Sony imx334 sensor driver
4*9746b117SMartina Krasteva  *
5*9746b117SMartina Krasteva  * Copyright (C) 2021 Intel Corporation
6*9746b117SMartina Krasteva  */
7*9746b117SMartina Krasteva #include <asm/unaligned.h>
8*9746b117SMartina Krasteva 
9*9746b117SMartina Krasteva #include <linux/clk.h>
10*9746b117SMartina Krasteva #include <linux/delay.h>
11*9746b117SMartina Krasteva #include <linux/i2c.h>
12*9746b117SMartina Krasteva #include <linux/module.h>
13*9746b117SMartina Krasteva #include <linux/pm_runtime.h>
14*9746b117SMartina Krasteva 
15*9746b117SMartina Krasteva #include <media/v4l2-ctrls.h>
16*9746b117SMartina Krasteva #include <media/v4l2-fwnode.h>
17*9746b117SMartina Krasteva #include <media/v4l2-subdev.h>
18*9746b117SMartina Krasteva 
19*9746b117SMartina Krasteva /* Streaming Mode */
20*9746b117SMartina Krasteva #define IMX334_REG_MODE_SELECT	0x3000
21*9746b117SMartina Krasteva #define IMX334_MODE_STANDBY	0x01
22*9746b117SMartina Krasteva #define IMX334_MODE_STREAMING	0x00
23*9746b117SMartina Krasteva 
24*9746b117SMartina Krasteva /* Lines per frame */
25*9746b117SMartina Krasteva #define IMX334_REG_LPFR		0x3030
26*9746b117SMartina Krasteva 
27*9746b117SMartina Krasteva /* Chip ID */
28*9746b117SMartina Krasteva #define IMX334_REG_ID		0x3044
29*9746b117SMartina Krasteva #define IMX334_ID		0x1e
30*9746b117SMartina Krasteva 
31*9746b117SMartina Krasteva /* Exposure control */
32*9746b117SMartina Krasteva #define IMX334_REG_SHUTTER	0x3058
33*9746b117SMartina Krasteva #define IMX334_EXPOSURE_MIN	1
34*9746b117SMartina Krasteva #define IMX334_EXPOSURE_OFFSET	5
35*9746b117SMartina Krasteva #define IMX334_EXPOSURE_STEP	1
36*9746b117SMartina Krasteva #define IMX334_EXPOSURE_DEFAULT	0x0648
37*9746b117SMartina Krasteva 
38*9746b117SMartina Krasteva /* Analog gain control */
39*9746b117SMartina Krasteva #define IMX334_REG_AGAIN	0x30e8
40*9746b117SMartina Krasteva #define IMX334_AGAIN_MIN	0
41*9746b117SMartina Krasteva #define IMX334_AGAIN_MAX	240
42*9746b117SMartina Krasteva #define IMX334_AGAIN_STEP	1
43*9746b117SMartina Krasteva #define IMX334_AGAIN_DEFAULT	0
44*9746b117SMartina Krasteva 
45*9746b117SMartina Krasteva /* Group hold register */
46*9746b117SMartina Krasteva #define IMX334_REG_HOLD		0x3001
47*9746b117SMartina Krasteva 
48*9746b117SMartina Krasteva /* Input clock rate */
49*9746b117SMartina Krasteva #define IMX334_INCLK_RATE	24000000
50*9746b117SMartina Krasteva 
51*9746b117SMartina Krasteva /* CSI2 HW configuration */
52*9746b117SMartina Krasteva #define IMX334_LINK_FREQ	891000000
53*9746b117SMartina Krasteva #define IMX334_NUM_DATA_LANES	4
54*9746b117SMartina Krasteva 
55*9746b117SMartina Krasteva #define IMX334_REG_MIN		0x00
56*9746b117SMartina Krasteva #define IMX334_REG_MAX		0xfffff
57*9746b117SMartina Krasteva 
58*9746b117SMartina Krasteva /**
59*9746b117SMartina Krasteva  * struct imx334_reg - imx334 sensor register
60*9746b117SMartina Krasteva  * @address: Register address
61*9746b117SMartina Krasteva  * @val: Register value
62*9746b117SMartina Krasteva  */
63*9746b117SMartina Krasteva struct imx334_reg {
64*9746b117SMartina Krasteva 	u16 address;
65*9746b117SMartina Krasteva 	u8 val;
66*9746b117SMartina Krasteva };
67*9746b117SMartina Krasteva 
68*9746b117SMartina Krasteva /**
69*9746b117SMartina Krasteva  * struct imx334_reg_list - imx334 sensor register list
70*9746b117SMartina Krasteva  * @num_of_regs: Number of registers in the list
71*9746b117SMartina Krasteva  * @regs: Pointer to register list
72*9746b117SMartina Krasteva  */
73*9746b117SMartina Krasteva struct imx334_reg_list {
74*9746b117SMartina Krasteva 	u32 num_of_regs;
75*9746b117SMartina Krasteva 	const struct imx334_reg *regs;
76*9746b117SMartina Krasteva };
77*9746b117SMartina Krasteva 
78*9746b117SMartina Krasteva /**
79*9746b117SMartina Krasteva  * struct imx334_mode - imx334 sensor mode structure
80*9746b117SMartina Krasteva  * @width: Frame width
81*9746b117SMartina Krasteva  * @height: Frame height
82*9746b117SMartina Krasteva  * @code: Format code
83*9746b117SMartina Krasteva  * @hblank: Horizontal blanking in lines
84*9746b117SMartina Krasteva  * @vblank: Vertical blanking in lines
85*9746b117SMartina Krasteva  * @vblank_min: Minimal vertical blanking in lines
86*9746b117SMartina Krasteva  * @vblank_max: Maximum vertical blanking in lines
87*9746b117SMartina Krasteva  * @pclk: Sensor pixel clock
88*9746b117SMartina Krasteva  * @link_freq_idx: Link frequency index
89*9746b117SMartina Krasteva  * @reg_list: Register list for sensor mode
90*9746b117SMartina Krasteva  */
91*9746b117SMartina Krasteva struct imx334_mode {
92*9746b117SMartina Krasteva 	u32 width;
93*9746b117SMartina Krasteva 	u32 height;
94*9746b117SMartina Krasteva 	u32 code;
95*9746b117SMartina Krasteva 	u32 hblank;
96*9746b117SMartina Krasteva 	u32 vblank;
97*9746b117SMartina Krasteva 	u32 vblank_min;
98*9746b117SMartina Krasteva 	u32 vblank_max;
99*9746b117SMartina Krasteva 	u64 pclk;
100*9746b117SMartina Krasteva 	u32 link_freq_idx;
101*9746b117SMartina Krasteva 	struct imx334_reg_list reg_list;
102*9746b117SMartina Krasteva };
103*9746b117SMartina Krasteva 
104*9746b117SMartina Krasteva /**
105*9746b117SMartina Krasteva  * struct imx334 - imx334 sensor device structure
106*9746b117SMartina Krasteva  * @dev: Pointer to generic device
107*9746b117SMartina Krasteva  * @client: Pointer to i2c client
108*9746b117SMartina Krasteva  * @sd: V4L2 sub-device
109*9746b117SMartina Krasteva  * @pad: Media pad. Only one pad supported
110*9746b117SMartina Krasteva  * @reset_gpio: Sensor reset gpio
111*9746b117SMartina Krasteva  * @inclk: Sensor input clock
112*9746b117SMartina Krasteva  * @ctrl_handler: V4L2 control handler
113*9746b117SMartina Krasteva  * @link_freq_ctrl: Pointer to link frequency control
114*9746b117SMartina Krasteva  * @pclk_ctrl: Pointer to pixel clock control
115*9746b117SMartina Krasteva  * @hblank_ctrl: Pointer to horizontal blanking control
116*9746b117SMartina Krasteva  * @vblank_ctrl: Pointer to vertical blanking control
117*9746b117SMartina Krasteva  * @exp_ctrl: Pointer to exposure control
118*9746b117SMartina Krasteva  * @again_ctrl: Pointer to analog gain control
119*9746b117SMartina Krasteva  * @vblank: Vertical blanking in lines
120*9746b117SMartina Krasteva  * @cur_mode: Pointer to current selected sensor mode
121*9746b117SMartina Krasteva  * @mutex: Mutex for serializing sensor controls
122*9746b117SMartina Krasteva  * @streaming: Flag indicating streaming state
123*9746b117SMartina Krasteva  */
124*9746b117SMartina Krasteva struct imx334 {
125*9746b117SMartina Krasteva 	struct device *dev;
126*9746b117SMartina Krasteva 	struct i2c_client *client;
127*9746b117SMartina Krasteva 	struct v4l2_subdev sd;
128*9746b117SMartina Krasteva 	struct media_pad pad;
129*9746b117SMartina Krasteva 	struct gpio_desc *reset_gpio;
130*9746b117SMartina Krasteva 	struct clk *inclk;
131*9746b117SMartina Krasteva 	struct v4l2_ctrl_handler ctrl_handler;
132*9746b117SMartina Krasteva 	struct v4l2_ctrl *link_freq_ctrl;
133*9746b117SMartina Krasteva 	struct v4l2_ctrl *pclk_ctrl;
134*9746b117SMartina Krasteva 	struct v4l2_ctrl *hblank_ctrl;
135*9746b117SMartina Krasteva 	struct v4l2_ctrl *vblank_ctrl;
136*9746b117SMartina Krasteva 	struct {
137*9746b117SMartina Krasteva 		struct v4l2_ctrl *exp_ctrl;
138*9746b117SMartina Krasteva 		struct v4l2_ctrl *again_ctrl;
139*9746b117SMartina Krasteva 	};
140*9746b117SMartina Krasteva 	u32 vblank;
141*9746b117SMartina Krasteva 	const struct imx334_mode *cur_mode;
142*9746b117SMartina Krasteva 	struct mutex mutex;
143*9746b117SMartina Krasteva 	bool streaming;
144*9746b117SMartina Krasteva };
145*9746b117SMartina Krasteva 
146*9746b117SMartina Krasteva static const s64 link_freq[] = {
147*9746b117SMartina Krasteva 	IMX334_LINK_FREQ,
148*9746b117SMartina Krasteva };
149*9746b117SMartina Krasteva 
150*9746b117SMartina Krasteva /* Sensor mode registers */
151*9746b117SMartina Krasteva static const struct imx334_reg mode_3840x2160_regs[] = {
152*9746b117SMartina Krasteva 	{0x3000, 0x01},
153*9746b117SMartina Krasteva 	{0x3002, 0x00},
154*9746b117SMartina Krasteva 	{0x3018, 0x04},
155*9746b117SMartina Krasteva 	{0x37b0, 0x36},
156*9746b117SMartina Krasteva 	{0x304c, 0x00},
157*9746b117SMartina Krasteva 	{0x300c, 0x3b},
158*9746b117SMartina Krasteva 	{0x300d, 0x2a},
159*9746b117SMartina Krasteva 	{0x3034, 0x26},
160*9746b117SMartina Krasteva 	{0x3035, 0x02},
161*9746b117SMartina Krasteva 	{0x314c, 0x29},
162*9746b117SMartina Krasteva 	{0x314d, 0x01},
163*9746b117SMartina Krasteva 	{0x315a, 0x02},
164*9746b117SMartina Krasteva 	{0x3168, 0xa0},
165*9746b117SMartina Krasteva 	{0x316a, 0x7e},
166*9746b117SMartina Krasteva 	{0x3288, 0x21},
167*9746b117SMartina Krasteva 	{0x328a, 0x02},
168*9746b117SMartina Krasteva 	{0x302c, 0x3c},
169*9746b117SMartina Krasteva 	{0x302e, 0x00},
170*9746b117SMartina Krasteva 	{0x302f, 0x0f},
171*9746b117SMartina Krasteva 	{0x3076, 0x70},
172*9746b117SMartina Krasteva 	{0x3077, 0x08},
173*9746b117SMartina Krasteva 	{0x3090, 0x70},
174*9746b117SMartina Krasteva 	{0x3091, 0x08},
175*9746b117SMartina Krasteva 	{0x30d8, 0x20},
176*9746b117SMartina Krasteva 	{0x30d9, 0x12},
177*9746b117SMartina Krasteva 	{0x3308, 0x70},
178*9746b117SMartina Krasteva 	{0x3309, 0x08},
179*9746b117SMartina Krasteva 	{0x3414, 0x05},
180*9746b117SMartina Krasteva 	{0x3416, 0x18},
181*9746b117SMartina Krasteva 	{0x35ac, 0x0e},
182*9746b117SMartina Krasteva 	{0x3648, 0x01},
183*9746b117SMartina Krasteva 	{0x364a, 0x04},
184*9746b117SMartina Krasteva 	{0x364c, 0x04},
185*9746b117SMartina Krasteva 	{0x3678, 0x01},
186*9746b117SMartina Krasteva 	{0x367c, 0x31},
187*9746b117SMartina Krasteva 	{0x367e, 0x31},
188*9746b117SMartina Krasteva 	{0x3708, 0x02},
189*9746b117SMartina Krasteva 	{0x3714, 0x01},
190*9746b117SMartina Krasteva 	{0x3715, 0x02},
191*9746b117SMartina Krasteva 	{0x3716, 0x02},
192*9746b117SMartina Krasteva 	{0x3717, 0x02},
193*9746b117SMartina Krasteva 	{0x371c, 0x3d},
194*9746b117SMartina Krasteva 	{0x371d, 0x3f},
195*9746b117SMartina Krasteva 	{0x372c, 0x00},
196*9746b117SMartina Krasteva 	{0x372d, 0x00},
197*9746b117SMartina Krasteva 	{0x372e, 0x46},
198*9746b117SMartina Krasteva 	{0x372f, 0x00},
199*9746b117SMartina Krasteva 	{0x3730, 0x89},
200*9746b117SMartina Krasteva 	{0x3731, 0x00},
201*9746b117SMartina Krasteva 	{0x3732, 0x08},
202*9746b117SMartina Krasteva 	{0x3733, 0x01},
203*9746b117SMartina Krasteva 	{0x3734, 0xfe},
204*9746b117SMartina Krasteva 	{0x3735, 0x05},
205*9746b117SMartina Krasteva 	{0x375d, 0x00},
206*9746b117SMartina Krasteva 	{0x375e, 0x00},
207*9746b117SMartina Krasteva 	{0x375f, 0x61},
208*9746b117SMartina Krasteva 	{0x3760, 0x06},
209*9746b117SMartina Krasteva 	{0x3768, 0x1b},
210*9746b117SMartina Krasteva 	{0x3769, 0x1b},
211*9746b117SMartina Krasteva 	{0x376a, 0x1a},
212*9746b117SMartina Krasteva 	{0x376b, 0x19},
213*9746b117SMartina Krasteva 	{0x376c, 0x18},
214*9746b117SMartina Krasteva 	{0x376d, 0x14},
215*9746b117SMartina Krasteva 	{0x376e, 0x0f},
216*9746b117SMartina Krasteva 	{0x3776, 0x00},
217*9746b117SMartina Krasteva 	{0x3777, 0x00},
218*9746b117SMartina Krasteva 	{0x3778, 0x46},
219*9746b117SMartina Krasteva 	{0x3779, 0x00},
220*9746b117SMartina Krasteva 	{0x377a, 0x08},
221*9746b117SMartina Krasteva 	{0x377b, 0x01},
222*9746b117SMartina Krasteva 	{0x377c, 0x45},
223*9746b117SMartina Krasteva 	{0x377d, 0x01},
224*9746b117SMartina Krasteva 	{0x377e, 0x23},
225*9746b117SMartina Krasteva 	{0x377f, 0x02},
226*9746b117SMartina Krasteva 	{0x3780, 0xd9},
227*9746b117SMartina Krasteva 	{0x3781, 0x03},
228*9746b117SMartina Krasteva 	{0x3782, 0xf5},
229*9746b117SMartina Krasteva 	{0x3783, 0x06},
230*9746b117SMartina Krasteva 	{0x3784, 0xa5},
231*9746b117SMartina Krasteva 	{0x3788, 0x0f},
232*9746b117SMartina Krasteva 	{0x378a, 0xd9},
233*9746b117SMartina Krasteva 	{0x378b, 0x03},
234*9746b117SMartina Krasteva 	{0x378c, 0xeb},
235*9746b117SMartina Krasteva 	{0x378d, 0x05},
236*9746b117SMartina Krasteva 	{0x378e, 0x87},
237*9746b117SMartina Krasteva 	{0x378f, 0x06},
238*9746b117SMartina Krasteva 	{0x3790, 0xf5},
239*9746b117SMartina Krasteva 	{0x3792, 0x43},
240*9746b117SMartina Krasteva 	{0x3794, 0x7a},
241*9746b117SMartina Krasteva 	{0x3796, 0xa1},
242*9746b117SMartina Krasteva 	{0x3e04, 0x0e},
243*9746b117SMartina Krasteva 	{0x3a00, 0x01},
244*9746b117SMartina Krasteva };
245*9746b117SMartina Krasteva 
246*9746b117SMartina Krasteva /* Supported sensor mode configurations */
247*9746b117SMartina Krasteva static const struct imx334_mode supported_mode = {
248*9746b117SMartina Krasteva 	.width = 3840,
249*9746b117SMartina Krasteva 	.height = 2160,
250*9746b117SMartina Krasteva 	.hblank = 560,
251*9746b117SMartina Krasteva 	.vblank = 2340,
252*9746b117SMartina Krasteva 	.vblank_min = 90,
253*9746b117SMartina Krasteva 	.vblank_max = 132840,
254*9746b117SMartina Krasteva 	.pclk = 594000000,
255*9746b117SMartina Krasteva 	.link_freq_idx = 0,
256*9746b117SMartina Krasteva 	.code = MEDIA_BUS_FMT_SRGGB12_1X12,
257*9746b117SMartina Krasteva 	.reg_list = {
258*9746b117SMartina Krasteva 		.num_of_regs = ARRAY_SIZE(mode_3840x2160_regs),
259*9746b117SMartina Krasteva 		.regs = mode_3840x2160_regs,
260*9746b117SMartina Krasteva 	},
261*9746b117SMartina Krasteva };
262*9746b117SMartina Krasteva 
263*9746b117SMartina Krasteva /**
264*9746b117SMartina Krasteva  * to_imx334() - imv334 V4L2 sub-device to imx334 device.
265*9746b117SMartina Krasteva  * @subdev: pointer to imx334 V4L2 sub-device
266*9746b117SMartina Krasteva  *
267*9746b117SMartina Krasteva  * Return: pointer to imx334 device
268*9746b117SMartina Krasteva  */
269*9746b117SMartina Krasteva static inline struct imx334 *to_imx334(struct v4l2_subdev *subdev)
270*9746b117SMartina Krasteva {
271*9746b117SMartina Krasteva 	return container_of(subdev, struct imx334, sd);
272*9746b117SMartina Krasteva }
273*9746b117SMartina Krasteva 
274*9746b117SMartina Krasteva /**
275*9746b117SMartina Krasteva  * imx334_read_reg() - Read registers.
276*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
277*9746b117SMartina Krasteva  * @reg: register address
278*9746b117SMartina Krasteva  * @len: length of bytes to read. Max supported bytes is 4
279*9746b117SMartina Krasteva  * @val: pointer to register value to be filled.
280*9746b117SMartina Krasteva  *
281*9746b117SMartina Krasteva  * Big endian register addresses with little endian values.
282*9746b117SMartina Krasteva  *
283*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
284*9746b117SMartina Krasteva  */
285*9746b117SMartina Krasteva static int imx334_read_reg(struct imx334 *imx334, u16 reg, u32 len, u32 *val)
286*9746b117SMartina Krasteva {
287*9746b117SMartina Krasteva 	struct i2c_client *client = v4l2_get_subdevdata(&imx334->sd);
288*9746b117SMartina Krasteva 	struct i2c_msg msgs[2] = {0};
289*9746b117SMartina Krasteva 	u8 addr_buf[2] = {0};
290*9746b117SMartina Krasteva 	u8 data_buf[4] = {0};
291*9746b117SMartina Krasteva 	int ret;
292*9746b117SMartina Krasteva 
293*9746b117SMartina Krasteva 	if (WARN_ON(len > 4))
294*9746b117SMartina Krasteva 		return -EINVAL;
295*9746b117SMartina Krasteva 
296*9746b117SMartina Krasteva 	put_unaligned_be16(reg, addr_buf);
297*9746b117SMartina Krasteva 
298*9746b117SMartina Krasteva 	/* Write register address */
299*9746b117SMartina Krasteva 	msgs[0].addr = client->addr;
300*9746b117SMartina Krasteva 	msgs[0].flags = 0;
301*9746b117SMartina Krasteva 	msgs[0].len = ARRAY_SIZE(addr_buf);
302*9746b117SMartina Krasteva 	msgs[0].buf = addr_buf;
303*9746b117SMartina Krasteva 
304*9746b117SMartina Krasteva 	/* Read data from register */
305*9746b117SMartina Krasteva 	msgs[1].addr = client->addr;
306*9746b117SMartina Krasteva 	msgs[1].flags = I2C_M_RD;
307*9746b117SMartina Krasteva 	msgs[1].len = len;
308*9746b117SMartina Krasteva 	msgs[1].buf = data_buf;
309*9746b117SMartina Krasteva 
310*9746b117SMartina Krasteva 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
311*9746b117SMartina Krasteva 	if (ret != ARRAY_SIZE(msgs))
312*9746b117SMartina Krasteva 		return -EIO;
313*9746b117SMartina Krasteva 
314*9746b117SMartina Krasteva 	*val = get_unaligned_le32(data_buf);
315*9746b117SMartina Krasteva 
316*9746b117SMartina Krasteva 	return 0;
317*9746b117SMartina Krasteva }
318*9746b117SMartina Krasteva 
319*9746b117SMartina Krasteva /**
320*9746b117SMartina Krasteva  * imx334_write_reg() - Write register
321*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
322*9746b117SMartina Krasteva  * @reg: register address
323*9746b117SMartina Krasteva  * @len: length of bytes. Max supported bytes is 4
324*9746b117SMartina Krasteva  * @val: register value
325*9746b117SMartina Krasteva  *
326*9746b117SMartina Krasteva  * Big endian register addresses with little endian values.
327*9746b117SMartina Krasteva  *
328*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
329*9746b117SMartina Krasteva  */
330*9746b117SMartina Krasteva static int imx334_write_reg(struct imx334 *imx334, u16 reg, u32 len, u32 val)
331*9746b117SMartina Krasteva {
332*9746b117SMartina Krasteva 	struct i2c_client *client = v4l2_get_subdevdata(&imx334->sd);
333*9746b117SMartina Krasteva 	u8 buf[6] = {0};
334*9746b117SMartina Krasteva 
335*9746b117SMartina Krasteva 	if (WARN_ON(len > 4))
336*9746b117SMartina Krasteva 		return -EINVAL;
337*9746b117SMartina Krasteva 
338*9746b117SMartina Krasteva 	put_unaligned_be16(reg, buf);
339*9746b117SMartina Krasteva 	put_unaligned_le32(val, buf + 2);
340*9746b117SMartina Krasteva 	if (i2c_master_send(client, buf, len + 2) != len + 2)
341*9746b117SMartina Krasteva 		return -EIO;
342*9746b117SMartina Krasteva 
343*9746b117SMartina Krasteva 	return 0;
344*9746b117SMartina Krasteva }
345*9746b117SMartina Krasteva 
346*9746b117SMartina Krasteva /**
347*9746b117SMartina Krasteva  * imx334_write_regs() - Write a list of registers
348*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
349*9746b117SMartina Krasteva  * @regs: list of registers to be written
350*9746b117SMartina Krasteva  * @len: length of registers array
351*9746b117SMartina Krasteva  *
352*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
353*9746b117SMartina Krasteva  */
354*9746b117SMartina Krasteva static int imx334_write_regs(struct imx334 *imx334,
355*9746b117SMartina Krasteva 			     const struct imx334_reg *regs, u32 len)
356*9746b117SMartina Krasteva {
357*9746b117SMartina Krasteva 	unsigned int i;
358*9746b117SMartina Krasteva 	int ret;
359*9746b117SMartina Krasteva 
360*9746b117SMartina Krasteva 	for (i = 0; i < len; i++) {
361*9746b117SMartina Krasteva 		ret = imx334_write_reg(imx334, regs[i].address, 1, regs[i].val);
362*9746b117SMartina Krasteva 		if (ret)
363*9746b117SMartina Krasteva 			return ret;
364*9746b117SMartina Krasteva 	}
365*9746b117SMartina Krasteva 
366*9746b117SMartina Krasteva 	return 0;
367*9746b117SMartina Krasteva }
368*9746b117SMartina Krasteva 
369*9746b117SMartina Krasteva /**
370*9746b117SMartina Krasteva  * imx334_update_controls() - Update control ranges based on streaming mode
371*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
372*9746b117SMartina Krasteva  * @mode: pointer to imx334_mode sensor mode
373*9746b117SMartina Krasteva  *
374*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
375*9746b117SMartina Krasteva  */
376*9746b117SMartina Krasteva static int imx334_update_controls(struct imx334 *imx334,
377*9746b117SMartina Krasteva 				  const struct imx334_mode *mode)
378*9746b117SMartina Krasteva {
379*9746b117SMartina Krasteva 	int ret;
380*9746b117SMartina Krasteva 
381*9746b117SMartina Krasteva 	ret = __v4l2_ctrl_s_ctrl(imx334->link_freq_ctrl, mode->link_freq_idx);
382*9746b117SMartina Krasteva 	if (ret)
383*9746b117SMartina Krasteva 		return ret;
384*9746b117SMartina Krasteva 
385*9746b117SMartina Krasteva 	ret = __v4l2_ctrl_s_ctrl(imx334->hblank_ctrl, mode->hblank);
386*9746b117SMartina Krasteva 	if (ret)
387*9746b117SMartina Krasteva 		return ret;
388*9746b117SMartina Krasteva 
389*9746b117SMartina Krasteva 	return __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min,
390*9746b117SMartina Krasteva 					mode->vblank_max, 1, mode->vblank);
391*9746b117SMartina Krasteva }
392*9746b117SMartina Krasteva 
393*9746b117SMartina Krasteva /**
394*9746b117SMartina Krasteva  * imx334_update_exp_gain() - Set updated exposure and gain
395*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
396*9746b117SMartina Krasteva  * @exposure: updated exposure value
397*9746b117SMartina Krasteva  * @gain: updated analog gain value
398*9746b117SMartina Krasteva  *
399*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
400*9746b117SMartina Krasteva  */
401*9746b117SMartina Krasteva static int imx334_update_exp_gain(struct imx334 *imx334, u32 exposure, u32 gain)
402*9746b117SMartina Krasteva {
403*9746b117SMartina Krasteva 	u32 lpfr, shutter;
404*9746b117SMartina Krasteva 	int ret;
405*9746b117SMartina Krasteva 
406*9746b117SMartina Krasteva 	lpfr = imx334->vblank + imx334->cur_mode->height;
407*9746b117SMartina Krasteva 	shutter = lpfr - exposure;
408*9746b117SMartina Krasteva 
409*9746b117SMartina Krasteva 	dev_dbg(imx334->dev, "Set long exp %u analog gain %u sh0 %u lpfr %u",
410*9746b117SMartina Krasteva 		exposure, gain, shutter, lpfr);
411*9746b117SMartina Krasteva 
412*9746b117SMartina Krasteva 	ret = imx334_write_reg(imx334, IMX334_REG_HOLD, 1, 1);
413*9746b117SMartina Krasteva 	if (ret)
414*9746b117SMartina Krasteva 		return ret;
415*9746b117SMartina Krasteva 
416*9746b117SMartina Krasteva 	ret = imx334_write_reg(imx334, IMX334_REG_LPFR, 3, lpfr);
417*9746b117SMartina Krasteva 	if (ret)
418*9746b117SMartina Krasteva 		goto error_release_group_hold;
419*9746b117SMartina Krasteva 
420*9746b117SMartina Krasteva 	ret = imx334_write_reg(imx334, IMX334_REG_SHUTTER, 3, shutter);
421*9746b117SMartina Krasteva 	if (ret)
422*9746b117SMartina Krasteva 		goto error_release_group_hold;
423*9746b117SMartina Krasteva 
424*9746b117SMartina Krasteva 	ret = imx334_write_reg(imx334, IMX334_REG_AGAIN, 1, gain);
425*9746b117SMartina Krasteva 
426*9746b117SMartina Krasteva error_release_group_hold:
427*9746b117SMartina Krasteva 	imx334_write_reg(imx334, IMX334_REG_HOLD, 1, 0);
428*9746b117SMartina Krasteva 
429*9746b117SMartina Krasteva 	return ret;
430*9746b117SMartina Krasteva }
431*9746b117SMartina Krasteva 
432*9746b117SMartina Krasteva /**
433*9746b117SMartina Krasteva  * imx334_set_ctrl() - Set subdevice control
434*9746b117SMartina Krasteva  * @ctrl: pointer to v4l2_ctrl structure
435*9746b117SMartina Krasteva  *
436*9746b117SMartina Krasteva  * Supported controls:
437*9746b117SMartina Krasteva  * - V4L2_CID_VBLANK
438*9746b117SMartina Krasteva  * - cluster controls:
439*9746b117SMartina Krasteva  *   - V4L2_CID_ANALOGUE_GAIN
440*9746b117SMartina Krasteva  *   - V4L2_CID_EXPOSURE
441*9746b117SMartina Krasteva  *
442*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
443*9746b117SMartina Krasteva  */
444*9746b117SMartina Krasteva static int imx334_set_ctrl(struct v4l2_ctrl *ctrl)
445*9746b117SMartina Krasteva {
446*9746b117SMartina Krasteva 	struct imx334 *imx334 =
447*9746b117SMartina Krasteva 		container_of(ctrl->handler, struct imx334, ctrl_handler);
448*9746b117SMartina Krasteva 	u32 analog_gain;
449*9746b117SMartina Krasteva 	u32 exposure;
450*9746b117SMartina Krasteva 	int ret;
451*9746b117SMartina Krasteva 
452*9746b117SMartina Krasteva 	switch (ctrl->id) {
453*9746b117SMartina Krasteva 	case V4L2_CID_VBLANK:
454*9746b117SMartina Krasteva 		imx334->vblank = imx334->vblank_ctrl->val;
455*9746b117SMartina Krasteva 
456*9746b117SMartina Krasteva 		dev_dbg(imx334->dev, "Received vblank %u, new lpfr %u",
457*9746b117SMartina Krasteva 			imx334->vblank,
458*9746b117SMartina Krasteva 			imx334->vblank + imx334->cur_mode->height);
459*9746b117SMartina Krasteva 
460*9746b117SMartina Krasteva 		ret = __v4l2_ctrl_modify_range(imx334->exp_ctrl,
461*9746b117SMartina Krasteva 					       IMX334_EXPOSURE_MIN,
462*9746b117SMartina Krasteva 					       imx334->vblank +
463*9746b117SMartina Krasteva 					       imx334->cur_mode->height -
464*9746b117SMartina Krasteva 					       IMX334_EXPOSURE_OFFSET,
465*9746b117SMartina Krasteva 					       1, IMX334_EXPOSURE_DEFAULT);
466*9746b117SMartina Krasteva 		break;
467*9746b117SMartina Krasteva 	case V4L2_CID_EXPOSURE:
468*9746b117SMartina Krasteva 
469*9746b117SMartina Krasteva 		/* Set controls only if sensor is in power on state */
470*9746b117SMartina Krasteva 		if (!pm_runtime_get_if_in_use(imx334->dev))
471*9746b117SMartina Krasteva 			return 0;
472*9746b117SMartina Krasteva 
473*9746b117SMartina Krasteva 		exposure = ctrl->val;
474*9746b117SMartina Krasteva 		analog_gain = imx334->again_ctrl->val;
475*9746b117SMartina Krasteva 
476*9746b117SMartina Krasteva 		dev_dbg(imx334->dev, "Received exp %u analog gain %u",
477*9746b117SMartina Krasteva 			exposure, analog_gain);
478*9746b117SMartina Krasteva 
479*9746b117SMartina Krasteva 		ret = imx334_update_exp_gain(imx334, exposure, analog_gain);
480*9746b117SMartina Krasteva 
481*9746b117SMartina Krasteva 		pm_runtime_put(imx334->dev);
482*9746b117SMartina Krasteva 
483*9746b117SMartina Krasteva 		break;
484*9746b117SMartina Krasteva 	default:
485*9746b117SMartina Krasteva 		dev_err(imx334->dev, "Invalid control %d", ctrl->id);
486*9746b117SMartina Krasteva 		ret = -EINVAL;
487*9746b117SMartina Krasteva 	}
488*9746b117SMartina Krasteva 
489*9746b117SMartina Krasteva 	return ret;
490*9746b117SMartina Krasteva }
491*9746b117SMartina Krasteva 
492*9746b117SMartina Krasteva /* V4l2 subdevice control ops*/
493*9746b117SMartina Krasteva static const struct v4l2_ctrl_ops imx334_ctrl_ops = {
494*9746b117SMartina Krasteva 	.s_ctrl = imx334_set_ctrl,
495*9746b117SMartina Krasteva };
496*9746b117SMartina Krasteva 
497*9746b117SMartina Krasteva /**
498*9746b117SMartina Krasteva  * imx334_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes
499*9746b117SMartina Krasteva  * @sd: pointer to imx334 V4L2 sub-device structure
500*9746b117SMartina Krasteva  * @cfg: V4L2 sub-device pad configuration
501*9746b117SMartina Krasteva  * @code: V4L2 sub-device code enumeration need to be filled
502*9746b117SMartina Krasteva  *
503*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
504*9746b117SMartina Krasteva  */
505*9746b117SMartina Krasteva static int imx334_enum_mbus_code(struct v4l2_subdev *sd,
506*9746b117SMartina Krasteva 				 struct v4l2_subdev_pad_config *cfg,
507*9746b117SMartina Krasteva 				 struct v4l2_subdev_mbus_code_enum *code)
508*9746b117SMartina Krasteva {
509*9746b117SMartina Krasteva 	if (code->index > 0)
510*9746b117SMartina Krasteva 		return -EINVAL;
511*9746b117SMartina Krasteva 
512*9746b117SMartina Krasteva 	code->code = supported_mode.code;
513*9746b117SMartina Krasteva 
514*9746b117SMartina Krasteva 	return 0;
515*9746b117SMartina Krasteva }
516*9746b117SMartina Krasteva 
517*9746b117SMartina Krasteva /**
518*9746b117SMartina Krasteva  * imx334_enum_frame_size() - Enumerate V4L2 sub-device frame sizes
519*9746b117SMartina Krasteva  * @sd: pointer to imx334 V4L2 sub-device structure
520*9746b117SMartina Krasteva  * @cfg: V4L2 sub-device pad configuration
521*9746b117SMartina Krasteva  * @fsize: V4L2 sub-device size enumeration need to be filled
522*9746b117SMartina Krasteva  *
523*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
524*9746b117SMartina Krasteva  */
525*9746b117SMartina Krasteva static int imx334_enum_frame_size(struct v4l2_subdev *sd,
526*9746b117SMartina Krasteva 				  struct v4l2_subdev_pad_config *cfg,
527*9746b117SMartina Krasteva 				  struct v4l2_subdev_frame_size_enum *fsize)
528*9746b117SMartina Krasteva {
529*9746b117SMartina Krasteva 	if (fsize->index > 0)
530*9746b117SMartina Krasteva 		return -EINVAL;
531*9746b117SMartina Krasteva 
532*9746b117SMartina Krasteva 	if (fsize->code != supported_mode.code)
533*9746b117SMartina Krasteva 		return -EINVAL;
534*9746b117SMartina Krasteva 
535*9746b117SMartina Krasteva 	fsize->min_width = supported_mode.width;
536*9746b117SMartina Krasteva 	fsize->max_width = fsize->min_width;
537*9746b117SMartina Krasteva 	fsize->min_height = supported_mode.height;
538*9746b117SMartina Krasteva 	fsize->max_height = fsize->min_height;
539*9746b117SMartina Krasteva 
540*9746b117SMartina Krasteva 	return 0;
541*9746b117SMartina Krasteva }
542*9746b117SMartina Krasteva 
543*9746b117SMartina Krasteva /**
544*9746b117SMartina Krasteva  * imx334_fill_pad_format() - Fill subdevice pad format
545*9746b117SMartina Krasteva  *                            from selected sensor mode
546*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
547*9746b117SMartina Krasteva  * @mode: pointer to imx334_mode sensor mode
548*9746b117SMartina Krasteva  * @fmt: V4L2 sub-device format need to be filled
549*9746b117SMartina Krasteva  */
550*9746b117SMartina Krasteva static void imx334_fill_pad_format(struct imx334 *imx334,
551*9746b117SMartina Krasteva 				   const struct imx334_mode *mode,
552*9746b117SMartina Krasteva 				   struct v4l2_subdev_format *fmt)
553*9746b117SMartina Krasteva {
554*9746b117SMartina Krasteva 	fmt->format.width = mode->width;
555*9746b117SMartina Krasteva 	fmt->format.height = mode->height;
556*9746b117SMartina Krasteva 	fmt->format.code = mode->code;
557*9746b117SMartina Krasteva 	fmt->format.field = V4L2_FIELD_NONE;
558*9746b117SMartina Krasteva 	fmt->format.colorspace = V4L2_COLORSPACE_RAW;
559*9746b117SMartina Krasteva 	fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
560*9746b117SMartina Krasteva 	fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT;
561*9746b117SMartina Krasteva 	fmt->format.xfer_func = V4L2_XFER_FUNC_NONE;
562*9746b117SMartina Krasteva }
563*9746b117SMartina Krasteva 
564*9746b117SMartina Krasteva /**
565*9746b117SMartina Krasteva  * imx334_get_pad_format() - Get subdevice pad format
566*9746b117SMartina Krasteva  * @sd: pointer to imx334 V4L2 sub-device structure
567*9746b117SMartina Krasteva  * @cfg: V4L2 sub-device pad configuration
568*9746b117SMartina Krasteva  * @fmt: V4L2 sub-device format need to be set
569*9746b117SMartina Krasteva  *
570*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
571*9746b117SMartina Krasteva  */
572*9746b117SMartina Krasteva static int imx334_get_pad_format(struct v4l2_subdev *sd,
573*9746b117SMartina Krasteva 				 struct v4l2_subdev_pad_config *cfg,
574*9746b117SMartina Krasteva 				 struct v4l2_subdev_format *fmt)
575*9746b117SMartina Krasteva {
576*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
577*9746b117SMartina Krasteva 
578*9746b117SMartina Krasteva 	mutex_lock(&imx334->mutex);
579*9746b117SMartina Krasteva 
580*9746b117SMartina Krasteva 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
581*9746b117SMartina Krasteva 		struct v4l2_mbus_framefmt *framefmt;
582*9746b117SMartina Krasteva 
583*9746b117SMartina Krasteva 		framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
584*9746b117SMartina Krasteva 		fmt->format = *framefmt;
585*9746b117SMartina Krasteva 	} else {
586*9746b117SMartina Krasteva 		imx334_fill_pad_format(imx334, imx334->cur_mode, fmt);
587*9746b117SMartina Krasteva 	}
588*9746b117SMartina Krasteva 
589*9746b117SMartina Krasteva 	mutex_unlock(&imx334->mutex);
590*9746b117SMartina Krasteva 
591*9746b117SMartina Krasteva 	return 0;
592*9746b117SMartina Krasteva }
593*9746b117SMartina Krasteva 
594*9746b117SMartina Krasteva /**
595*9746b117SMartina Krasteva  * imx334_set_pad_format() - Set subdevice pad format
596*9746b117SMartina Krasteva  * @sd: pointer to imx334 V4L2 sub-device structure
597*9746b117SMartina Krasteva  * @cfg: V4L2 sub-device pad configuration
598*9746b117SMartina Krasteva  * @fmt: V4L2 sub-device format need to be set
599*9746b117SMartina Krasteva  *
600*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
601*9746b117SMartina Krasteva  */
602*9746b117SMartina Krasteva static int imx334_set_pad_format(struct v4l2_subdev *sd,
603*9746b117SMartina Krasteva 				 struct v4l2_subdev_pad_config *cfg,
604*9746b117SMartina Krasteva 				 struct v4l2_subdev_format *fmt)
605*9746b117SMartina Krasteva {
606*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
607*9746b117SMartina Krasteva 	const struct imx334_mode *mode;
608*9746b117SMartina Krasteva 	int ret = 0;
609*9746b117SMartina Krasteva 
610*9746b117SMartina Krasteva 	mutex_lock(&imx334->mutex);
611*9746b117SMartina Krasteva 
612*9746b117SMartina Krasteva 	mode = &supported_mode;
613*9746b117SMartina Krasteva 	imx334_fill_pad_format(imx334, mode, fmt);
614*9746b117SMartina Krasteva 
615*9746b117SMartina Krasteva 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
616*9746b117SMartina Krasteva 		struct v4l2_mbus_framefmt *framefmt;
617*9746b117SMartina Krasteva 
618*9746b117SMartina Krasteva 		framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
619*9746b117SMartina Krasteva 		*framefmt = fmt->format;
620*9746b117SMartina Krasteva 	} else {
621*9746b117SMartina Krasteva 		ret = imx334_update_controls(imx334, mode);
622*9746b117SMartina Krasteva 		if (!ret)
623*9746b117SMartina Krasteva 			imx334->cur_mode = mode;
624*9746b117SMartina Krasteva 	}
625*9746b117SMartina Krasteva 
626*9746b117SMartina Krasteva 	mutex_unlock(&imx334->mutex);
627*9746b117SMartina Krasteva 
628*9746b117SMartina Krasteva 	return ret;
629*9746b117SMartina Krasteva }
630*9746b117SMartina Krasteva 
631*9746b117SMartina Krasteva /**
632*9746b117SMartina Krasteva  * imx334_init_pad_cfg() - Initialize sub-device pad configuration
633*9746b117SMartina Krasteva  * @sd: pointer to imx334 V4L2 sub-device structure
634*9746b117SMartina Krasteva  * @cfg: V4L2 sub-device pad configuration
635*9746b117SMartina Krasteva  *
636*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
637*9746b117SMartina Krasteva  */
638*9746b117SMartina Krasteva static int imx334_init_pad_cfg(struct v4l2_subdev *sd,
639*9746b117SMartina Krasteva 			       struct v4l2_subdev_pad_config *cfg)
640*9746b117SMartina Krasteva {
641*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
642*9746b117SMartina Krasteva 	struct v4l2_subdev_format fmt = { 0 };
643*9746b117SMartina Krasteva 
644*9746b117SMartina Krasteva 	fmt.which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
645*9746b117SMartina Krasteva 	imx334_fill_pad_format(imx334, &supported_mode, &fmt);
646*9746b117SMartina Krasteva 
647*9746b117SMartina Krasteva 	return imx334_set_pad_format(sd, cfg, &fmt);
648*9746b117SMartina Krasteva }
649*9746b117SMartina Krasteva 
650*9746b117SMartina Krasteva /**
651*9746b117SMartina Krasteva  * imx334_start_streaming() - Start sensor stream
652*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
653*9746b117SMartina Krasteva  *
654*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
655*9746b117SMartina Krasteva  */
656*9746b117SMartina Krasteva static int imx334_start_streaming(struct imx334 *imx334)
657*9746b117SMartina Krasteva {
658*9746b117SMartina Krasteva 	const struct imx334_reg_list *reg_list;
659*9746b117SMartina Krasteva 	int ret;
660*9746b117SMartina Krasteva 
661*9746b117SMartina Krasteva 	/* Write sensor mode registers */
662*9746b117SMartina Krasteva 	reg_list = &imx334->cur_mode->reg_list;
663*9746b117SMartina Krasteva 	ret = imx334_write_regs(imx334, reg_list->regs,
664*9746b117SMartina Krasteva 				reg_list->num_of_regs);
665*9746b117SMartina Krasteva 	if (ret) {
666*9746b117SMartina Krasteva 		dev_err(imx334->dev, "fail to write initial registers");
667*9746b117SMartina Krasteva 		return ret;
668*9746b117SMartina Krasteva 	}
669*9746b117SMartina Krasteva 
670*9746b117SMartina Krasteva 	/* Setup handler will write actual exposure and gain */
671*9746b117SMartina Krasteva 	ret =  __v4l2_ctrl_handler_setup(imx334->sd.ctrl_handler);
672*9746b117SMartina Krasteva 	if (ret) {
673*9746b117SMartina Krasteva 		dev_err(imx334->dev, "fail to setup handler");
674*9746b117SMartina Krasteva 		return ret;
675*9746b117SMartina Krasteva 	}
676*9746b117SMartina Krasteva 
677*9746b117SMartina Krasteva 	/* Start streaming */
678*9746b117SMartina Krasteva 	ret = imx334_write_reg(imx334, IMX334_REG_MODE_SELECT,
679*9746b117SMartina Krasteva 			       1, IMX334_MODE_STREAMING);
680*9746b117SMartina Krasteva 	if (ret) {
681*9746b117SMartina Krasteva 		dev_err(imx334->dev, "fail to start streaming");
682*9746b117SMartina Krasteva 		return ret;
683*9746b117SMartina Krasteva 	}
684*9746b117SMartina Krasteva 
685*9746b117SMartina Krasteva 	return 0;
686*9746b117SMartina Krasteva }
687*9746b117SMartina Krasteva 
688*9746b117SMartina Krasteva /**
689*9746b117SMartina Krasteva  * imx334_stop_streaming() - Stop sensor stream
690*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
691*9746b117SMartina Krasteva  *
692*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
693*9746b117SMartina Krasteva  */
694*9746b117SMartina Krasteva static int imx334_stop_streaming(struct imx334 *imx334)
695*9746b117SMartina Krasteva {
696*9746b117SMartina Krasteva 	return imx334_write_reg(imx334, IMX334_REG_MODE_SELECT,
697*9746b117SMartina Krasteva 				1, IMX334_MODE_STANDBY);
698*9746b117SMartina Krasteva }
699*9746b117SMartina Krasteva 
700*9746b117SMartina Krasteva /**
701*9746b117SMartina Krasteva  * imx334_set_stream() - Enable sensor streaming
702*9746b117SMartina Krasteva  * @sd: pointer to imx334 subdevice
703*9746b117SMartina Krasteva  * @enable: set to enable sensor streaming
704*9746b117SMartina Krasteva  *
705*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
706*9746b117SMartina Krasteva  */
707*9746b117SMartina Krasteva static int imx334_set_stream(struct v4l2_subdev *sd, int enable)
708*9746b117SMartina Krasteva {
709*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
710*9746b117SMartina Krasteva 	int ret;
711*9746b117SMartina Krasteva 
712*9746b117SMartina Krasteva 	mutex_lock(&imx334->mutex);
713*9746b117SMartina Krasteva 
714*9746b117SMartina Krasteva 	if (imx334->streaming == enable) {
715*9746b117SMartina Krasteva 		mutex_unlock(&imx334->mutex);
716*9746b117SMartina Krasteva 		return 0;
717*9746b117SMartina Krasteva 	}
718*9746b117SMartina Krasteva 
719*9746b117SMartina Krasteva 	if (enable) {
720*9746b117SMartina Krasteva 		ret = pm_runtime_get_sync(imx334->dev);
721*9746b117SMartina Krasteva 		if (ret)
722*9746b117SMartina Krasteva 			goto error_power_off;
723*9746b117SMartina Krasteva 
724*9746b117SMartina Krasteva 		ret = imx334_start_streaming(imx334);
725*9746b117SMartina Krasteva 		if (ret)
726*9746b117SMartina Krasteva 			goto error_power_off;
727*9746b117SMartina Krasteva 	} else {
728*9746b117SMartina Krasteva 		imx334_stop_streaming(imx334);
729*9746b117SMartina Krasteva 		pm_runtime_put(imx334->dev);
730*9746b117SMartina Krasteva 	}
731*9746b117SMartina Krasteva 
732*9746b117SMartina Krasteva 	imx334->streaming = enable;
733*9746b117SMartina Krasteva 
734*9746b117SMartina Krasteva 	mutex_unlock(&imx334->mutex);
735*9746b117SMartina Krasteva 
736*9746b117SMartina Krasteva 	return 0;
737*9746b117SMartina Krasteva 
738*9746b117SMartina Krasteva error_power_off:
739*9746b117SMartina Krasteva 	pm_runtime_put(imx334->dev);
740*9746b117SMartina Krasteva 	mutex_unlock(&imx334->mutex);
741*9746b117SMartina Krasteva 
742*9746b117SMartina Krasteva 	return ret;
743*9746b117SMartina Krasteva }
744*9746b117SMartina Krasteva 
745*9746b117SMartina Krasteva /**
746*9746b117SMartina Krasteva  * imx334_detect() - Detect imx334 sensor
747*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
748*9746b117SMartina Krasteva  *
749*9746b117SMartina Krasteva  * Return: 0 if successful, -EIO if sensor id does not match
750*9746b117SMartina Krasteva  */
751*9746b117SMartina Krasteva static int imx334_detect(struct imx334 *imx334)
752*9746b117SMartina Krasteva {
753*9746b117SMartina Krasteva 	int ret;
754*9746b117SMartina Krasteva 	u32 val;
755*9746b117SMartina Krasteva 
756*9746b117SMartina Krasteva 	ret = imx334_read_reg(imx334, IMX334_REG_ID, 2, &val);
757*9746b117SMartina Krasteva 	if (ret)
758*9746b117SMartina Krasteva 		return ret;
759*9746b117SMartina Krasteva 
760*9746b117SMartina Krasteva 	if (val != IMX334_ID) {
761*9746b117SMartina Krasteva 		dev_err(imx334->dev, "chip id mismatch: %x!=%x",
762*9746b117SMartina Krasteva 			IMX334_ID, val);
763*9746b117SMartina Krasteva 		return -ENXIO;
764*9746b117SMartina Krasteva 	}
765*9746b117SMartina Krasteva 
766*9746b117SMartina Krasteva 	return 0;
767*9746b117SMartina Krasteva }
768*9746b117SMartina Krasteva 
769*9746b117SMartina Krasteva /**
770*9746b117SMartina Krasteva  * imx334_parse_hw_config() - Parse HW configuration and check if supported
771*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
772*9746b117SMartina Krasteva  *
773*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
774*9746b117SMartina Krasteva  */
775*9746b117SMartina Krasteva static int imx334_parse_hw_config(struct imx334 *imx334)
776*9746b117SMartina Krasteva {
777*9746b117SMartina Krasteva 	struct fwnode_handle *fwnode = dev_fwnode(imx334->dev);
778*9746b117SMartina Krasteva 	struct v4l2_fwnode_endpoint bus_cfg = {
779*9746b117SMartina Krasteva 		.bus_type = V4L2_MBUS_CSI2_DPHY
780*9746b117SMartina Krasteva 	};
781*9746b117SMartina Krasteva 	struct fwnode_handle *ep;
782*9746b117SMartina Krasteva 	unsigned long rate;
783*9746b117SMartina Krasteva 	int ret;
784*9746b117SMartina Krasteva 	int i;
785*9746b117SMartina Krasteva 
786*9746b117SMartina Krasteva 	if (!fwnode)
787*9746b117SMartina Krasteva 		return -ENXIO;
788*9746b117SMartina Krasteva 
789*9746b117SMartina Krasteva 	/* Request optional reset pin */
790*9746b117SMartina Krasteva 	imx334->reset_gpio = devm_gpiod_get_optional(imx334->dev, "reset",
791*9746b117SMartina Krasteva 						     GPIOD_OUT_LOW);
792*9746b117SMartina Krasteva 	if (IS_ERR(imx334->reset_gpio)) {
793*9746b117SMartina Krasteva 		dev_err(imx334->dev, "failed to get reset gpio %d", ret);
794*9746b117SMartina Krasteva 		return PTR_ERR(imx334->reset_gpio);
795*9746b117SMartina Krasteva 	}
796*9746b117SMartina Krasteva 
797*9746b117SMartina Krasteva 	/* Get sensor input clock */
798*9746b117SMartina Krasteva 	imx334->inclk = devm_clk_get(imx334->dev, NULL);
799*9746b117SMartina Krasteva 	if (IS_ERR(imx334->inclk)) {
800*9746b117SMartina Krasteva 		dev_err(imx334->dev, "could not get inclk");
801*9746b117SMartina Krasteva 		return PTR_ERR(imx334->inclk);
802*9746b117SMartina Krasteva 	}
803*9746b117SMartina Krasteva 
804*9746b117SMartina Krasteva 	rate = clk_get_rate(imx334->inclk);
805*9746b117SMartina Krasteva 	if (rate != IMX334_INCLK_RATE) {
806*9746b117SMartina Krasteva 		dev_err(imx334->dev, "inclk frequency mismatch");
807*9746b117SMartina Krasteva 		return -EINVAL;
808*9746b117SMartina Krasteva 	}
809*9746b117SMartina Krasteva 
810*9746b117SMartina Krasteva 	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
811*9746b117SMartina Krasteva 	if (!ep)
812*9746b117SMartina Krasteva 		return -ENXIO;
813*9746b117SMartina Krasteva 
814*9746b117SMartina Krasteva 	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
815*9746b117SMartina Krasteva 	fwnode_handle_put(ep);
816*9746b117SMartina Krasteva 	if (ret)
817*9746b117SMartina Krasteva 		return ret;
818*9746b117SMartina Krasteva 
819*9746b117SMartina Krasteva 	if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX334_NUM_DATA_LANES) {
820*9746b117SMartina Krasteva 		dev_err(imx334->dev,
821*9746b117SMartina Krasteva 			"number of CSI2 data lanes %d is not supported",
822*9746b117SMartina Krasteva 			bus_cfg.bus.mipi_csi2.num_data_lanes);
823*9746b117SMartina Krasteva 		ret = -EINVAL;
824*9746b117SMartina Krasteva 		goto done_endpoint_free;
825*9746b117SMartina Krasteva 	}
826*9746b117SMartina Krasteva 
827*9746b117SMartina Krasteva 	if (!bus_cfg.nr_of_link_frequencies) {
828*9746b117SMartina Krasteva 		dev_err(imx334->dev, "no link frequencies defined");
829*9746b117SMartina Krasteva 		ret = -EINVAL;
830*9746b117SMartina Krasteva 		goto done_endpoint_free;
831*9746b117SMartina Krasteva 	}
832*9746b117SMartina Krasteva 
833*9746b117SMartina Krasteva 	for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
834*9746b117SMartina Krasteva 		if (bus_cfg.link_frequencies[i] == IMX334_LINK_FREQ)
835*9746b117SMartina Krasteva 			goto done_endpoint_free;
836*9746b117SMartina Krasteva 
837*9746b117SMartina Krasteva 	ret = -EINVAL;
838*9746b117SMartina Krasteva 
839*9746b117SMartina Krasteva done_endpoint_free:
840*9746b117SMartina Krasteva 	v4l2_fwnode_endpoint_free(&bus_cfg);
841*9746b117SMartina Krasteva 
842*9746b117SMartina Krasteva 	return ret;
843*9746b117SMartina Krasteva }
844*9746b117SMartina Krasteva 
845*9746b117SMartina Krasteva /* V4l2 subdevice ops */
846*9746b117SMartina Krasteva static const struct v4l2_subdev_video_ops imx334_video_ops = {
847*9746b117SMartina Krasteva 	.s_stream = imx334_set_stream,
848*9746b117SMartina Krasteva };
849*9746b117SMartina Krasteva 
850*9746b117SMartina Krasteva static const struct v4l2_subdev_pad_ops imx334_pad_ops = {
851*9746b117SMartina Krasteva 	.init_cfg = imx334_init_pad_cfg,
852*9746b117SMartina Krasteva 	.enum_mbus_code = imx334_enum_mbus_code,
853*9746b117SMartina Krasteva 	.enum_frame_size = imx334_enum_frame_size,
854*9746b117SMartina Krasteva 	.get_fmt = imx334_get_pad_format,
855*9746b117SMartina Krasteva 	.set_fmt = imx334_set_pad_format,
856*9746b117SMartina Krasteva };
857*9746b117SMartina Krasteva 
858*9746b117SMartina Krasteva static const struct v4l2_subdev_ops imx334_subdev_ops = {
859*9746b117SMartina Krasteva 	.video = &imx334_video_ops,
860*9746b117SMartina Krasteva 	.pad = &imx334_pad_ops,
861*9746b117SMartina Krasteva };
862*9746b117SMartina Krasteva 
863*9746b117SMartina Krasteva /**
864*9746b117SMartina Krasteva  * imx334_power_on() - Sensor power on sequence
865*9746b117SMartina Krasteva  * @dev: pointer to i2c device
866*9746b117SMartina Krasteva  *
867*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
868*9746b117SMartina Krasteva  */
869*9746b117SMartina Krasteva static int imx334_power_on(struct device *dev)
870*9746b117SMartina Krasteva {
871*9746b117SMartina Krasteva 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
872*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
873*9746b117SMartina Krasteva 	int ret;
874*9746b117SMartina Krasteva 
875*9746b117SMartina Krasteva 	gpiod_set_value_cansleep(imx334->reset_gpio, 1);
876*9746b117SMartina Krasteva 
877*9746b117SMartina Krasteva 	ret = clk_prepare_enable(imx334->inclk);
878*9746b117SMartina Krasteva 	if (ret) {
879*9746b117SMartina Krasteva 		dev_err(imx334->dev, "fail to enable inclk");
880*9746b117SMartina Krasteva 		goto error_reset;
881*9746b117SMartina Krasteva 	}
882*9746b117SMartina Krasteva 
883*9746b117SMartina Krasteva 	usleep_range(18000, 20000);
884*9746b117SMartina Krasteva 
885*9746b117SMartina Krasteva 	return 0;
886*9746b117SMartina Krasteva 
887*9746b117SMartina Krasteva error_reset:
888*9746b117SMartina Krasteva 	gpiod_set_value_cansleep(imx334->reset_gpio, 0);
889*9746b117SMartina Krasteva 
890*9746b117SMartina Krasteva 	return ret;
891*9746b117SMartina Krasteva }
892*9746b117SMartina Krasteva 
893*9746b117SMartina Krasteva /**
894*9746b117SMartina Krasteva  * imx334_power_off() - Sensor power off sequence
895*9746b117SMartina Krasteva  * @dev: pointer to i2c device
896*9746b117SMartina Krasteva  *
897*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
898*9746b117SMartina Krasteva  */
899*9746b117SMartina Krasteva static int imx334_power_off(struct device *dev)
900*9746b117SMartina Krasteva {
901*9746b117SMartina Krasteva 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
902*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
903*9746b117SMartina Krasteva 
904*9746b117SMartina Krasteva 	gpiod_set_value_cansleep(imx334->reset_gpio, 0);
905*9746b117SMartina Krasteva 
906*9746b117SMartina Krasteva 	clk_disable_unprepare(imx334->inclk);
907*9746b117SMartina Krasteva 
908*9746b117SMartina Krasteva 	return 0;
909*9746b117SMartina Krasteva }
910*9746b117SMartina Krasteva 
911*9746b117SMartina Krasteva /**
912*9746b117SMartina Krasteva  * imx334_init_controls() - Initialize sensor subdevice controls
913*9746b117SMartina Krasteva  * @imx334: pointer to imx334 device
914*9746b117SMartina Krasteva  *
915*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
916*9746b117SMartina Krasteva  */
917*9746b117SMartina Krasteva static int imx334_init_controls(struct imx334 *imx334)
918*9746b117SMartina Krasteva {
919*9746b117SMartina Krasteva 	struct v4l2_ctrl_handler *ctrl_hdlr = &imx334->ctrl_handler;
920*9746b117SMartina Krasteva 	const struct imx334_mode *mode = imx334->cur_mode;
921*9746b117SMartina Krasteva 	u32 lpfr;
922*9746b117SMartina Krasteva 	int ret;
923*9746b117SMartina Krasteva 
924*9746b117SMartina Krasteva 	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6);
925*9746b117SMartina Krasteva 	if (ret)
926*9746b117SMartina Krasteva 		return ret;
927*9746b117SMartina Krasteva 
928*9746b117SMartina Krasteva 	/* Serialize controls with sensor device */
929*9746b117SMartina Krasteva 	ctrl_hdlr->lock = &imx334->mutex;
930*9746b117SMartina Krasteva 
931*9746b117SMartina Krasteva 	/* Initialize exposure and gain */
932*9746b117SMartina Krasteva 	lpfr = mode->vblank + mode->height;
933*9746b117SMartina Krasteva 	imx334->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
934*9746b117SMartina Krasteva 					     &imx334_ctrl_ops,
935*9746b117SMartina Krasteva 					     V4L2_CID_EXPOSURE,
936*9746b117SMartina Krasteva 					     IMX334_EXPOSURE_MIN,
937*9746b117SMartina Krasteva 					     lpfr - IMX334_EXPOSURE_OFFSET,
938*9746b117SMartina Krasteva 					     IMX334_EXPOSURE_STEP,
939*9746b117SMartina Krasteva 					     IMX334_EXPOSURE_DEFAULT);
940*9746b117SMartina Krasteva 
941*9746b117SMartina Krasteva 	imx334->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
942*9746b117SMartina Krasteva 					       &imx334_ctrl_ops,
943*9746b117SMartina Krasteva 					       V4L2_CID_ANALOGUE_GAIN,
944*9746b117SMartina Krasteva 					       IMX334_AGAIN_MIN,
945*9746b117SMartina Krasteva 					       IMX334_AGAIN_MAX,
946*9746b117SMartina Krasteva 					       IMX334_AGAIN_STEP,
947*9746b117SMartina Krasteva 					       IMX334_AGAIN_DEFAULT);
948*9746b117SMartina Krasteva 
949*9746b117SMartina Krasteva 	v4l2_ctrl_cluster(2, &imx334->exp_ctrl);
950*9746b117SMartina Krasteva 
951*9746b117SMartina Krasteva 	imx334->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
952*9746b117SMartina Krasteva 						&imx334_ctrl_ops,
953*9746b117SMartina Krasteva 						V4L2_CID_VBLANK,
954*9746b117SMartina Krasteva 						mode->vblank_min,
955*9746b117SMartina Krasteva 						mode->vblank_max,
956*9746b117SMartina Krasteva 						1, mode->vblank);
957*9746b117SMartina Krasteva 
958*9746b117SMartina Krasteva 	/* Read only controls */
959*9746b117SMartina Krasteva 	imx334->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
960*9746b117SMartina Krasteva 					      &imx334_ctrl_ops,
961*9746b117SMartina Krasteva 					      V4L2_CID_PIXEL_RATE,
962*9746b117SMartina Krasteva 					      mode->pclk, mode->pclk,
963*9746b117SMartina Krasteva 					      1, mode->pclk);
964*9746b117SMartina Krasteva 
965*9746b117SMartina Krasteva 	imx334->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr,
966*9746b117SMartina Krasteva 							&imx334_ctrl_ops,
967*9746b117SMartina Krasteva 							V4L2_CID_LINK_FREQ,
968*9746b117SMartina Krasteva 							ARRAY_SIZE(link_freq) -
969*9746b117SMartina Krasteva 							1,
970*9746b117SMartina Krasteva 							mode->link_freq_idx,
971*9746b117SMartina Krasteva 							link_freq);
972*9746b117SMartina Krasteva 	if (imx334->link_freq_ctrl)
973*9746b117SMartina Krasteva 		imx334->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
974*9746b117SMartina Krasteva 
975*9746b117SMartina Krasteva 	imx334->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr,
976*9746b117SMartina Krasteva 						&imx334_ctrl_ops,
977*9746b117SMartina Krasteva 						V4L2_CID_HBLANK,
978*9746b117SMartina Krasteva 						IMX334_REG_MIN,
979*9746b117SMartina Krasteva 						IMX334_REG_MAX,
980*9746b117SMartina Krasteva 						1, mode->hblank);
981*9746b117SMartina Krasteva 	if (imx334->hblank_ctrl)
982*9746b117SMartina Krasteva 		imx334->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
983*9746b117SMartina Krasteva 
984*9746b117SMartina Krasteva 	if (ctrl_hdlr->error) {
985*9746b117SMartina Krasteva 		dev_err(imx334->dev, "control init failed: %d",
986*9746b117SMartina Krasteva 			ctrl_hdlr->error);
987*9746b117SMartina Krasteva 		v4l2_ctrl_handler_free(ctrl_hdlr);
988*9746b117SMartina Krasteva 		return ctrl_hdlr->error;
989*9746b117SMartina Krasteva 	}
990*9746b117SMartina Krasteva 
991*9746b117SMartina Krasteva 	imx334->sd.ctrl_handler = ctrl_hdlr;
992*9746b117SMartina Krasteva 
993*9746b117SMartina Krasteva 	return 0;
994*9746b117SMartina Krasteva }
995*9746b117SMartina Krasteva 
996*9746b117SMartina Krasteva /**
997*9746b117SMartina Krasteva  * imx334_probe() - I2C client device binding
998*9746b117SMartina Krasteva  * @client: pointer to i2c client device
999*9746b117SMartina Krasteva  *
1000*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
1001*9746b117SMartina Krasteva  */
1002*9746b117SMartina Krasteva static int imx334_probe(struct i2c_client *client)
1003*9746b117SMartina Krasteva {
1004*9746b117SMartina Krasteva 	struct imx334 *imx334;
1005*9746b117SMartina Krasteva 	int ret;
1006*9746b117SMartina Krasteva 
1007*9746b117SMartina Krasteva 	imx334 = devm_kzalloc(&client->dev, sizeof(*imx334), GFP_KERNEL);
1008*9746b117SMartina Krasteva 	if (!imx334)
1009*9746b117SMartina Krasteva 		return -ENOMEM;
1010*9746b117SMartina Krasteva 
1011*9746b117SMartina Krasteva 	imx334->dev = &client->dev;
1012*9746b117SMartina Krasteva 
1013*9746b117SMartina Krasteva 	/* Initialize subdev */
1014*9746b117SMartina Krasteva 	v4l2_i2c_subdev_init(&imx334->sd, client, &imx334_subdev_ops);
1015*9746b117SMartina Krasteva 
1016*9746b117SMartina Krasteva 	ret = imx334_parse_hw_config(imx334);
1017*9746b117SMartina Krasteva 	if (ret) {
1018*9746b117SMartina Krasteva 		dev_err(imx334->dev, "HW configuration is not supported");
1019*9746b117SMartina Krasteva 		return ret;
1020*9746b117SMartina Krasteva 	}
1021*9746b117SMartina Krasteva 
1022*9746b117SMartina Krasteva 	mutex_init(&imx334->mutex);
1023*9746b117SMartina Krasteva 
1024*9746b117SMartina Krasteva 	ret = imx334_power_on(imx334->dev);
1025*9746b117SMartina Krasteva 	if (ret) {
1026*9746b117SMartina Krasteva 		dev_err(imx334->dev, "failed to power-on the sensor");
1027*9746b117SMartina Krasteva 		goto error_mutex_destroy;
1028*9746b117SMartina Krasteva 	}
1029*9746b117SMartina Krasteva 
1030*9746b117SMartina Krasteva 	/* Check module identity */
1031*9746b117SMartina Krasteva 	ret = imx334_detect(imx334);
1032*9746b117SMartina Krasteva 	if (ret) {
1033*9746b117SMartina Krasteva 		dev_err(imx334->dev, "failed to find sensor: %d", ret);
1034*9746b117SMartina Krasteva 		goto error_power_off;
1035*9746b117SMartina Krasteva 	}
1036*9746b117SMartina Krasteva 
1037*9746b117SMartina Krasteva 	/* Set default mode to max resolution */
1038*9746b117SMartina Krasteva 	imx334->cur_mode = &supported_mode;
1039*9746b117SMartina Krasteva 	imx334->vblank = imx334->cur_mode->vblank;
1040*9746b117SMartina Krasteva 
1041*9746b117SMartina Krasteva 	ret = imx334_init_controls(imx334);
1042*9746b117SMartina Krasteva 	if (ret) {
1043*9746b117SMartina Krasteva 		dev_err(imx334->dev, "failed to init controls: %d", ret);
1044*9746b117SMartina Krasteva 		goto error_power_off;
1045*9746b117SMartina Krasteva 	}
1046*9746b117SMartina Krasteva 
1047*9746b117SMartina Krasteva 	/* Initialize subdev */
1048*9746b117SMartina Krasteva 	imx334->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1049*9746b117SMartina Krasteva 	imx334->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1050*9746b117SMartina Krasteva 
1051*9746b117SMartina Krasteva 	/* Initialize source pad */
1052*9746b117SMartina Krasteva 	imx334->pad.flags = MEDIA_PAD_FL_SOURCE;
1053*9746b117SMartina Krasteva 	ret = media_entity_pads_init(&imx334->sd.entity, 1, &imx334->pad);
1054*9746b117SMartina Krasteva 	if (ret) {
1055*9746b117SMartina Krasteva 		dev_err(imx334->dev, "failed to init entity pads: %d", ret);
1056*9746b117SMartina Krasteva 		goto error_handler_free;
1057*9746b117SMartina Krasteva 	}
1058*9746b117SMartina Krasteva 
1059*9746b117SMartina Krasteva 	ret = v4l2_async_register_subdev_sensor_common(&imx334->sd);
1060*9746b117SMartina Krasteva 	if (ret < 0) {
1061*9746b117SMartina Krasteva 		dev_err(imx334->dev,
1062*9746b117SMartina Krasteva 			"failed to register async subdev: %d", ret);
1063*9746b117SMartina Krasteva 		goto error_media_entity;
1064*9746b117SMartina Krasteva 	}
1065*9746b117SMartina Krasteva 
1066*9746b117SMartina Krasteva 	pm_runtime_set_active(imx334->dev);
1067*9746b117SMartina Krasteva 	pm_runtime_enable(imx334->dev);
1068*9746b117SMartina Krasteva 	pm_runtime_idle(imx334->dev);
1069*9746b117SMartina Krasteva 
1070*9746b117SMartina Krasteva 	return 0;
1071*9746b117SMartina Krasteva 
1072*9746b117SMartina Krasteva error_media_entity:
1073*9746b117SMartina Krasteva 	media_entity_cleanup(&imx334->sd.entity);
1074*9746b117SMartina Krasteva error_handler_free:
1075*9746b117SMartina Krasteva 	v4l2_ctrl_handler_free(imx334->sd.ctrl_handler);
1076*9746b117SMartina Krasteva error_power_off:
1077*9746b117SMartina Krasteva 	imx334_power_off(imx334->dev);
1078*9746b117SMartina Krasteva error_mutex_destroy:
1079*9746b117SMartina Krasteva 	mutex_destroy(&imx334->mutex);
1080*9746b117SMartina Krasteva 
1081*9746b117SMartina Krasteva 	return ret;
1082*9746b117SMartina Krasteva }
1083*9746b117SMartina Krasteva 
1084*9746b117SMartina Krasteva /**
1085*9746b117SMartina Krasteva  * imx334_remove() - I2C client device unbinding
1086*9746b117SMartina Krasteva  * @client: pointer to I2C client device
1087*9746b117SMartina Krasteva  *
1088*9746b117SMartina Krasteva  * Return: 0 if successful, error code otherwise.
1089*9746b117SMartina Krasteva  */
1090*9746b117SMartina Krasteva static int imx334_remove(struct i2c_client *client)
1091*9746b117SMartina Krasteva {
1092*9746b117SMartina Krasteva 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1093*9746b117SMartina Krasteva 	struct imx334 *imx334 = to_imx334(sd);
1094*9746b117SMartina Krasteva 
1095*9746b117SMartina Krasteva 	v4l2_async_unregister_subdev(sd);
1096*9746b117SMartina Krasteva 	media_entity_cleanup(&sd->entity);
1097*9746b117SMartina Krasteva 	v4l2_ctrl_handler_free(sd->ctrl_handler);
1098*9746b117SMartina Krasteva 
1099*9746b117SMartina Krasteva 	pm_runtime_disable(&client->dev);
1100*9746b117SMartina Krasteva 	pm_runtime_suspended(&client->dev);
1101*9746b117SMartina Krasteva 
1102*9746b117SMartina Krasteva 	mutex_destroy(&imx334->mutex);
1103*9746b117SMartina Krasteva 
1104*9746b117SMartina Krasteva 	return 0;
1105*9746b117SMartina Krasteva }
1106*9746b117SMartina Krasteva 
1107*9746b117SMartina Krasteva static const struct dev_pm_ops imx334_pm_ops = {
1108*9746b117SMartina Krasteva 	SET_RUNTIME_PM_OPS(imx334_power_off, imx334_power_on, NULL)
1109*9746b117SMartina Krasteva };
1110*9746b117SMartina Krasteva 
1111*9746b117SMartina Krasteva static const struct of_device_id imx334_of_match[] = {
1112*9746b117SMartina Krasteva 	{ .compatible = "sony,imx334" },
1113*9746b117SMartina Krasteva 	{ }
1114*9746b117SMartina Krasteva };
1115*9746b117SMartina Krasteva 
1116*9746b117SMartina Krasteva MODULE_DEVICE_TABLE(of, imx334_of_match);
1117*9746b117SMartina Krasteva 
1118*9746b117SMartina Krasteva static struct i2c_driver imx334_driver = {
1119*9746b117SMartina Krasteva 	.probe_new = imx334_probe,
1120*9746b117SMartina Krasteva 	.remove = imx334_remove,
1121*9746b117SMartina Krasteva 	.driver = {
1122*9746b117SMartina Krasteva 		.name = "imx334",
1123*9746b117SMartina Krasteva 		.pm = &imx334_pm_ops,
1124*9746b117SMartina Krasteva 		.of_match_table = imx334_of_match,
1125*9746b117SMartina Krasteva 	},
1126*9746b117SMartina Krasteva };
1127*9746b117SMartina Krasteva 
1128*9746b117SMartina Krasteva module_i2c_driver(imx334_driver);
1129*9746b117SMartina Krasteva 
1130*9746b117SMartina Krasteva MODULE_DESCRIPTION("Sony imx334 sensor driver");
1131*9746b117SMartina Krasteva MODULE_LICENSE("GPL");
1132