xref: /openbmc/linux/drivers/media/i2c/ov2680.c (revision 3ee47cad3e6955147882f1a24a9465704d8eddd2)
1*3ee47cadSRui Miguel Silva // SPDX-License-Identifier: GPL-2.0
2*3ee47cadSRui Miguel Silva /*
3*3ee47cadSRui Miguel Silva  * Omnivision OV2680 CMOS Image Sensor driver
4*3ee47cadSRui Miguel Silva  *
5*3ee47cadSRui Miguel Silva  * Copyright (C) 2018 Linaro Ltd
6*3ee47cadSRui Miguel Silva  *
7*3ee47cadSRui Miguel Silva  * Based on OV5640 Sensor Driver
8*3ee47cadSRui Miguel Silva  * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
9*3ee47cadSRui Miguel Silva  * Copyright (C) 2014-2017 Mentor Graphics Inc.
10*3ee47cadSRui Miguel Silva  *
11*3ee47cadSRui Miguel Silva  */
12*3ee47cadSRui Miguel Silva 
13*3ee47cadSRui Miguel Silva #include <asm/unaligned.h>
14*3ee47cadSRui Miguel Silva #include <linux/clk.h>
15*3ee47cadSRui Miguel Silva #include <linux/delay.h>
16*3ee47cadSRui Miguel Silva #include <linux/err.h>
17*3ee47cadSRui Miguel Silva #include <linux/i2c.h>
18*3ee47cadSRui Miguel Silva #include <linux/init.h>
19*3ee47cadSRui Miguel Silva #include <linux/module.h>
20*3ee47cadSRui Miguel Silva #include <linux/of_device.h>
21*3ee47cadSRui Miguel Silva #include <linux/gpio/consumer.h>
22*3ee47cadSRui Miguel Silva #include <linux/regulator/consumer.h>
23*3ee47cadSRui Miguel Silva 
24*3ee47cadSRui Miguel Silva #include <media/v4l2-common.h>
25*3ee47cadSRui Miguel Silva #include <media/v4l2-ctrls.h>
26*3ee47cadSRui Miguel Silva #include <media/v4l2-subdev.h>
27*3ee47cadSRui Miguel Silva 
28*3ee47cadSRui Miguel Silva #define OV2680_XVCLK_VALUE	24000000
29*3ee47cadSRui Miguel Silva 
30*3ee47cadSRui Miguel Silva #define OV2680_CHIP_ID		0x2680
31*3ee47cadSRui Miguel Silva 
32*3ee47cadSRui Miguel Silva #define OV2680_REG_STREAM_CTRL		0x0100
33*3ee47cadSRui Miguel Silva #define OV2680_REG_SOFT_RESET		0x0103
34*3ee47cadSRui Miguel Silva 
35*3ee47cadSRui Miguel Silva #define OV2680_REG_CHIP_ID_HIGH		0x300a
36*3ee47cadSRui Miguel Silva #define OV2680_REG_CHIP_ID_LOW		0x300b
37*3ee47cadSRui Miguel Silva 
38*3ee47cadSRui Miguel Silva #define OV2680_REG_R_MANUAL		0x3503
39*3ee47cadSRui Miguel Silva #define OV2680_REG_GAIN_PK		0x350a
40*3ee47cadSRui Miguel Silva #define OV2680_REG_EXPOSURE_PK_HIGH	0x3500
41*3ee47cadSRui Miguel Silva #define OV2680_REG_TIMING_HTS		0x380c
42*3ee47cadSRui Miguel Silva #define OV2680_REG_TIMING_VTS		0x380e
43*3ee47cadSRui Miguel Silva #define OV2680_REG_FORMAT1		0x3820
44*3ee47cadSRui Miguel Silva #define OV2680_REG_FORMAT2		0x3821
45*3ee47cadSRui Miguel Silva 
46*3ee47cadSRui Miguel Silva #define OV2680_REG_ISP_CTRL00		0x5080
47*3ee47cadSRui Miguel Silva 
48*3ee47cadSRui Miguel Silva #define OV2680_FRAME_RATE		30
49*3ee47cadSRui Miguel Silva 
50*3ee47cadSRui Miguel Silva #define OV2680_REG_VALUE_8BIT		1
51*3ee47cadSRui Miguel Silva #define OV2680_REG_VALUE_16BIT		2
52*3ee47cadSRui Miguel Silva #define OV2680_REG_VALUE_24BIT		3
53*3ee47cadSRui Miguel Silva 
54*3ee47cadSRui Miguel Silva #define OV2680_WIDTH_MAX		1600
55*3ee47cadSRui Miguel Silva #define OV2680_HEIGHT_MAX		1200
56*3ee47cadSRui Miguel Silva 
57*3ee47cadSRui Miguel Silva enum ov2680_mode_id {
58*3ee47cadSRui Miguel Silva 	OV2680_MODE_QUXGA_800_600,
59*3ee47cadSRui Miguel Silva 	OV2680_MODE_720P_1280_720,
60*3ee47cadSRui Miguel Silva 	OV2680_MODE_UXGA_1600_1200,
61*3ee47cadSRui Miguel Silva 	OV2680_MODE_MAX,
62*3ee47cadSRui Miguel Silva };
63*3ee47cadSRui Miguel Silva 
64*3ee47cadSRui Miguel Silva struct reg_value {
65*3ee47cadSRui Miguel Silva 	u16 reg_addr;
66*3ee47cadSRui Miguel Silva 	u8 val;
67*3ee47cadSRui Miguel Silva };
68*3ee47cadSRui Miguel Silva 
69*3ee47cadSRui Miguel Silva static const char * const ov2680_supply_name[] = {
70*3ee47cadSRui Miguel Silva 	"DOVDD",
71*3ee47cadSRui Miguel Silva 	"DVDD",
72*3ee47cadSRui Miguel Silva 	"AVDD",
73*3ee47cadSRui Miguel Silva };
74*3ee47cadSRui Miguel Silva 
75*3ee47cadSRui Miguel Silva #define OV2680_NUM_SUPPLIES ARRAY_SIZE(ov2680_supply_name)
76*3ee47cadSRui Miguel Silva 
77*3ee47cadSRui Miguel Silva struct ov2680_mode_info {
78*3ee47cadSRui Miguel Silva 	const char *name;
79*3ee47cadSRui Miguel Silva 	enum ov2680_mode_id id;
80*3ee47cadSRui Miguel Silva 	u32 width;
81*3ee47cadSRui Miguel Silva 	u32 height;
82*3ee47cadSRui Miguel Silva 	const struct reg_value *reg_data;
83*3ee47cadSRui Miguel Silva 	u32 reg_data_size;
84*3ee47cadSRui Miguel Silva };
85*3ee47cadSRui Miguel Silva 
86*3ee47cadSRui Miguel Silva struct ov2680_ctrls {
87*3ee47cadSRui Miguel Silva 	struct v4l2_ctrl_handler handler;
88*3ee47cadSRui Miguel Silva 	struct {
89*3ee47cadSRui Miguel Silva 		struct v4l2_ctrl *auto_exp;
90*3ee47cadSRui Miguel Silva 		struct v4l2_ctrl *exposure;
91*3ee47cadSRui Miguel Silva 	};
92*3ee47cadSRui Miguel Silva 	struct {
93*3ee47cadSRui Miguel Silva 		struct v4l2_ctrl *auto_gain;
94*3ee47cadSRui Miguel Silva 		struct v4l2_ctrl *gain;
95*3ee47cadSRui Miguel Silva 	};
96*3ee47cadSRui Miguel Silva 
97*3ee47cadSRui Miguel Silva 	struct v4l2_ctrl *hflip;
98*3ee47cadSRui Miguel Silva 	struct v4l2_ctrl *vflip;
99*3ee47cadSRui Miguel Silva 	struct v4l2_ctrl *test_pattern;
100*3ee47cadSRui Miguel Silva };
101*3ee47cadSRui Miguel Silva 
102*3ee47cadSRui Miguel Silva struct ov2680_dev {
103*3ee47cadSRui Miguel Silva 	struct i2c_client		*i2c_client;
104*3ee47cadSRui Miguel Silva 	struct v4l2_subdev		sd;
105*3ee47cadSRui Miguel Silva 
106*3ee47cadSRui Miguel Silva 	struct media_pad		pad;
107*3ee47cadSRui Miguel Silva 	struct clk			*xvclk;
108*3ee47cadSRui Miguel Silva 	u32				xvclk_freq;
109*3ee47cadSRui Miguel Silva 	struct regulator_bulk_data	supplies[OV2680_NUM_SUPPLIES];
110*3ee47cadSRui Miguel Silva 
111*3ee47cadSRui Miguel Silva 	struct gpio_desc		*reset_gpio;
112*3ee47cadSRui Miguel Silva 	struct mutex			lock; /* protect members */
113*3ee47cadSRui Miguel Silva 
114*3ee47cadSRui Miguel Silva 	bool				mode_pending_changes;
115*3ee47cadSRui Miguel Silva 	bool				is_enabled;
116*3ee47cadSRui Miguel Silva 	bool				is_streaming;
117*3ee47cadSRui Miguel Silva 
118*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls		ctrls;
119*3ee47cadSRui Miguel Silva 	struct v4l2_mbus_framefmt	fmt;
120*3ee47cadSRui Miguel Silva 	struct v4l2_fract		frame_interval;
121*3ee47cadSRui Miguel Silva 
122*3ee47cadSRui Miguel Silva 	const struct ov2680_mode_info	*current_mode;
123*3ee47cadSRui Miguel Silva };
124*3ee47cadSRui Miguel Silva 
125*3ee47cadSRui Miguel Silva static const char * const test_pattern_menu[] = {
126*3ee47cadSRui Miguel Silva 	"Disabled",
127*3ee47cadSRui Miguel Silva 	"Color Bars",
128*3ee47cadSRui Miguel Silva 	"Random Data",
129*3ee47cadSRui Miguel Silva 	"Square",
130*3ee47cadSRui Miguel Silva 	"Black Image",
131*3ee47cadSRui Miguel Silva };
132*3ee47cadSRui Miguel Silva 
133*3ee47cadSRui Miguel Silva static const int ov2680_hv_flip_bayer_order[] = {
134*3ee47cadSRui Miguel Silva 	MEDIA_BUS_FMT_SBGGR10_1X10,
135*3ee47cadSRui Miguel Silva 	MEDIA_BUS_FMT_SGRBG10_1X10,
136*3ee47cadSRui Miguel Silva 	MEDIA_BUS_FMT_SGBRG10_1X10,
137*3ee47cadSRui Miguel Silva 	MEDIA_BUS_FMT_SRGGB10_1X10,
138*3ee47cadSRui Miguel Silva };
139*3ee47cadSRui Miguel Silva 
140*3ee47cadSRui Miguel Silva static const struct reg_value ov2680_setting_30fps_QUXGA_800_600[] = {
141*3ee47cadSRui Miguel Silva 	{0x3086, 0x01}, {0x370a, 0x23}, {0x3808, 0x03}, {0x3809, 0x20},
142*3ee47cadSRui Miguel Silva 	{0x380a, 0x02}, {0x380b, 0x58}, {0x380c, 0x06}, {0x380d, 0xac},
143*3ee47cadSRui Miguel Silva 	{0x380e, 0x02}, {0x380f, 0x84}, {0x3811, 0x04}, {0x3813, 0x04},
144*3ee47cadSRui Miguel Silva 	{0x3814, 0x31}, {0x3815, 0x31}, {0x3820, 0xc0}, {0x4008, 0x00},
145*3ee47cadSRui Miguel Silva 	{0x4009, 0x03}, {0x4837, 0x1e}, {0x3501, 0x4e}, {0x3502, 0xe0},
146*3ee47cadSRui Miguel Silva };
147*3ee47cadSRui Miguel Silva 
148*3ee47cadSRui Miguel Silva static const struct reg_value ov2680_setting_30fps_720P_1280_720[] = {
149*3ee47cadSRui Miguel Silva 	{0x3086, 0x00}, {0x3808, 0x05}, {0x3809, 0x00}, {0x380a, 0x02},
150*3ee47cadSRui Miguel Silva 	{0x380b, 0xd0}, {0x380c, 0x06}, {0x380d, 0xa8}, {0x380e, 0x05},
151*3ee47cadSRui Miguel Silva 	{0x380f, 0x0e}, {0x3811, 0x08}, {0x3813, 0x06}, {0x3814, 0x11},
152*3ee47cadSRui Miguel Silva 	{0x3815, 0x11}, {0x3820, 0xc0}, {0x4008, 0x00},
153*3ee47cadSRui Miguel Silva };
154*3ee47cadSRui Miguel Silva 
155*3ee47cadSRui Miguel Silva static const struct reg_value ov2680_setting_30fps_UXGA_1600_1200[] = {
156*3ee47cadSRui Miguel Silva 	{0x3086, 0x00}, {0x3501, 0x4e}, {0x3502, 0xe0}, {0x3808, 0x06},
157*3ee47cadSRui Miguel Silva 	{0x3809, 0x40}, {0x380a, 0x04}, {0x380b, 0xb0}, {0x380c, 0x06},
158*3ee47cadSRui Miguel Silva 	{0x380d, 0xa8}, {0x380e, 0x05}, {0x380f, 0x0e}, {0x3811, 0x00},
159*3ee47cadSRui Miguel Silva 	{0x3813, 0x00}, {0x3814, 0x11}, {0x3815, 0x11}, {0x3820, 0xc0},
160*3ee47cadSRui Miguel Silva 	{0x4008, 0x00}, {0x4837, 0x18}
161*3ee47cadSRui Miguel Silva };
162*3ee47cadSRui Miguel Silva 
163*3ee47cadSRui Miguel Silva static const struct ov2680_mode_info ov2680_mode_init_data = {
164*3ee47cadSRui Miguel Silva 	"mode_quxga_800_600", OV2680_MODE_QUXGA_800_600, 800, 600,
165*3ee47cadSRui Miguel Silva 	ov2680_setting_30fps_QUXGA_800_600,
166*3ee47cadSRui Miguel Silva 	ARRAY_SIZE(ov2680_setting_30fps_QUXGA_800_600),
167*3ee47cadSRui Miguel Silva };
168*3ee47cadSRui Miguel Silva 
169*3ee47cadSRui Miguel Silva static const struct ov2680_mode_info ov2680_mode_data[OV2680_MODE_MAX] = {
170*3ee47cadSRui Miguel Silva 	{"mode_quxga_800_600", OV2680_MODE_QUXGA_800_600,
171*3ee47cadSRui Miguel Silva 	 800, 600, ov2680_setting_30fps_QUXGA_800_600,
172*3ee47cadSRui Miguel Silva 	 ARRAY_SIZE(ov2680_setting_30fps_QUXGA_800_600)},
173*3ee47cadSRui Miguel Silva 	{"mode_720p_1280_720", OV2680_MODE_720P_1280_720,
174*3ee47cadSRui Miguel Silva 	 1280, 720, ov2680_setting_30fps_720P_1280_720,
175*3ee47cadSRui Miguel Silva 	 ARRAY_SIZE(ov2680_setting_30fps_720P_1280_720)},
176*3ee47cadSRui Miguel Silva 	{"mode_uxga_1600_1200", OV2680_MODE_UXGA_1600_1200,
177*3ee47cadSRui Miguel Silva 	 1600, 1200, ov2680_setting_30fps_UXGA_1600_1200,
178*3ee47cadSRui Miguel Silva 	 ARRAY_SIZE(ov2680_setting_30fps_UXGA_1600_1200)},
179*3ee47cadSRui Miguel Silva };
180*3ee47cadSRui Miguel Silva 
181*3ee47cadSRui Miguel Silva static struct ov2680_dev *to_ov2680_dev(struct v4l2_subdev *sd)
182*3ee47cadSRui Miguel Silva {
183*3ee47cadSRui Miguel Silva 	return container_of(sd, struct ov2680_dev, sd);
184*3ee47cadSRui Miguel Silva }
185*3ee47cadSRui Miguel Silva 
186*3ee47cadSRui Miguel Silva static struct device *ov2680_to_dev(struct ov2680_dev *sensor)
187*3ee47cadSRui Miguel Silva {
188*3ee47cadSRui Miguel Silva 	return &sensor->i2c_client->dev;
189*3ee47cadSRui Miguel Silva }
190*3ee47cadSRui Miguel Silva 
191*3ee47cadSRui Miguel Silva static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
192*3ee47cadSRui Miguel Silva {
193*3ee47cadSRui Miguel Silva 	return &container_of(ctrl->handler, struct ov2680_dev,
194*3ee47cadSRui Miguel Silva 			     ctrls.handler)->sd;
195*3ee47cadSRui Miguel Silva }
196*3ee47cadSRui Miguel Silva 
197*3ee47cadSRui Miguel Silva static int __ov2680_write_reg(struct ov2680_dev *sensor, u16 reg,
198*3ee47cadSRui Miguel Silva 			      unsigned int len, u32 val)
199*3ee47cadSRui Miguel Silva {
200*3ee47cadSRui Miguel Silva 	struct i2c_client *client = sensor->i2c_client;
201*3ee47cadSRui Miguel Silva 	u8 buf[6];
202*3ee47cadSRui Miguel Silva 	int ret;
203*3ee47cadSRui Miguel Silva 
204*3ee47cadSRui Miguel Silva 	if (len > 4)
205*3ee47cadSRui Miguel Silva 		return -EINVAL;
206*3ee47cadSRui Miguel Silva 
207*3ee47cadSRui Miguel Silva 	put_unaligned_be16(reg, buf);
208*3ee47cadSRui Miguel Silva 	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
209*3ee47cadSRui Miguel Silva 	ret = i2c_master_send(client, buf, len + 2);
210*3ee47cadSRui Miguel Silva 	if (ret != len + 2) {
211*3ee47cadSRui Miguel Silva 		dev_err(&client->dev, "write error: reg=0x%4x: %d\n", reg, ret);
212*3ee47cadSRui Miguel Silva 		return -EIO;
213*3ee47cadSRui Miguel Silva 	}
214*3ee47cadSRui Miguel Silva 
215*3ee47cadSRui Miguel Silva 	return 0;
216*3ee47cadSRui Miguel Silva }
217*3ee47cadSRui Miguel Silva 
218*3ee47cadSRui Miguel Silva #define ov2680_write_reg(s, r, v) \
219*3ee47cadSRui Miguel Silva 	__ov2680_write_reg(s, r, OV2680_REG_VALUE_8BIT, v)
220*3ee47cadSRui Miguel Silva 
221*3ee47cadSRui Miguel Silva #define ov2680_write_reg16(s, r, v) \
222*3ee47cadSRui Miguel Silva 	__ov2680_write_reg(s, r, OV2680_REG_VALUE_16BIT, v)
223*3ee47cadSRui Miguel Silva 
224*3ee47cadSRui Miguel Silva #define ov2680_write_reg24(s, r, v) \
225*3ee47cadSRui Miguel Silva 	__ov2680_write_reg(s, r, OV2680_REG_VALUE_24BIT, v)
226*3ee47cadSRui Miguel Silva 
227*3ee47cadSRui Miguel Silva static int __ov2680_read_reg(struct ov2680_dev *sensor, u16 reg,
228*3ee47cadSRui Miguel Silva 			     unsigned int len, u32 *val)
229*3ee47cadSRui Miguel Silva {
230*3ee47cadSRui Miguel Silva 	struct i2c_client *client = sensor->i2c_client;
231*3ee47cadSRui Miguel Silva 	struct i2c_msg msgs[2];
232*3ee47cadSRui Miguel Silva 	u8 addr_buf[2] = { reg >> 8, reg & 0xff };
233*3ee47cadSRui Miguel Silva 	u8 data_buf[4] = { 0, };
234*3ee47cadSRui Miguel Silva 	int ret;
235*3ee47cadSRui Miguel Silva 
236*3ee47cadSRui Miguel Silva 	if (len > 4)
237*3ee47cadSRui Miguel Silva 		return -EINVAL;
238*3ee47cadSRui Miguel Silva 
239*3ee47cadSRui Miguel Silva 	msgs[0].addr = client->addr;
240*3ee47cadSRui Miguel Silva 	msgs[0].flags = 0;
241*3ee47cadSRui Miguel Silva 	msgs[0].len = ARRAY_SIZE(addr_buf);
242*3ee47cadSRui Miguel Silva 	msgs[0].buf = addr_buf;
243*3ee47cadSRui Miguel Silva 
244*3ee47cadSRui Miguel Silva 	msgs[1].addr = client->addr;
245*3ee47cadSRui Miguel Silva 	msgs[1].flags = I2C_M_RD;
246*3ee47cadSRui Miguel Silva 	msgs[1].len = len;
247*3ee47cadSRui Miguel Silva 	msgs[1].buf = &data_buf[4 - len];
248*3ee47cadSRui Miguel Silva 
249*3ee47cadSRui Miguel Silva 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
250*3ee47cadSRui Miguel Silva 	if (ret != ARRAY_SIZE(msgs)) {
251*3ee47cadSRui Miguel Silva 		dev_err(&client->dev, "read error: reg=0x%4x: %d\n", reg, ret);
252*3ee47cadSRui Miguel Silva 		return -EIO;
253*3ee47cadSRui Miguel Silva 	}
254*3ee47cadSRui Miguel Silva 
255*3ee47cadSRui Miguel Silva 	*val = get_unaligned_be32(data_buf);
256*3ee47cadSRui Miguel Silva 
257*3ee47cadSRui Miguel Silva 	return 0;
258*3ee47cadSRui Miguel Silva }
259*3ee47cadSRui Miguel Silva 
260*3ee47cadSRui Miguel Silva #define ov2680_read_reg(s, r, v) \
261*3ee47cadSRui Miguel Silva 	__ov2680_read_reg(s, r, OV2680_REG_VALUE_8BIT, v)
262*3ee47cadSRui Miguel Silva 
263*3ee47cadSRui Miguel Silva #define ov2680_read_reg16(s, r, v) \
264*3ee47cadSRui Miguel Silva 	__ov2680_read_reg(s, r, OV2680_REG_VALUE_16BIT, v)
265*3ee47cadSRui Miguel Silva 
266*3ee47cadSRui Miguel Silva #define ov2680_read_reg24(s, r, v) \
267*3ee47cadSRui Miguel Silva 	__ov2680_read_reg(s, r, OV2680_REG_VALUE_24BIT, v)
268*3ee47cadSRui Miguel Silva 
269*3ee47cadSRui Miguel Silva static int ov2680_mod_reg(struct ov2680_dev *sensor, u16 reg, u8 mask, u8 val)
270*3ee47cadSRui Miguel Silva {
271*3ee47cadSRui Miguel Silva 	u32 readval;
272*3ee47cadSRui Miguel Silva 	int ret;
273*3ee47cadSRui Miguel Silva 
274*3ee47cadSRui Miguel Silva 	ret = ov2680_read_reg(sensor, reg, &readval);
275*3ee47cadSRui Miguel Silva 	if (ret < 0)
276*3ee47cadSRui Miguel Silva 		return ret;
277*3ee47cadSRui Miguel Silva 
278*3ee47cadSRui Miguel Silva 	readval &= ~mask;
279*3ee47cadSRui Miguel Silva 	val &= mask;
280*3ee47cadSRui Miguel Silva 	val |= readval;
281*3ee47cadSRui Miguel Silva 
282*3ee47cadSRui Miguel Silva 	return ov2680_write_reg(sensor, reg, val);
283*3ee47cadSRui Miguel Silva }
284*3ee47cadSRui Miguel Silva 
285*3ee47cadSRui Miguel Silva static int ov2680_load_regs(struct ov2680_dev *sensor,
286*3ee47cadSRui Miguel Silva 			    const struct ov2680_mode_info *mode)
287*3ee47cadSRui Miguel Silva {
288*3ee47cadSRui Miguel Silva 	const struct reg_value *regs = mode->reg_data;
289*3ee47cadSRui Miguel Silva 	unsigned int i;
290*3ee47cadSRui Miguel Silva 	int ret = 0;
291*3ee47cadSRui Miguel Silva 	u16 reg_addr;
292*3ee47cadSRui Miguel Silva 	u8 val;
293*3ee47cadSRui Miguel Silva 
294*3ee47cadSRui Miguel Silva 	for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
295*3ee47cadSRui Miguel Silva 		reg_addr = regs->reg_addr;
296*3ee47cadSRui Miguel Silva 		val = regs->val;
297*3ee47cadSRui Miguel Silva 
298*3ee47cadSRui Miguel Silva 		ret = ov2680_write_reg(sensor, reg_addr, val);
299*3ee47cadSRui Miguel Silva 		if (ret)
300*3ee47cadSRui Miguel Silva 			break;
301*3ee47cadSRui Miguel Silva 	}
302*3ee47cadSRui Miguel Silva 
303*3ee47cadSRui Miguel Silva 	return ret;
304*3ee47cadSRui Miguel Silva }
305*3ee47cadSRui Miguel Silva 
306*3ee47cadSRui Miguel Silva static void ov2680_power_up(struct ov2680_dev *sensor)
307*3ee47cadSRui Miguel Silva {
308*3ee47cadSRui Miguel Silva 	if (!sensor->reset_gpio)
309*3ee47cadSRui Miguel Silva 		return;
310*3ee47cadSRui Miguel Silva 
311*3ee47cadSRui Miguel Silva 	gpiod_set_value(sensor->reset_gpio, 0);
312*3ee47cadSRui Miguel Silva 	usleep_range(5000, 10000);
313*3ee47cadSRui Miguel Silva }
314*3ee47cadSRui Miguel Silva 
315*3ee47cadSRui Miguel Silva static void ov2680_power_down(struct ov2680_dev *sensor)
316*3ee47cadSRui Miguel Silva {
317*3ee47cadSRui Miguel Silva 	if (!sensor->reset_gpio)
318*3ee47cadSRui Miguel Silva 		return;
319*3ee47cadSRui Miguel Silva 
320*3ee47cadSRui Miguel Silva 	gpiod_set_value(sensor->reset_gpio, 1);
321*3ee47cadSRui Miguel Silva 	usleep_range(5000, 10000);
322*3ee47cadSRui Miguel Silva }
323*3ee47cadSRui Miguel Silva 
324*3ee47cadSRui Miguel Silva static int ov2680_bayer_order(struct ov2680_dev *sensor)
325*3ee47cadSRui Miguel Silva {
326*3ee47cadSRui Miguel Silva 	u32 format1;
327*3ee47cadSRui Miguel Silva 	u32 format2;
328*3ee47cadSRui Miguel Silva 	u32 hv_flip;
329*3ee47cadSRui Miguel Silva 	int ret;
330*3ee47cadSRui Miguel Silva 
331*3ee47cadSRui Miguel Silva 	ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT1, &format1);
332*3ee47cadSRui Miguel Silva 	if (ret < 0)
333*3ee47cadSRui Miguel Silva 		return ret;
334*3ee47cadSRui Miguel Silva 
335*3ee47cadSRui Miguel Silva 	ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT2, &format2);
336*3ee47cadSRui Miguel Silva 	if (ret < 0)
337*3ee47cadSRui Miguel Silva 		return ret;
338*3ee47cadSRui Miguel Silva 
339*3ee47cadSRui Miguel Silva 	hv_flip = (format2 & BIT(2)  << 1) | (format1 & BIT(2));
340*3ee47cadSRui Miguel Silva 
341*3ee47cadSRui Miguel Silva 	sensor->fmt.code = ov2680_hv_flip_bayer_order[hv_flip];
342*3ee47cadSRui Miguel Silva 
343*3ee47cadSRui Miguel Silva 	return 0;
344*3ee47cadSRui Miguel Silva }
345*3ee47cadSRui Miguel Silva 
346*3ee47cadSRui Miguel Silva static int ov2680_vflip_enable(struct ov2680_dev *sensor)
347*3ee47cadSRui Miguel Silva {
348*3ee47cadSRui Miguel Silva 	int ret;
349*3ee47cadSRui Miguel Silva 
350*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(2));
351*3ee47cadSRui Miguel Silva 	if (ret < 0)
352*3ee47cadSRui Miguel Silva 		return ret;
353*3ee47cadSRui Miguel Silva 
354*3ee47cadSRui Miguel Silva 	return ov2680_bayer_order(sensor);
355*3ee47cadSRui Miguel Silva }
356*3ee47cadSRui Miguel Silva 
357*3ee47cadSRui Miguel Silva static int ov2680_vflip_disable(struct ov2680_dev *sensor)
358*3ee47cadSRui Miguel Silva {
359*3ee47cadSRui Miguel Silva 	int ret;
360*3ee47cadSRui Miguel Silva 
361*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(0));
362*3ee47cadSRui Miguel Silva 	if (ret < 0)
363*3ee47cadSRui Miguel Silva 		return ret;
364*3ee47cadSRui Miguel Silva 
365*3ee47cadSRui Miguel Silva 	return ov2680_bayer_order(sensor);
366*3ee47cadSRui Miguel Silva }
367*3ee47cadSRui Miguel Silva 
368*3ee47cadSRui Miguel Silva static int ov2680_hflip_enable(struct ov2680_dev *sensor)
369*3ee47cadSRui Miguel Silva {
370*3ee47cadSRui Miguel Silva 	int ret;
371*3ee47cadSRui Miguel Silva 
372*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(2));
373*3ee47cadSRui Miguel Silva 	if (ret < 0)
374*3ee47cadSRui Miguel Silva 		return ret;
375*3ee47cadSRui Miguel Silva 
376*3ee47cadSRui Miguel Silva 	return ov2680_bayer_order(sensor);
377*3ee47cadSRui Miguel Silva }
378*3ee47cadSRui Miguel Silva 
379*3ee47cadSRui Miguel Silva static int ov2680_hflip_disable(struct ov2680_dev *sensor)
380*3ee47cadSRui Miguel Silva {
381*3ee47cadSRui Miguel Silva 	int ret;
382*3ee47cadSRui Miguel Silva 
383*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(0));
384*3ee47cadSRui Miguel Silva 	if (ret < 0)
385*3ee47cadSRui Miguel Silva 		return ret;
386*3ee47cadSRui Miguel Silva 
387*3ee47cadSRui Miguel Silva 	return ov2680_bayer_order(sensor);
388*3ee47cadSRui Miguel Silva }
389*3ee47cadSRui Miguel Silva 
390*3ee47cadSRui Miguel Silva static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value)
391*3ee47cadSRui Miguel Silva {
392*3ee47cadSRui Miguel Silva 	int ret;
393*3ee47cadSRui Miguel Silva 
394*3ee47cadSRui Miguel Silva 	if (!value)
395*3ee47cadSRui Miguel Silva 		return ov2680_mod_reg(sensor, OV2680_REG_ISP_CTRL00, BIT(7), 0);
396*3ee47cadSRui Miguel Silva 
397*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_ISP_CTRL00, 0x03, value - 1);
398*3ee47cadSRui Miguel Silva 	if (ret < 0)
399*3ee47cadSRui Miguel Silva 		return ret;
400*3ee47cadSRui Miguel Silva 
401*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_ISP_CTRL00, BIT(7), BIT(7));
402*3ee47cadSRui Miguel Silva 	if (ret < 0)
403*3ee47cadSRui Miguel Silva 		return ret;
404*3ee47cadSRui Miguel Silva 
405*3ee47cadSRui Miguel Silva 	return 0;
406*3ee47cadSRui Miguel Silva }
407*3ee47cadSRui Miguel Silva 
408*3ee47cadSRui Miguel Silva static int ov2680_gain_set(struct ov2680_dev *sensor, bool auto_gain)
409*3ee47cadSRui Miguel Silva {
410*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls *ctrls = &sensor->ctrls;
411*3ee47cadSRui Miguel Silva 	u32 gain;
412*3ee47cadSRui Miguel Silva 	int ret;
413*3ee47cadSRui Miguel Silva 
414*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(1),
415*3ee47cadSRui Miguel Silva 			     auto_gain ? 0 : BIT(1));
416*3ee47cadSRui Miguel Silva 	if (ret < 0)
417*3ee47cadSRui Miguel Silva 		return ret;
418*3ee47cadSRui Miguel Silva 
419*3ee47cadSRui Miguel Silva 	if (auto_gain || !ctrls->gain->is_new)
420*3ee47cadSRui Miguel Silva 		return 0;
421*3ee47cadSRui Miguel Silva 
422*3ee47cadSRui Miguel Silva 	gain = ctrls->gain->val;
423*3ee47cadSRui Miguel Silva 
424*3ee47cadSRui Miguel Silva 	ret = ov2680_write_reg16(sensor, OV2680_REG_GAIN_PK, gain);
425*3ee47cadSRui Miguel Silva 
426*3ee47cadSRui Miguel Silva 	return 0;
427*3ee47cadSRui Miguel Silva }
428*3ee47cadSRui Miguel Silva 
429*3ee47cadSRui Miguel Silva static int ov2680_gain_get(struct ov2680_dev *sensor)
430*3ee47cadSRui Miguel Silva {
431*3ee47cadSRui Miguel Silva 	u32 gain;
432*3ee47cadSRui Miguel Silva 	int ret;
433*3ee47cadSRui Miguel Silva 
434*3ee47cadSRui Miguel Silva 	ret = ov2680_read_reg16(sensor, OV2680_REG_GAIN_PK, &gain);
435*3ee47cadSRui Miguel Silva 	if (ret)
436*3ee47cadSRui Miguel Silva 		return ret;
437*3ee47cadSRui Miguel Silva 
438*3ee47cadSRui Miguel Silva 	return gain;
439*3ee47cadSRui Miguel Silva }
440*3ee47cadSRui Miguel Silva 
441*3ee47cadSRui Miguel Silva static int ov2680_exposure_set(struct ov2680_dev *sensor, bool auto_exp)
442*3ee47cadSRui Miguel Silva {
443*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls *ctrls = &sensor->ctrls;
444*3ee47cadSRui Miguel Silva 	u32 exp;
445*3ee47cadSRui Miguel Silva 	int ret;
446*3ee47cadSRui Miguel Silva 
447*3ee47cadSRui Miguel Silva 	ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(0),
448*3ee47cadSRui Miguel Silva 			     auto_exp ? 0 : BIT(0));
449*3ee47cadSRui Miguel Silva 	if (ret < 0)
450*3ee47cadSRui Miguel Silva 		return ret;
451*3ee47cadSRui Miguel Silva 
452*3ee47cadSRui Miguel Silva 	if (auto_exp || !ctrls->exposure->is_new)
453*3ee47cadSRui Miguel Silva 		return 0;
454*3ee47cadSRui Miguel Silva 
455*3ee47cadSRui Miguel Silva 	exp = (u32)ctrls->exposure->val;
456*3ee47cadSRui Miguel Silva 	exp <<= 4;
457*3ee47cadSRui Miguel Silva 
458*3ee47cadSRui Miguel Silva 	return ov2680_write_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, exp);
459*3ee47cadSRui Miguel Silva }
460*3ee47cadSRui Miguel Silva 
461*3ee47cadSRui Miguel Silva static int ov2680_exposure_get(struct ov2680_dev *sensor)
462*3ee47cadSRui Miguel Silva {
463*3ee47cadSRui Miguel Silva 	int ret;
464*3ee47cadSRui Miguel Silva 	u32 exp;
465*3ee47cadSRui Miguel Silva 
466*3ee47cadSRui Miguel Silva 	ret = ov2680_read_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, &exp);
467*3ee47cadSRui Miguel Silva 	if (ret)
468*3ee47cadSRui Miguel Silva 		return ret;
469*3ee47cadSRui Miguel Silva 
470*3ee47cadSRui Miguel Silva 	return exp >> 4;
471*3ee47cadSRui Miguel Silva }
472*3ee47cadSRui Miguel Silva 
473*3ee47cadSRui Miguel Silva static int ov2680_stream_enable(struct ov2680_dev *sensor)
474*3ee47cadSRui Miguel Silva {
475*3ee47cadSRui Miguel Silva 	return ov2680_write_reg(sensor, OV2680_REG_STREAM_CTRL, 1);
476*3ee47cadSRui Miguel Silva }
477*3ee47cadSRui Miguel Silva 
478*3ee47cadSRui Miguel Silva static int ov2680_stream_disable(struct ov2680_dev *sensor)
479*3ee47cadSRui Miguel Silva {
480*3ee47cadSRui Miguel Silva 	return ov2680_write_reg(sensor, OV2680_REG_STREAM_CTRL, 0);
481*3ee47cadSRui Miguel Silva }
482*3ee47cadSRui Miguel Silva 
483*3ee47cadSRui Miguel Silva static int ov2680_mode_set(struct ov2680_dev *sensor)
484*3ee47cadSRui Miguel Silva {
485*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls *ctrls = &sensor->ctrls;
486*3ee47cadSRui Miguel Silva 	int ret;
487*3ee47cadSRui Miguel Silva 
488*3ee47cadSRui Miguel Silva 	ret = ov2680_gain_set(sensor, false);
489*3ee47cadSRui Miguel Silva 	if (ret < 0)
490*3ee47cadSRui Miguel Silva 		return ret;
491*3ee47cadSRui Miguel Silva 
492*3ee47cadSRui Miguel Silva 	ret = ov2680_exposure_set(sensor, false);
493*3ee47cadSRui Miguel Silva 	if (ret < 0)
494*3ee47cadSRui Miguel Silva 		return ret;
495*3ee47cadSRui Miguel Silva 
496*3ee47cadSRui Miguel Silva 	ret = ov2680_load_regs(sensor, sensor->current_mode);
497*3ee47cadSRui Miguel Silva 	if (ret < 0)
498*3ee47cadSRui Miguel Silva 		return ret;
499*3ee47cadSRui Miguel Silva 
500*3ee47cadSRui Miguel Silva 	if (ctrls->auto_gain->val) {
501*3ee47cadSRui Miguel Silva 		ret = ov2680_gain_set(sensor, true);
502*3ee47cadSRui Miguel Silva 		if (ret < 0)
503*3ee47cadSRui Miguel Silva 			return ret;
504*3ee47cadSRui Miguel Silva 	}
505*3ee47cadSRui Miguel Silva 
506*3ee47cadSRui Miguel Silva 	if (ctrls->auto_exp->val == V4L2_EXPOSURE_AUTO) {
507*3ee47cadSRui Miguel Silva 		ret = ov2680_exposure_set(sensor, true);
508*3ee47cadSRui Miguel Silva 		if (ret < 0)
509*3ee47cadSRui Miguel Silva 			return ret;
510*3ee47cadSRui Miguel Silva 	}
511*3ee47cadSRui Miguel Silva 
512*3ee47cadSRui Miguel Silva 	sensor->mode_pending_changes = false;
513*3ee47cadSRui Miguel Silva 
514*3ee47cadSRui Miguel Silva 	return 0;
515*3ee47cadSRui Miguel Silva }
516*3ee47cadSRui Miguel Silva 
517*3ee47cadSRui Miguel Silva static int ov2680_mode_restore(struct ov2680_dev *sensor)
518*3ee47cadSRui Miguel Silva {
519*3ee47cadSRui Miguel Silva 	int ret;
520*3ee47cadSRui Miguel Silva 
521*3ee47cadSRui Miguel Silva 	ret = ov2680_load_regs(sensor, &ov2680_mode_init_data);
522*3ee47cadSRui Miguel Silva 	if (ret < 0)
523*3ee47cadSRui Miguel Silva 		return ret;
524*3ee47cadSRui Miguel Silva 
525*3ee47cadSRui Miguel Silva 	return ov2680_mode_set(sensor);
526*3ee47cadSRui Miguel Silva }
527*3ee47cadSRui Miguel Silva 
528*3ee47cadSRui Miguel Silva static int ov2680_power_off(struct ov2680_dev *sensor)
529*3ee47cadSRui Miguel Silva {
530*3ee47cadSRui Miguel Silva 	if (!sensor->is_enabled)
531*3ee47cadSRui Miguel Silva 		return 0;
532*3ee47cadSRui Miguel Silva 
533*3ee47cadSRui Miguel Silva 	clk_disable_unprepare(sensor->xvclk);
534*3ee47cadSRui Miguel Silva 	ov2680_power_down(sensor);
535*3ee47cadSRui Miguel Silva 	regulator_bulk_disable(OV2680_NUM_SUPPLIES, sensor->supplies);
536*3ee47cadSRui Miguel Silva 	sensor->is_enabled = false;
537*3ee47cadSRui Miguel Silva 
538*3ee47cadSRui Miguel Silva 	return 0;
539*3ee47cadSRui Miguel Silva }
540*3ee47cadSRui Miguel Silva 
541*3ee47cadSRui Miguel Silva static int ov2680_power_on(struct ov2680_dev *sensor)
542*3ee47cadSRui Miguel Silva {
543*3ee47cadSRui Miguel Silva 	struct device *dev = ov2680_to_dev(sensor);
544*3ee47cadSRui Miguel Silva 	int ret;
545*3ee47cadSRui Miguel Silva 
546*3ee47cadSRui Miguel Silva 	if (sensor->is_enabled)
547*3ee47cadSRui Miguel Silva 		return 0;
548*3ee47cadSRui Miguel Silva 
549*3ee47cadSRui Miguel Silva 	ret = regulator_bulk_enable(OV2680_NUM_SUPPLIES, sensor->supplies);
550*3ee47cadSRui Miguel Silva 	if (ret < 0) {
551*3ee47cadSRui Miguel Silva 		dev_err(dev, "failed to enable regulators: %d\n", ret);
552*3ee47cadSRui Miguel Silva 		return ret;
553*3ee47cadSRui Miguel Silva 	}
554*3ee47cadSRui Miguel Silva 
555*3ee47cadSRui Miguel Silva 	if (!sensor->reset_gpio) {
556*3ee47cadSRui Miguel Silva 		ret = ov2680_write_reg(sensor, OV2680_REG_SOFT_RESET, 0x01);
557*3ee47cadSRui Miguel Silva 		if (ret != 0) {
558*3ee47cadSRui Miguel Silva 			dev_err(dev, "sensor soft reset failed\n");
559*3ee47cadSRui Miguel Silva 			return ret;
560*3ee47cadSRui Miguel Silva 		}
561*3ee47cadSRui Miguel Silva 		usleep_range(1000, 2000);
562*3ee47cadSRui Miguel Silva 	} else {
563*3ee47cadSRui Miguel Silva 		ov2680_power_down(sensor);
564*3ee47cadSRui Miguel Silva 		ov2680_power_up(sensor);
565*3ee47cadSRui Miguel Silva 	}
566*3ee47cadSRui Miguel Silva 
567*3ee47cadSRui Miguel Silva 	ret = clk_prepare_enable(sensor->xvclk);
568*3ee47cadSRui Miguel Silva 	if (ret < 0)
569*3ee47cadSRui Miguel Silva 		return ret;
570*3ee47cadSRui Miguel Silva 
571*3ee47cadSRui Miguel Silva 	ret = ov2680_mode_restore(sensor);
572*3ee47cadSRui Miguel Silva 	if (ret < 0)
573*3ee47cadSRui Miguel Silva 		goto disable;
574*3ee47cadSRui Miguel Silva 
575*3ee47cadSRui Miguel Silva 	sensor->is_enabled = true;
576*3ee47cadSRui Miguel Silva 
577*3ee47cadSRui Miguel Silva 	/* Set clock lane into LP-11 state */
578*3ee47cadSRui Miguel Silva 	ov2680_stream_enable(sensor);
579*3ee47cadSRui Miguel Silva 	usleep_range(1000, 2000);
580*3ee47cadSRui Miguel Silva 	ov2680_stream_disable(sensor);
581*3ee47cadSRui Miguel Silva 
582*3ee47cadSRui Miguel Silva 	return 0;
583*3ee47cadSRui Miguel Silva 
584*3ee47cadSRui Miguel Silva disable:
585*3ee47cadSRui Miguel Silva 	dev_err(dev, "failed to enable sensor: %d\n", ret);
586*3ee47cadSRui Miguel Silva 	ov2680_power_off(sensor);
587*3ee47cadSRui Miguel Silva 
588*3ee47cadSRui Miguel Silva 	return ret;
589*3ee47cadSRui Miguel Silva }
590*3ee47cadSRui Miguel Silva 
591*3ee47cadSRui Miguel Silva static int ov2680_s_power(struct v4l2_subdev *sd, int on)
592*3ee47cadSRui Miguel Silva {
593*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
594*3ee47cadSRui Miguel Silva 	int ret = 0;
595*3ee47cadSRui Miguel Silva 
596*3ee47cadSRui Miguel Silva 	mutex_lock(&sensor->lock);
597*3ee47cadSRui Miguel Silva 
598*3ee47cadSRui Miguel Silva 	if (on)
599*3ee47cadSRui Miguel Silva 		ret = ov2680_power_on(sensor);
600*3ee47cadSRui Miguel Silva 	else
601*3ee47cadSRui Miguel Silva 		ret = ov2680_power_off(sensor);
602*3ee47cadSRui Miguel Silva 
603*3ee47cadSRui Miguel Silva 	mutex_unlock(&sensor->lock);
604*3ee47cadSRui Miguel Silva 
605*3ee47cadSRui Miguel Silva 	if (on && ret == 0) {
606*3ee47cadSRui Miguel Silva 		ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
607*3ee47cadSRui Miguel Silva 		if (ret < 0)
608*3ee47cadSRui Miguel Silva 			return ret;
609*3ee47cadSRui Miguel Silva 	}
610*3ee47cadSRui Miguel Silva 
611*3ee47cadSRui Miguel Silva 	return ret;
612*3ee47cadSRui Miguel Silva }
613*3ee47cadSRui Miguel Silva 
614*3ee47cadSRui Miguel Silva static int ov2680_s_g_frame_interval(struct v4l2_subdev *sd,
615*3ee47cadSRui Miguel Silva 				     struct v4l2_subdev_frame_interval *fi)
616*3ee47cadSRui Miguel Silva {
617*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
618*3ee47cadSRui Miguel Silva 
619*3ee47cadSRui Miguel Silva 	mutex_lock(&sensor->lock);
620*3ee47cadSRui Miguel Silva 	fi->interval = sensor->frame_interval;
621*3ee47cadSRui Miguel Silva 	mutex_unlock(&sensor->lock);
622*3ee47cadSRui Miguel Silva 
623*3ee47cadSRui Miguel Silva 	return 0;
624*3ee47cadSRui Miguel Silva }
625*3ee47cadSRui Miguel Silva 
626*3ee47cadSRui Miguel Silva static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
627*3ee47cadSRui Miguel Silva {
628*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
629*3ee47cadSRui Miguel Silva 	int ret = 0;
630*3ee47cadSRui Miguel Silva 
631*3ee47cadSRui Miguel Silva 	mutex_lock(&sensor->lock);
632*3ee47cadSRui Miguel Silva 
633*3ee47cadSRui Miguel Silva 	if (sensor->is_streaming == !!enable)
634*3ee47cadSRui Miguel Silva 		goto unlock;
635*3ee47cadSRui Miguel Silva 
636*3ee47cadSRui Miguel Silva 	if (enable && sensor->mode_pending_changes) {
637*3ee47cadSRui Miguel Silva 		ret = ov2680_mode_set(sensor);
638*3ee47cadSRui Miguel Silva 		if (ret < 0)
639*3ee47cadSRui Miguel Silva 			goto unlock;
640*3ee47cadSRui Miguel Silva 	}
641*3ee47cadSRui Miguel Silva 
642*3ee47cadSRui Miguel Silva 	if (enable)
643*3ee47cadSRui Miguel Silva 		ret = ov2680_stream_enable(sensor);
644*3ee47cadSRui Miguel Silva 	else
645*3ee47cadSRui Miguel Silva 		ret = ov2680_stream_disable(sensor);
646*3ee47cadSRui Miguel Silva 
647*3ee47cadSRui Miguel Silva 	sensor->is_streaming = !!enable;
648*3ee47cadSRui Miguel Silva 
649*3ee47cadSRui Miguel Silva unlock:
650*3ee47cadSRui Miguel Silva 	mutex_unlock(&sensor->lock);
651*3ee47cadSRui Miguel Silva 
652*3ee47cadSRui Miguel Silva 	return ret;
653*3ee47cadSRui Miguel Silva }
654*3ee47cadSRui Miguel Silva 
655*3ee47cadSRui Miguel Silva static int ov2680_enum_mbus_code(struct v4l2_subdev *sd,
656*3ee47cadSRui Miguel Silva 				 struct v4l2_subdev_pad_config *cfg,
657*3ee47cadSRui Miguel Silva 				 struct v4l2_subdev_mbus_code_enum *code)
658*3ee47cadSRui Miguel Silva {
659*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
660*3ee47cadSRui Miguel Silva 
661*3ee47cadSRui Miguel Silva 	if (code->pad != 0 || code->index != 0)
662*3ee47cadSRui Miguel Silva 		return -EINVAL;
663*3ee47cadSRui Miguel Silva 
664*3ee47cadSRui Miguel Silva 	code->code = sensor->fmt.code;
665*3ee47cadSRui Miguel Silva 
666*3ee47cadSRui Miguel Silva 	return 0;
667*3ee47cadSRui Miguel Silva }
668*3ee47cadSRui Miguel Silva 
669*3ee47cadSRui Miguel Silva static int ov2680_get_fmt(struct v4l2_subdev *sd,
670*3ee47cadSRui Miguel Silva 			  struct v4l2_subdev_pad_config *cfg,
671*3ee47cadSRui Miguel Silva 			  struct v4l2_subdev_format *format)
672*3ee47cadSRui Miguel Silva {
673*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
674*3ee47cadSRui Miguel Silva 	struct v4l2_mbus_framefmt *fmt = NULL;
675*3ee47cadSRui Miguel Silva 	int ret = 0;
676*3ee47cadSRui Miguel Silva 
677*3ee47cadSRui Miguel Silva 	if (format->pad != 0)
678*3ee47cadSRui Miguel Silva 		return -EINVAL;
679*3ee47cadSRui Miguel Silva 
680*3ee47cadSRui Miguel Silva 	mutex_lock(&sensor->lock);
681*3ee47cadSRui Miguel Silva 
682*3ee47cadSRui Miguel Silva 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
683*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
684*3ee47cadSRui Miguel Silva 		fmt = v4l2_subdev_get_try_format(&sensor->sd, cfg, format->pad);
685*3ee47cadSRui Miguel Silva #else
686*3ee47cadSRui Miguel Silva 		ret = -ENOTTY;
687*3ee47cadSRui Miguel Silva #endif
688*3ee47cadSRui Miguel Silva 	} else {
689*3ee47cadSRui Miguel Silva 		fmt = &sensor->fmt;
690*3ee47cadSRui Miguel Silva 	}
691*3ee47cadSRui Miguel Silva 
692*3ee47cadSRui Miguel Silva 	if (fmt)
693*3ee47cadSRui Miguel Silva 		format->format = *fmt;
694*3ee47cadSRui Miguel Silva 
695*3ee47cadSRui Miguel Silva 	mutex_unlock(&sensor->lock);
696*3ee47cadSRui Miguel Silva 
697*3ee47cadSRui Miguel Silva 	return ret;
698*3ee47cadSRui Miguel Silva }
699*3ee47cadSRui Miguel Silva 
700*3ee47cadSRui Miguel Silva static int ov2680_set_fmt(struct v4l2_subdev *sd,
701*3ee47cadSRui Miguel Silva 			  struct v4l2_subdev_pad_config *cfg,
702*3ee47cadSRui Miguel Silva 			  struct v4l2_subdev_format *format)
703*3ee47cadSRui Miguel Silva {
704*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
705*3ee47cadSRui Miguel Silva 	struct v4l2_mbus_framefmt *fmt = &format->format;
706*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
707*3ee47cadSRui Miguel Silva 	struct v4l2_mbus_framefmt *try_fmt;
708*3ee47cadSRui Miguel Silva #endif
709*3ee47cadSRui Miguel Silva 	const struct ov2680_mode_info *mode;
710*3ee47cadSRui Miguel Silva 	int ret = 0;
711*3ee47cadSRui Miguel Silva 
712*3ee47cadSRui Miguel Silva 	if (format->pad != 0)
713*3ee47cadSRui Miguel Silva 		return -EINVAL;
714*3ee47cadSRui Miguel Silva 
715*3ee47cadSRui Miguel Silva 	mutex_lock(&sensor->lock);
716*3ee47cadSRui Miguel Silva 
717*3ee47cadSRui Miguel Silva 	if (sensor->is_streaming) {
718*3ee47cadSRui Miguel Silva 		ret = -EBUSY;
719*3ee47cadSRui Miguel Silva 		goto unlock;
720*3ee47cadSRui Miguel Silva 	}
721*3ee47cadSRui Miguel Silva 
722*3ee47cadSRui Miguel Silva 	mode = v4l2_find_nearest_size(ov2680_mode_data,
723*3ee47cadSRui Miguel Silva 				      ARRAY_SIZE(ov2680_mode_data), width,
724*3ee47cadSRui Miguel Silva 				      height, fmt->width, fmt->height);
725*3ee47cadSRui Miguel Silva 	if (!mode) {
726*3ee47cadSRui Miguel Silva 		ret = -EINVAL;
727*3ee47cadSRui Miguel Silva 		goto unlock;
728*3ee47cadSRui Miguel Silva 	}
729*3ee47cadSRui Miguel Silva 
730*3ee47cadSRui Miguel Silva 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
731*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
732*3ee47cadSRui Miguel Silva 		try_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
733*3ee47cadSRui Miguel Silva 		format->format = *try_fmt;
734*3ee47cadSRui Miguel Silva #else
735*3ee47cadSRui Miguel Silva 		ret = -ENOTTY;
736*3ee47cadSRui Miguel Silva #endif
737*3ee47cadSRui Miguel Silva 
738*3ee47cadSRui Miguel Silva 		goto unlock;
739*3ee47cadSRui Miguel Silva 	}
740*3ee47cadSRui Miguel Silva 
741*3ee47cadSRui Miguel Silva 	fmt->width = mode->width;
742*3ee47cadSRui Miguel Silva 	fmt->height = mode->height;
743*3ee47cadSRui Miguel Silva 	fmt->code = sensor->fmt.code;
744*3ee47cadSRui Miguel Silva 	fmt->colorspace = sensor->fmt.colorspace;
745*3ee47cadSRui Miguel Silva 
746*3ee47cadSRui Miguel Silva 	sensor->current_mode = mode;
747*3ee47cadSRui Miguel Silva 	sensor->fmt = format->format;
748*3ee47cadSRui Miguel Silva 	sensor->mode_pending_changes = true;
749*3ee47cadSRui Miguel Silva 
750*3ee47cadSRui Miguel Silva unlock:
751*3ee47cadSRui Miguel Silva 	mutex_unlock(&sensor->lock);
752*3ee47cadSRui Miguel Silva 
753*3ee47cadSRui Miguel Silva 	return ret;
754*3ee47cadSRui Miguel Silva }
755*3ee47cadSRui Miguel Silva 
756*3ee47cadSRui Miguel Silva static int ov2680_init_cfg(struct v4l2_subdev *sd,
757*3ee47cadSRui Miguel Silva 			   struct v4l2_subdev_pad_config *cfg)
758*3ee47cadSRui Miguel Silva {
759*3ee47cadSRui Miguel Silva 	struct v4l2_subdev_format fmt = {
760*3ee47cadSRui Miguel Silva 		.which = cfg ? V4L2_SUBDEV_FORMAT_TRY
761*3ee47cadSRui Miguel Silva 				: V4L2_SUBDEV_FORMAT_ACTIVE,
762*3ee47cadSRui Miguel Silva 		.format = {
763*3ee47cadSRui Miguel Silva 			.width = 800,
764*3ee47cadSRui Miguel Silva 			.height = 600,
765*3ee47cadSRui Miguel Silva 		}
766*3ee47cadSRui Miguel Silva 	};
767*3ee47cadSRui Miguel Silva 
768*3ee47cadSRui Miguel Silva 	return ov2680_set_fmt(sd, cfg, &fmt);
769*3ee47cadSRui Miguel Silva }
770*3ee47cadSRui Miguel Silva 
771*3ee47cadSRui Miguel Silva static int ov2680_enum_frame_size(struct v4l2_subdev *sd,
772*3ee47cadSRui Miguel Silva 				  struct v4l2_subdev_pad_config *cfg,
773*3ee47cadSRui Miguel Silva 				  struct v4l2_subdev_frame_size_enum *fse)
774*3ee47cadSRui Miguel Silva {
775*3ee47cadSRui Miguel Silva 	int index = fse->index;
776*3ee47cadSRui Miguel Silva 
777*3ee47cadSRui Miguel Silva 	if (index >= OV2680_MODE_MAX || index < 0)
778*3ee47cadSRui Miguel Silva 		return -EINVAL;
779*3ee47cadSRui Miguel Silva 
780*3ee47cadSRui Miguel Silva 	fse->min_width = ov2680_mode_data[index].width;
781*3ee47cadSRui Miguel Silva 	fse->min_height = ov2680_mode_data[index].height;
782*3ee47cadSRui Miguel Silva 	fse->max_width = ov2680_mode_data[index].width;
783*3ee47cadSRui Miguel Silva 	fse->max_height = ov2680_mode_data[index].height;
784*3ee47cadSRui Miguel Silva 
785*3ee47cadSRui Miguel Silva 	return 0;
786*3ee47cadSRui Miguel Silva }
787*3ee47cadSRui Miguel Silva 
788*3ee47cadSRui Miguel Silva static int ov2680_enum_frame_interval(struct v4l2_subdev *sd,
789*3ee47cadSRui Miguel Silva 			      struct v4l2_subdev_pad_config *cfg,
790*3ee47cadSRui Miguel Silva 			      struct v4l2_subdev_frame_interval_enum *fie)
791*3ee47cadSRui Miguel Silva {
792*3ee47cadSRui Miguel Silva 	struct v4l2_fract tpf;
793*3ee47cadSRui Miguel Silva 
794*3ee47cadSRui Miguel Silva 	if (fie->index >= OV2680_MODE_MAX || fie->width > OV2680_WIDTH_MAX ||
795*3ee47cadSRui Miguel Silva 	    fie->height > OV2680_HEIGHT_MAX ||
796*3ee47cadSRui Miguel Silva 	    fie->which > V4L2_SUBDEV_FORMAT_ACTIVE)
797*3ee47cadSRui Miguel Silva 		return -EINVAL;
798*3ee47cadSRui Miguel Silva 
799*3ee47cadSRui Miguel Silva 	tpf.denominator = OV2680_FRAME_RATE;
800*3ee47cadSRui Miguel Silva 	tpf.numerator = 1;
801*3ee47cadSRui Miguel Silva 
802*3ee47cadSRui Miguel Silva 	fie->interval = tpf;
803*3ee47cadSRui Miguel Silva 
804*3ee47cadSRui Miguel Silva 	return 0;
805*3ee47cadSRui Miguel Silva }
806*3ee47cadSRui Miguel Silva 
807*3ee47cadSRui Miguel Silva static int ov2680_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
808*3ee47cadSRui Miguel Silva {
809*3ee47cadSRui Miguel Silva 	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
810*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
811*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls *ctrls = &sensor->ctrls;
812*3ee47cadSRui Miguel Silva 	int val;
813*3ee47cadSRui Miguel Silva 
814*3ee47cadSRui Miguel Silva 	if (!sensor->is_enabled)
815*3ee47cadSRui Miguel Silva 		return 0;
816*3ee47cadSRui Miguel Silva 
817*3ee47cadSRui Miguel Silva 	switch (ctrl->id) {
818*3ee47cadSRui Miguel Silva 	case V4L2_CID_GAIN:
819*3ee47cadSRui Miguel Silva 		val = ov2680_gain_get(sensor);
820*3ee47cadSRui Miguel Silva 		if (val < 0)
821*3ee47cadSRui Miguel Silva 			return val;
822*3ee47cadSRui Miguel Silva 		ctrls->gain->val = val;
823*3ee47cadSRui Miguel Silva 		break;
824*3ee47cadSRui Miguel Silva 	case V4L2_CID_EXPOSURE:
825*3ee47cadSRui Miguel Silva 		val = ov2680_exposure_get(sensor);
826*3ee47cadSRui Miguel Silva 		if (val < 0)
827*3ee47cadSRui Miguel Silva 			return val;
828*3ee47cadSRui Miguel Silva 		ctrls->exposure->val = val;
829*3ee47cadSRui Miguel Silva 		break;
830*3ee47cadSRui Miguel Silva 	}
831*3ee47cadSRui Miguel Silva 
832*3ee47cadSRui Miguel Silva 	return 0;
833*3ee47cadSRui Miguel Silva }
834*3ee47cadSRui Miguel Silva 
835*3ee47cadSRui Miguel Silva static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
836*3ee47cadSRui Miguel Silva {
837*3ee47cadSRui Miguel Silva 	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
838*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
839*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls *ctrls = &sensor->ctrls;
840*3ee47cadSRui Miguel Silva 
841*3ee47cadSRui Miguel Silva 	if (!sensor->is_enabled)
842*3ee47cadSRui Miguel Silva 		return 0;
843*3ee47cadSRui Miguel Silva 
844*3ee47cadSRui Miguel Silva 	switch (ctrl->id) {
845*3ee47cadSRui Miguel Silva 	case V4L2_CID_AUTOGAIN:
846*3ee47cadSRui Miguel Silva 		return ov2680_gain_set(sensor, !!ctrl->val);
847*3ee47cadSRui Miguel Silva 	case V4L2_CID_GAIN:
848*3ee47cadSRui Miguel Silva 		return ov2680_gain_set(sensor, !!ctrls->auto_gain->val);
849*3ee47cadSRui Miguel Silva 	case V4L2_CID_EXPOSURE_AUTO:
850*3ee47cadSRui Miguel Silva 		return ov2680_exposure_set(sensor, !!ctrl->val);
851*3ee47cadSRui Miguel Silva 	case V4L2_CID_EXPOSURE:
852*3ee47cadSRui Miguel Silva 		return ov2680_exposure_set(sensor, !!ctrls->auto_exp->val);
853*3ee47cadSRui Miguel Silva 	case V4L2_CID_VFLIP:
854*3ee47cadSRui Miguel Silva 		if (sensor->is_streaming)
855*3ee47cadSRui Miguel Silva 			return -EBUSY;
856*3ee47cadSRui Miguel Silva 		if (ctrl->val)
857*3ee47cadSRui Miguel Silva 			return ov2680_vflip_enable(sensor);
858*3ee47cadSRui Miguel Silva 		else
859*3ee47cadSRui Miguel Silva 			return ov2680_vflip_disable(sensor);
860*3ee47cadSRui Miguel Silva 	case V4L2_CID_HFLIP:
861*3ee47cadSRui Miguel Silva 		if (sensor->is_streaming)
862*3ee47cadSRui Miguel Silva 			return -EBUSY;
863*3ee47cadSRui Miguel Silva 		if (ctrl->val)
864*3ee47cadSRui Miguel Silva 			return ov2680_hflip_enable(sensor);
865*3ee47cadSRui Miguel Silva 		else
866*3ee47cadSRui Miguel Silva 			return ov2680_hflip_disable(sensor);
867*3ee47cadSRui Miguel Silva 	case V4L2_CID_TEST_PATTERN:
868*3ee47cadSRui Miguel Silva 		return ov2680_test_pattern_set(sensor, ctrl->val);
869*3ee47cadSRui Miguel Silva 	default:
870*3ee47cadSRui Miguel Silva 		break;
871*3ee47cadSRui Miguel Silva 	}
872*3ee47cadSRui Miguel Silva 
873*3ee47cadSRui Miguel Silva 	return -EINVAL;
874*3ee47cadSRui Miguel Silva }
875*3ee47cadSRui Miguel Silva 
876*3ee47cadSRui Miguel Silva static const struct v4l2_ctrl_ops ov2680_ctrl_ops = {
877*3ee47cadSRui Miguel Silva 	.g_volatile_ctrl = ov2680_g_volatile_ctrl,
878*3ee47cadSRui Miguel Silva 	.s_ctrl = ov2680_s_ctrl,
879*3ee47cadSRui Miguel Silva };
880*3ee47cadSRui Miguel Silva 
881*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_core_ops ov2680_core_ops = {
882*3ee47cadSRui Miguel Silva 	.s_power = ov2680_s_power,
883*3ee47cadSRui Miguel Silva };
884*3ee47cadSRui Miguel Silva 
885*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_video_ops ov2680_video_ops = {
886*3ee47cadSRui Miguel Silva 	.g_frame_interval	= ov2680_s_g_frame_interval,
887*3ee47cadSRui Miguel Silva 	.s_frame_interval	= ov2680_s_g_frame_interval,
888*3ee47cadSRui Miguel Silva 	.s_stream		= ov2680_s_stream,
889*3ee47cadSRui Miguel Silva };
890*3ee47cadSRui Miguel Silva 
891*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_pad_ops ov2680_pad_ops = {
892*3ee47cadSRui Miguel Silva 	.init_cfg		= ov2680_init_cfg,
893*3ee47cadSRui Miguel Silva 	.enum_mbus_code		= ov2680_enum_mbus_code,
894*3ee47cadSRui Miguel Silva 	.get_fmt		= ov2680_get_fmt,
895*3ee47cadSRui Miguel Silva 	.set_fmt		= ov2680_set_fmt,
896*3ee47cadSRui Miguel Silva 	.enum_frame_size	= ov2680_enum_frame_size,
897*3ee47cadSRui Miguel Silva 	.enum_frame_interval	= ov2680_enum_frame_interval,
898*3ee47cadSRui Miguel Silva };
899*3ee47cadSRui Miguel Silva 
900*3ee47cadSRui Miguel Silva static const struct v4l2_subdev_ops ov2680_subdev_ops = {
901*3ee47cadSRui Miguel Silva 	.core	= &ov2680_core_ops,
902*3ee47cadSRui Miguel Silva 	.video	= &ov2680_video_ops,
903*3ee47cadSRui Miguel Silva 	.pad	= &ov2680_pad_ops,
904*3ee47cadSRui Miguel Silva };
905*3ee47cadSRui Miguel Silva 
906*3ee47cadSRui Miguel Silva static int ov2680_mode_init(struct ov2680_dev *sensor)
907*3ee47cadSRui Miguel Silva {
908*3ee47cadSRui Miguel Silva 	const struct ov2680_mode_info *init_mode;
909*3ee47cadSRui Miguel Silva 
910*3ee47cadSRui Miguel Silva 	/* set initial mode */
911*3ee47cadSRui Miguel Silva 	sensor->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
912*3ee47cadSRui Miguel Silva 	sensor->fmt.width = 800;
913*3ee47cadSRui Miguel Silva 	sensor->fmt.height = 600;
914*3ee47cadSRui Miguel Silva 	sensor->fmt.field = V4L2_FIELD_NONE;
915*3ee47cadSRui Miguel Silva 	sensor->fmt.colorspace = V4L2_COLORSPACE_SRGB;
916*3ee47cadSRui Miguel Silva 
917*3ee47cadSRui Miguel Silva 	sensor->frame_interval.denominator = OV2680_FRAME_RATE;
918*3ee47cadSRui Miguel Silva 	sensor->frame_interval.numerator = 1;
919*3ee47cadSRui Miguel Silva 
920*3ee47cadSRui Miguel Silva 	init_mode = &ov2680_mode_init_data;
921*3ee47cadSRui Miguel Silva 
922*3ee47cadSRui Miguel Silva 	sensor->current_mode = init_mode;
923*3ee47cadSRui Miguel Silva 
924*3ee47cadSRui Miguel Silva 	sensor->mode_pending_changes = true;
925*3ee47cadSRui Miguel Silva 
926*3ee47cadSRui Miguel Silva 	return 0;
927*3ee47cadSRui Miguel Silva }
928*3ee47cadSRui Miguel Silva 
929*3ee47cadSRui Miguel Silva static int ov2680_v4l2_init(struct ov2680_dev *sensor)
930*3ee47cadSRui Miguel Silva {
931*3ee47cadSRui Miguel Silva 	const struct v4l2_ctrl_ops *ops = &ov2680_ctrl_ops;
932*3ee47cadSRui Miguel Silva 	struct ov2680_ctrls *ctrls = &sensor->ctrls;
933*3ee47cadSRui Miguel Silva 	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
934*3ee47cadSRui Miguel Silva 	int ret = 0;
935*3ee47cadSRui Miguel Silva 
936*3ee47cadSRui Miguel Silva 	v4l2_i2c_subdev_init(&sensor->sd, sensor->i2c_client,
937*3ee47cadSRui Miguel Silva 			     &ov2680_subdev_ops);
938*3ee47cadSRui Miguel Silva 
939*3ee47cadSRui Miguel Silva #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
940*3ee47cadSRui Miguel Silva 	sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
941*3ee47cadSRui Miguel Silva #endif
942*3ee47cadSRui Miguel Silva 	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
943*3ee47cadSRui Miguel Silva 	sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
944*3ee47cadSRui Miguel Silva 
945*3ee47cadSRui Miguel Silva 	ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
946*3ee47cadSRui Miguel Silva 	if (ret < 0)
947*3ee47cadSRui Miguel Silva 		return ret;
948*3ee47cadSRui Miguel Silva 
949*3ee47cadSRui Miguel Silva 	v4l2_ctrl_handler_init(hdl, 7);
950*3ee47cadSRui Miguel Silva 
951*3ee47cadSRui Miguel Silva 	hdl->lock = &sensor->lock;
952*3ee47cadSRui Miguel Silva 
953*3ee47cadSRui Miguel Silva 	ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
954*3ee47cadSRui Miguel Silva 	ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
955*3ee47cadSRui Miguel Silva 
956*3ee47cadSRui Miguel Silva 	ctrls->test_pattern = v4l2_ctrl_new_std_menu_items(hdl,
957*3ee47cadSRui Miguel Silva 					&ov2680_ctrl_ops, V4L2_CID_TEST_PATTERN,
958*3ee47cadSRui Miguel Silva 					ARRAY_SIZE(test_pattern_menu) - 1,
959*3ee47cadSRui Miguel Silva 					0, 0, test_pattern_menu);
960*3ee47cadSRui Miguel Silva 
961*3ee47cadSRui Miguel Silva 	ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
962*3ee47cadSRui Miguel Silva 						 V4L2_CID_EXPOSURE_AUTO,
963*3ee47cadSRui Miguel Silva 						 V4L2_EXPOSURE_MANUAL, 0,
964*3ee47cadSRui Miguel Silva 						 V4L2_EXPOSURE_AUTO);
965*3ee47cadSRui Miguel Silva 
966*3ee47cadSRui Miguel Silva 	ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
967*3ee47cadSRui Miguel Silva 					    0, 32767, 1, 0);
968*3ee47cadSRui Miguel Silva 
969*3ee47cadSRui Miguel Silva 	ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
970*3ee47cadSRui Miguel Silva 					     0, 1, 1, 1);
971*3ee47cadSRui Miguel Silva 	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 0, 2047, 1, 0);
972*3ee47cadSRui Miguel Silva 
973*3ee47cadSRui Miguel Silva 	if (hdl->error) {
974*3ee47cadSRui Miguel Silva 		ret = hdl->error;
975*3ee47cadSRui Miguel Silva 		goto cleanup_entity;
976*3ee47cadSRui Miguel Silva 	}
977*3ee47cadSRui Miguel Silva 
978*3ee47cadSRui Miguel Silva 	ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
979*3ee47cadSRui Miguel Silva 	ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
980*3ee47cadSRui Miguel Silva 
981*3ee47cadSRui Miguel Silva 	v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
982*3ee47cadSRui Miguel Silva 	v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
983*3ee47cadSRui Miguel Silva 
984*3ee47cadSRui Miguel Silva 	sensor->sd.ctrl_handler = hdl;
985*3ee47cadSRui Miguel Silva 
986*3ee47cadSRui Miguel Silva 	ret = v4l2_async_register_subdev(&sensor->sd);
987*3ee47cadSRui Miguel Silva 	if (ret < 0)
988*3ee47cadSRui Miguel Silva 		goto cleanup_entity;
989*3ee47cadSRui Miguel Silva 
990*3ee47cadSRui Miguel Silva 	return 0;
991*3ee47cadSRui Miguel Silva 
992*3ee47cadSRui Miguel Silva cleanup_entity:
993*3ee47cadSRui Miguel Silva 	media_entity_cleanup(&sensor->sd.entity);
994*3ee47cadSRui Miguel Silva 	v4l2_ctrl_handler_free(hdl);
995*3ee47cadSRui Miguel Silva 
996*3ee47cadSRui Miguel Silva 	return ret;
997*3ee47cadSRui Miguel Silva }
998*3ee47cadSRui Miguel Silva 
999*3ee47cadSRui Miguel Silva static int ov2680_get_regulators(struct ov2680_dev *sensor)
1000*3ee47cadSRui Miguel Silva {
1001*3ee47cadSRui Miguel Silva 	int i;
1002*3ee47cadSRui Miguel Silva 
1003*3ee47cadSRui Miguel Silva 	for (i = 0; i < OV2680_NUM_SUPPLIES; i++)
1004*3ee47cadSRui Miguel Silva 		sensor->supplies[i].supply = ov2680_supply_name[i];
1005*3ee47cadSRui Miguel Silva 
1006*3ee47cadSRui Miguel Silva 	return devm_regulator_bulk_get(&sensor->i2c_client->dev,
1007*3ee47cadSRui Miguel Silva 				       OV2680_NUM_SUPPLIES,
1008*3ee47cadSRui Miguel Silva 				       sensor->supplies);
1009*3ee47cadSRui Miguel Silva }
1010*3ee47cadSRui Miguel Silva 
1011*3ee47cadSRui Miguel Silva static int ov2680_check_id(struct ov2680_dev *sensor)
1012*3ee47cadSRui Miguel Silva {
1013*3ee47cadSRui Miguel Silva 	struct device *dev = ov2680_to_dev(sensor);
1014*3ee47cadSRui Miguel Silva 	u32 chip_id;
1015*3ee47cadSRui Miguel Silva 	int ret;
1016*3ee47cadSRui Miguel Silva 
1017*3ee47cadSRui Miguel Silva 	ov2680_power_on(sensor);
1018*3ee47cadSRui Miguel Silva 
1019*3ee47cadSRui Miguel Silva 	ret = ov2680_read_reg16(sensor, OV2680_REG_CHIP_ID_HIGH, &chip_id);
1020*3ee47cadSRui Miguel Silva 	if (ret < 0) {
1021*3ee47cadSRui Miguel Silva 		dev_err(dev, "failed to read chip id high\n");
1022*3ee47cadSRui Miguel Silva 		return -ENODEV;
1023*3ee47cadSRui Miguel Silva 	}
1024*3ee47cadSRui Miguel Silva 
1025*3ee47cadSRui Miguel Silva 	if (chip_id != OV2680_CHIP_ID) {
1026*3ee47cadSRui Miguel Silva 		dev_err(dev, "chip id: 0x%04x does not match expected 0x%04x\n",
1027*3ee47cadSRui Miguel Silva 			chip_id, OV2680_CHIP_ID);
1028*3ee47cadSRui Miguel Silva 		return -ENODEV;
1029*3ee47cadSRui Miguel Silva 	}
1030*3ee47cadSRui Miguel Silva 
1031*3ee47cadSRui Miguel Silva 	return 0;
1032*3ee47cadSRui Miguel Silva }
1033*3ee47cadSRui Miguel Silva 
1034*3ee47cadSRui Miguel Silva static int ov2860_parse_dt(struct ov2680_dev *sensor)
1035*3ee47cadSRui Miguel Silva {
1036*3ee47cadSRui Miguel Silva 	struct device *dev = ov2680_to_dev(sensor);
1037*3ee47cadSRui Miguel Silva 	int ret;
1038*3ee47cadSRui Miguel Silva 
1039*3ee47cadSRui Miguel Silva 	sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1040*3ee47cadSRui Miguel Silva 						     GPIOD_OUT_HIGH);
1041*3ee47cadSRui Miguel Silva 	ret = PTR_ERR_OR_ZERO(sensor->reset_gpio);
1042*3ee47cadSRui Miguel Silva 	if (ret < 0) {
1043*3ee47cadSRui Miguel Silva 		dev_dbg(dev, "error while getting reset gpio: %d\n", ret);
1044*3ee47cadSRui Miguel Silva 		return ret;
1045*3ee47cadSRui Miguel Silva 	}
1046*3ee47cadSRui Miguel Silva 
1047*3ee47cadSRui Miguel Silva 	sensor->xvclk = devm_clk_get(dev, "xvclk");
1048*3ee47cadSRui Miguel Silva 	if (IS_ERR(sensor->xvclk)) {
1049*3ee47cadSRui Miguel Silva 		dev_err(dev, "xvclk clock missing or invalid\n");
1050*3ee47cadSRui Miguel Silva 		return PTR_ERR(sensor->xvclk);
1051*3ee47cadSRui Miguel Silva 	}
1052*3ee47cadSRui Miguel Silva 
1053*3ee47cadSRui Miguel Silva 	sensor->xvclk_freq = clk_get_rate(sensor->xvclk);
1054*3ee47cadSRui Miguel Silva 	if (sensor->xvclk_freq != OV2680_XVCLK_VALUE) {
1055*3ee47cadSRui Miguel Silva 		dev_err(dev, "wrong xvclk frequency %d HZ, expected: %d Hz\n",
1056*3ee47cadSRui Miguel Silva 			sensor->xvclk_freq, OV2680_XVCLK_VALUE);
1057*3ee47cadSRui Miguel Silva 		return -EINVAL;
1058*3ee47cadSRui Miguel Silva 	}
1059*3ee47cadSRui Miguel Silva 
1060*3ee47cadSRui Miguel Silva 	return 0;
1061*3ee47cadSRui Miguel Silva }
1062*3ee47cadSRui Miguel Silva 
1063*3ee47cadSRui Miguel Silva static int ov2680_probe(struct i2c_client *client)
1064*3ee47cadSRui Miguel Silva {
1065*3ee47cadSRui Miguel Silva 	struct device *dev = &client->dev;
1066*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor;
1067*3ee47cadSRui Miguel Silva 	int ret;
1068*3ee47cadSRui Miguel Silva 
1069*3ee47cadSRui Miguel Silva 	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
1070*3ee47cadSRui Miguel Silva 	if (!sensor)
1071*3ee47cadSRui Miguel Silva 		return -ENOMEM;
1072*3ee47cadSRui Miguel Silva 
1073*3ee47cadSRui Miguel Silva 	sensor->i2c_client = client;
1074*3ee47cadSRui Miguel Silva 
1075*3ee47cadSRui Miguel Silva 	ret = ov2860_parse_dt(sensor);
1076*3ee47cadSRui Miguel Silva 	if (ret < 0)
1077*3ee47cadSRui Miguel Silva 		return -EINVAL;
1078*3ee47cadSRui Miguel Silva 
1079*3ee47cadSRui Miguel Silva 	ret = ov2680_mode_init(sensor);
1080*3ee47cadSRui Miguel Silva 	if (ret < 0)
1081*3ee47cadSRui Miguel Silva 		return ret;
1082*3ee47cadSRui Miguel Silva 
1083*3ee47cadSRui Miguel Silva 	ret = ov2680_get_regulators(sensor);
1084*3ee47cadSRui Miguel Silva 	if (ret < 0) {
1085*3ee47cadSRui Miguel Silva 		dev_err(dev, "failed to get regulators\n");
1086*3ee47cadSRui Miguel Silva 		return ret;
1087*3ee47cadSRui Miguel Silva 	}
1088*3ee47cadSRui Miguel Silva 
1089*3ee47cadSRui Miguel Silva 	mutex_init(&sensor->lock);
1090*3ee47cadSRui Miguel Silva 
1091*3ee47cadSRui Miguel Silva 	ret = ov2680_v4l2_init(sensor);
1092*3ee47cadSRui Miguel Silva 	if (ret < 0)
1093*3ee47cadSRui Miguel Silva 		goto lock_destroy;
1094*3ee47cadSRui Miguel Silva 
1095*3ee47cadSRui Miguel Silva 	ret = ov2680_check_id(sensor);
1096*3ee47cadSRui Miguel Silva 	if (ret < 0)
1097*3ee47cadSRui Miguel Silva 		goto error_cleanup;
1098*3ee47cadSRui Miguel Silva 
1099*3ee47cadSRui Miguel Silva 	dev_info(dev, "ov2680 init correctly\n");
1100*3ee47cadSRui Miguel Silva 
1101*3ee47cadSRui Miguel Silva 	return 0;
1102*3ee47cadSRui Miguel Silva 
1103*3ee47cadSRui Miguel Silva error_cleanup:
1104*3ee47cadSRui Miguel Silva 	dev_err(dev, "ov2680 init fail: %d\n", ret);
1105*3ee47cadSRui Miguel Silva 
1106*3ee47cadSRui Miguel Silva 	media_entity_cleanup(&sensor->sd.entity);
1107*3ee47cadSRui Miguel Silva 	v4l2_async_unregister_subdev(&sensor->sd);
1108*3ee47cadSRui Miguel Silva 	v4l2_ctrl_handler_free(&sensor->ctrls.handler);
1109*3ee47cadSRui Miguel Silva 
1110*3ee47cadSRui Miguel Silva lock_destroy:
1111*3ee47cadSRui Miguel Silva 	mutex_destroy(&sensor->lock);
1112*3ee47cadSRui Miguel Silva 
1113*3ee47cadSRui Miguel Silva 	return ret;
1114*3ee47cadSRui Miguel Silva }
1115*3ee47cadSRui Miguel Silva 
1116*3ee47cadSRui Miguel Silva static int ov2680_remove(struct i2c_client *client)
1117*3ee47cadSRui Miguel Silva {
1118*3ee47cadSRui Miguel Silva 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1119*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
1120*3ee47cadSRui Miguel Silva 
1121*3ee47cadSRui Miguel Silva 	v4l2_async_unregister_subdev(&sensor->sd);
1122*3ee47cadSRui Miguel Silva 	mutex_destroy(&sensor->lock);
1123*3ee47cadSRui Miguel Silva 	media_entity_cleanup(&sensor->sd.entity);
1124*3ee47cadSRui Miguel Silva 	v4l2_ctrl_handler_free(&sensor->ctrls.handler);
1125*3ee47cadSRui Miguel Silva 
1126*3ee47cadSRui Miguel Silva 	return 0;
1127*3ee47cadSRui Miguel Silva }
1128*3ee47cadSRui Miguel Silva 
1129*3ee47cadSRui Miguel Silva static int __maybe_unused ov2680_suspend(struct device *dev)
1130*3ee47cadSRui Miguel Silva {
1131*3ee47cadSRui Miguel Silva 	struct i2c_client *client = to_i2c_client(dev);
1132*3ee47cadSRui Miguel Silva 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1133*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
1134*3ee47cadSRui Miguel Silva 
1135*3ee47cadSRui Miguel Silva 	if (sensor->is_streaming)
1136*3ee47cadSRui Miguel Silva 		ov2680_stream_disable(sensor);
1137*3ee47cadSRui Miguel Silva 
1138*3ee47cadSRui Miguel Silva 	return 0;
1139*3ee47cadSRui Miguel Silva }
1140*3ee47cadSRui Miguel Silva 
1141*3ee47cadSRui Miguel Silva static int __maybe_unused ov2680_resume(struct device *dev)
1142*3ee47cadSRui Miguel Silva {
1143*3ee47cadSRui Miguel Silva 	struct i2c_client *client = to_i2c_client(dev);
1144*3ee47cadSRui Miguel Silva 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1145*3ee47cadSRui Miguel Silva 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
1146*3ee47cadSRui Miguel Silva 	int ret;
1147*3ee47cadSRui Miguel Silva 
1148*3ee47cadSRui Miguel Silva 	if (sensor->is_streaming) {
1149*3ee47cadSRui Miguel Silva 		ret = ov2680_stream_enable(sensor);
1150*3ee47cadSRui Miguel Silva 		if (ret < 0)
1151*3ee47cadSRui Miguel Silva 			goto stream_disable;
1152*3ee47cadSRui Miguel Silva 	}
1153*3ee47cadSRui Miguel Silva 
1154*3ee47cadSRui Miguel Silva 	return 0;
1155*3ee47cadSRui Miguel Silva 
1156*3ee47cadSRui Miguel Silva stream_disable:
1157*3ee47cadSRui Miguel Silva 	ov2680_stream_disable(sensor);
1158*3ee47cadSRui Miguel Silva 	sensor->is_streaming = false;
1159*3ee47cadSRui Miguel Silva 
1160*3ee47cadSRui Miguel Silva 	return ret;
1161*3ee47cadSRui Miguel Silva }
1162*3ee47cadSRui Miguel Silva 
1163*3ee47cadSRui Miguel Silva static const struct dev_pm_ops ov2680_pm_ops = {
1164*3ee47cadSRui Miguel Silva 	SET_SYSTEM_SLEEP_PM_OPS(ov2680_suspend, ov2680_resume)
1165*3ee47cadSRui Miguel Silva };
1166*3ee47cadSRui Miguel Silva 
1167*3ee47cadSRui Miguel Silva static const struct of_device_id ov2680_dt_ids[] = {
1168*3ee47cadSRui Miguel Silva 	{ .compatible = "ovti,ov2680" },
1169*3ee47cadSRui Miguel Silva 	{ /* sentinel */ },
1170*3ee47cadSRui Miguel Silva };
1171*3ee47cadSRui Miguel Silva MODULE_DEVICE_TABLE(of, ov2680_dt_ids);
1172*3ee47cadSRui Miguel Silva 
1173*3ee47cadSRui Miguel Silva static struct i2c_driver ov2680_i2c_driver = {
1174*3ee47cadSRui Miguel Silva 	.driver = {
1175*3ee47cadSRui Miguel Silva 		.name  = "ov2680",
1176*3ee47cadSRui Miguel Silva 		.pm = &ov2680_pm_ops,
1177*3ee47cadSRui Miguel Silva 		.of_match_table	= of_match_ptr(ov2680_dt_ids),
1178*3ee47cadSRui Miguel Silva 	},
1179*3ee47cadSRui Miguel Silva 	.probe_new	= ov2680_probe,
1180*3ee47cadSRui Miguel Silva 	.remove		= ov2680_remove,
1181*3ee47cadSRui Miguel Silva };
1182*3ee47cadSRui Miguel Silva module_i2c_driver(ov2680_i2c_driver);
1183*3ee47cadSRui Miguel Silva 
1184*3ee47cadSRui Miguel Silva MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>");
1185*3ee47cadSRui Miguel Silva MODULE_DESCRIPTION("OV2680 CMOS Image Sensor driver");
1186*3ee47cadSRui Miguel Silva MODULE_LICENSE("GPL v2");
1187