1ad85094bSMauro Carvalho Chehab /*
2ad85094bSMauro Carvalho Chehab  * Support for OmniVision OV5693 1080p HD camera sensor.
3ad85094bSMauro Carvalho Chehab  *
4ad85094bSMauro Carvalho Chehab  * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
5ad85094bSMauro Carvalho Chehab  *
6ad85094bSMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or
7ad85094bSMauro Carvalho Chehab  * modify it under the terms of the GNU General Public License version
8ad85094bSMauro Carvalho Chehab  * 2 as published by the Free Software Foundation.
9ad85094bSMauro Carvalho Chehab  *
10ad85094bSMauro Carvalho Chehab  * This program is distributed in the hope that it will be useful,
11ad85094bSMauro Carvalho Chehab  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12ad85094bSMauro Carvalho Chehab  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13ad85094bSMauro Carvalho Chehab  * GNU General Public License for more details.
14ad85094bSMauro Carvalho Chehab  *
15ad85094bSMauro Carvalho Chehab  *
16ad85094bSMauro Carvalho Chehab  */
17ad85094bSMauro Carvalho Chehab 
18ad85094bSMauro Carvalho Chehab #include <linux/module.h>
19ad85094bSMauro Carvalho Chehab #include <linux/types.h>
20ad85094bSMauro Carvalho Chehab #include <linux/kernel.h>
21ad85094bSMauro Carvalho Chehab #include <linux/mm.h>
22ad85094bSMauro Carvalho Chehab #include <linux/string.h>
23ad85094bSMauro Carvalho Chehab #include <linux/errno.h>
24ad85094bSMauro Carvalho Chehab #include <linux/init.h>
25ad85094bSMauro Carvalho Chehab #include <linux/kmod.h>
26ad85094bSMauro Carvalho Chehab #include <linux/device.h>
27ad85094bSMauro Carvalho Chehab #include <linux/delay.h>
28ad85094bSMauro Carvalho Chehab #include <linux/slab.h>
29ad85094bSMauro Carvalho Chehab #include <linux/i2c.h>
30ad85094bSMauro Carvalho Chehab #include <linux/moduleparam.h>
31ad85094bSMauro Carvalho Chehab #include <media/v4l2-device.h>
32ad85094bSMauro Carvalho Chehab #include <linux/io.h>
33ad85094bSMauro Carvalho Chehab #include <linux/acpi.h>
34ad85094bSMauro Carvalho Chehab #include "../../include/linux/atomisp_gmin_platform.h"
35ad85094bSMauro Carvalho Chehab 
36ad85094bSMauro Carvalho Chehab #include "ov5693.h"
37ad85094bSMauro Carvalho Chehab #include "ad5823.h"
38ad85094bSMauro Carvalho Chehab 
39ad85094bSMauro Carvalho Chehab #define __cci_delay(t) \
40ad85094bSMauro Carvalho Chehab 	do { \
41ad85094bSMauro Carvalho Chehab 		if ((t) < 10) { \
42ad85094bSMauro Carvalho Chehab 			usleep_range((t) * 1000, ((t) + 1) * 1000); \
43ad85094bSMauro Carvalho Chehab 		} else { \
44ad85094bSMauro Carvalho Chehab 			msleep((t)); \
45ad85094bSMauro Carvalho Chehab 		} \
46ad85094bSMauro Carvalho Chehab 	} while (0)
47ad85094bSMauro Carvalho Chehab 
48ad85094bSMauro Carvalho Chehab /* Value 30ms reached through experimentation on byt ecs.
49ad85094bSMauro Carvalho Chehab  * The DS specifies a much lower value but when using a smaller value
50ad85094bSMauro Carvalho Chehab  * the I2C bus sometimes locks up permanently when starting the camera.
51ad85094bSMauro Carvalho Chehab  * This issue could not be reproduced on cht, so we can reduce the
52ad85094bSMauro Carvalho Chehab  * delay value to a lower value when insmod.
53ad85094bSMauro Carvalho Chehab  */
54ad85094bSMauro Carvalho Chehab static uint up_delay = 30;
55ad85094bSMauro Carvalho Chehab module_param(up_delay, uint, 0644);
56ad85094bSMauro Carvalho Chehab MODULE_PARM_DESC(up_delay, "Delay prior to the first CCI transaction for ov5693");
57ad85094bSMauro Carvalho Chehab 
58ad85094bSMauro Carvalho Chehab static int vcm_ad_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
59ad85094bSMauro Carvalho Chehab {
60ad85094bSMauro Carvalho Chehab 	int err;
61ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg;
62ad85094bSMauro Carvalho Chehab 	u8 buf[2];
63ad85094bSMauro Carvalho Chehab 
64ad85094bSMauro Carvalho Chehab 	buf[0] = reg;
65ad85094bSMauro Carvalho Chehab 	buf[1] = val;
66ad85094bSMauro Carvalho Chehab 
67ad85094bSMauro Carvalho Chehab 	msg.addr = VCM_ADDR;
68ad85094bSMauro Carvalho Chehab 	msg.flags = 0;
69ad85094bSMauro Carvalho Chehab 	msg.len = 2;
70ad85094bSMauro Carvalho Chehab 	msg.buf = &buf[0];
71ad85094bSMauro Carvalho Chehab 
72ad85094bSMauro Carvalho Chehab 	err = i2c_transfer(client->adapter, &msg, 1);
73ad85094bSMauro Carvalho Chehab 	if (err != 1) {
74ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: vcm i2c fail, err code = %d\n",
75ad85094bSMauro Carvalho Chehab 			__func__, err);
76ad85094bSMauro Carvalho Chehab 		return -EIO;
77ad85094bSMauro Carvalho Chehab 	}
78ad85094bSMauro Carvalho Chehab 	return 0;
79ad85094bSMauro Carvalho Chehab }
80ad85094bSMauro Carvalho Chehab 
81ad85094bSMauro Carvalho Chehab static int ad5823_i2c_write(struct i2c_client *client, u8 reg, u8 val)
82ad85094bSMauro Carvalho Chehab {
83ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg;
84ad85094bSMauro Carvalho Chehab 	u8 buf[2];
85ad85094bSMauro Carvalho Chehab 
86ad85094bSMauro Carvalho Chehab 	buf[0] = reg;
87ad85094bSMauro Carvalho Chehab 	buf[1] = val;
88ad85094bSMauro Carvalho Chehab 	msg.addr = AD5823_VCM_ADDR;
89ad85094bSMauro Carvalho Chehab 	msg.flags = 0;
90ad85094bSMauro Carvalho Chehab 	msg.len = 0x02;
91ad85094bSMauro Carvalho Chehab 	msg.buf = &buf[0];
92ad85094bSMauro Carvalho Chehab 
93ad85094bSMauro Carvalho Chehab 	if (i2c_transfer(client->adapter, &msg, 1) != 1)
94ad85094bSMauro Carvalho Chehab 		return -EIO;
95ad85094bSMauro Carvalho Chehab 	return 0;
96ad85094bSMauro Carvalho Chehab }
97ad85094bSMauro Carvalho Chehab 
98ad85094bSMauro Carvalho Chehab static int ad5823_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
99ad85094bSMauro Carvalho Chehab {
100ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg[2];
101ad85094bSMauro Carvalho Chehab 	u8 buf[2];
102ad85094bSMauro Carvalho Chehab 
103ad85094bSMauro Carvalho Chehab 	buf[0] = reg;
104ad85094bSMauro Carvalho Chehab 	buf[1] = 0;
105ad85094bSMauro Carvalho Chehab 
106ad85094bSMauro Carvalho Chehab 	msg[0].addr = AD5823_VCM_ADDR;
107ad85094bSMauro Carvalho Chehab 	msg[0].flags = 0;
108ad85094bSMauro Carvalho Chehab 	msg[0].len = 0x01;
109ad85094bSMauro Carvalho Chehab 	msg[0].buf = &buf[0];
110ad85094bSMauro Carvalho Chehab 
111ad85094bSMauro Carvalho Chehab 	msg[1].addr = 0x0c;
112ad85094bSMauro Carvalho Chehab 	msg[1].flags = I2C_M_RD;
113ad85094bSMauro Carvalho Chehab 	msg[1].len = 0x01;
114ad85094bSMauro Carvalho Chehab 	msg[1].buf = &buf[1];
115ad85094bSMauro Carvalho Chehab 	*val = 0;
116ad85094bSMauro Carvalho Chehab 	if (i2c_transfer(client->adapter, msg, 2) != 2)
117ad85094bSMauro Carvalho Chehab 		return -EIO;
118ad85094bSMauro Carvalho Chehab 	*val = buf[1];
119ad85094bSMauro Carvalho Chehab 	return 0;
120ad85094bSMauro Carvalho Chehab }
121ad85094bSMauro Carvalho Chehab 
122bdfe0bebSMauro Carvalho Chehab static const u32 ov5693_embedded_effective_size = 28;
123ad85094bSMauro Carvalho Chehab 
124ad85094bSMauro Carvalho Chehab /* i2c read/write stuff */
125ad85094bSMauro Carvalho Chehab static int ov5693_read_reg(struct i2c_client *client,
126ad85094bSMauro Carvalho Chehab 			   u16 data_length, u16 reg, u16 *val)
127ad85094bSMauro Carvalho Chehab {
128ad85094bSMauro Carvalho Chehab 	int err;
129ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg[2];
130ad85094bSMauro Carvalho Chehab 	unsigned char data[6];
131ad85094bSMauro Carvalho Chehab 
132ad85094bSMauro Carvalho Chehab 	if (!client->adapter) {
133ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s error, no client->adapter\n",
134ad85094bSMauro Carvalho Chehab 			__func__);
135ad85094bSMauro Carvalho Chehab 		return -ENODEV;
136ad85094bSMauro Carvalho Chehab 	}
137ad85094bSMauro Carvalho Chehab 
138ad85094bSMauro Carvalho Chehab 	if (data_length != OV5693_8BIT && data_length != OV5693_16BIT
139ad85094bSMauro Carvalho Chehab 					&& data_length != OV5693_32BIT) {
140ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s error, invalid data length\n",
141ad85094bSMauro Carvalho Chehab 			__func__);
142ad85094bSMauro Carvalho Chehab 		return -EINVAL;
143ad85094bSMauro Carvalho Chehab 	}
144ad85094bSMauro Carvalho Chehab 
145ad85094bSMauro Carvalho Chehab 	memset(msg, 0, sizeof(msg));
146ad85094bSMauro Carvalho Chehab 
147ad85094bSMauro Carvalho Chehab 	msg[0].addr = client->addr;
148ad85094bSMauro Carvalho Chehab 	msg[0].flags = 0;
149ad85094bSMauro Carvalho Chehab 	msg[0].len = I2C_MSG_LENGTH;
150ad85094bSMauro Carvalho Chehab 	msg[0].buf = data;
151ad85094bSMauro Carvalho Chehab 
152ad85094bSMauro Carvalho Chehab 	/* high byte goes out first */
153ad85094bSMauro Carvalho Chehab 	data[0] = (u8)(reg >> 8);
154ad85094bSMauro Carvalho Chehab 	data[1] = (u8)(reg & 0xff);
155ad85094bSMauro Carvalho Chehab 
156ad85094bSMauro Carvalho Chehab 	msg[1].addr = client->addr;
157ad85094bSMauro Carvalho Chehab 	msg[1].len = data_length;
158ad85094bSMauro Carvalho Chehab 	msg[1].flags = I2C_M_RD;
159ad85094bSMauro Carvalho Chehab 	msg[1].buf = data;
160ad85094bSMauro Carvalho Chehab 
161ad85094bSMauro Carvalho Chehab 	err = i2c_transfer(client->adapter, msg, 2);
162ad85094bSMauro Carvalho Chehab 	if (err != 2) {
163ad85094bSMauro Carvalho Chehab 		if (err >= 0)
164ad85094bSMauro Carvalho Chehab 			err = -EIO;
165ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev,
166ad85094bSMauro Carvalho Chehab 			"read from offset 0x%x error %d", reg, err);
167ad85094bSMauro Carvalho Chehab 		return err;
168ad85094bSMauro Carvalho Chehab 	}
169ad85094bSMauro Carvalho Chehab 
170ad85094bSMauro Carvalho Chehab 	*val = 0;
171ad85094bSMauro Carvalho Chehab 	/* high byte comes first */
172ad85094bSMauro Carvalho Chehab 	if (data_length == OV5693_8BIT)
173ad85094bSMauro Carvalho Chehab 		*val = (u8)data[0];
174ad85094bSMauro Carvalho Chehab 	else if (data_length == OV5693_16BIT)
175ad85094bSMauro Carvalho Chehab 		*val = be16_to_cpu(*(__be16 *)&data[0]);
176ad85094bSMauro Carvalho Chehab 	else
177ad85094bSMauro Carvalho Chehab 		*val = be32_to_cpu(*(__be32 *)&data[0]);
178ad85094bSMauro Carvalho Chehab 
179ad85094bSMauro Carvalho Chehab 	return 0;
180ad85094bSMauro Carvalho Chehab }
181ad85094bSMauro Carvalho Chehab 
182ad85094bSMauro Carvalho Chehab static int ov5693_i2c_write(struct i2c_client *client, u16 len, u8 *data)
183ad85094bSMauro Carvalho Chehab {
184ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg;
185ad85094bSMauro Carvalho Chehab 	const int num_msg = 1;
186ad85094bSMauro Carvalho Chehab 	int ret;
187ad85094bSMauro Carvalho Chehab 
188ad85094bSMauro Carvalho Chehab 	msg.addr = client->addr;
189ad85094bSMauro Carvalho Chehab 	msg.flags = 0;
190ad85094bSMauro Carvalho Chehab 	msg.len = len;
191ad85094bSMauro Carvalho Chehab 	msg.buf = data;
192ad85094bSMauro Carvalho Chehab 	ret = i2c_transfer(client->adapter, &msg, 1);
193ad85094bSMauro Carvalho Chehab 
194ad85094bSMauro Carvalho Chehab 	return ret == num_msg ? 0 : -EIO;
195ad85094bSMauro Carvalho Chehab }
196ad85094bSMauro Carvalho Chehab 
197ad85094bSMauro Carvalho Chehab static int vcm_dw_i2c_write(struct i2c_client *client, u16 data)
198ad85094bSMauro Carvalho Chehab {
199ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg;
200ad85094bSMauro Carvalho Chehab 	const int num_msg = 1;
201ad85094bSMauro Carvalho Chehab 	int ret;
202ad85094bSMauro Carvalho Chehab 	__be16 val;
203ad85094bSMauro Carvalho Chehab 
204ad85094bSMauro Carvalho Chehab 	val = cpu_to_be16(data);
205ad85094bSMauro Carvalho Chehab 	msg.addr = VCM_ADDR;
206ad85094bSMauro Carvalho Chehab 	msg.flags = 0;
207ad85094bSMauro Carvalho Chehab 	msg.len = OV5693_16BIT;
208ad85094bSMauro Carvalho Chehab 	msg.buf = (void *)&val;
209ad85094bSMauro Carvalho Chehab 
210ad85094bSMauro Carvalho Chehab 	ret = i2c_transfer(client->adapter, &msg, 1);
211ad85094bSMauro Carvalho Chehab 
212ad85094bSMauro Carvalho Chehab 	return ret == num_msg ? 0 : -EIO;
213ad85094bSMauro Carvalho Chehab }
214ad85094bSMauro Carvalho Chehab 
215ad85094bSMauro Carvalho Chehab /*
216ad85094bSMauro Carvalho Chehab  * Theory: per datasheet, the two VCMs both allow for a 2-byte read.
217ad85094bSMauro Carvalho Chehab  * The DW9714 doesn't actually specify what this does (it has a
218ad85094bSMauro Carvalho Chehab  * two-byte write-only protocol, but specifies the read sequence as
219ad85094bSMauro Carvalho Chehab  * legal), but it returns the same data (zeroes) always, after an
220ad85094bSMauro Carvalho Chehab  * undocumented initial NAK.  The AD5823 has a one-byte address
221ad85094bSMauro Carvalho Chehab  * register to which all writes go, and subsequent reads will cycle
222ad85094bSMauro Carvalho Chehab  * through the 8 bytes of registers.  Notably, the default values (the
223ad85094bSMauro Carvalho Chehab  * device is always power-cycled affirmatively, so we can rely on
224ad85094bSMauro Carvalho Chehab  * these) in AD5823 are not pairwise repetitions of the same 16 bit
225ad85094bSMauro Carvalho Chehab  * word.  So all we have to do is sequentially read two bytes at a
226ad85094bSMauro Carvalho Chehab  * time and see if we detect a difference in any of the first four
227ad85094bSMauro Carvalho Chehab  * pairs.
228ad85094bSMauro Carvalho Chehab  */
229ad85094bSMauro Carvalho Chehab static int vcm_detect(struct i2c_client *client)
230ad85094bSMauro Carvalho Chehab {
231ad85094bSMauro Carvalho Chehab 	int i, ret;
232ad85094bSMauro Carvalho Chehab 	struct i2c_msg msg;
233ad85094bSMauro Carvalho Chehab 	u16 data0 = 0, data;
234ad85094bSMauro Carvalho Chehab 
235ad85094bSMauro Carvalho Chehab 	for (i = 0; i < 4; i++) {
236ad85094bSMauro Carvalho Chehab 		msg.addr = VCM_ADDR;
237ad85094bSMauro Carvalho Chehab 		msg.flags = I2C_M_RD;
238ad85094bSMauro Carvalho Chehab 		msg.len = sizeof(data);
239ad85094bSMauro Carvalho Chehab 		msg.buf = (u8 *)&data;
240ad85094bSMauro Carvalho Chehab 		ret = i2c_transfer(client->adapter, &msg, 1);
241ad85094bSMauro Carvalho Chehab 
242ad85094bSMauro Carvalho Chehab 		/*
243ad85094bSMauro Carvalho Chehab 		 * DW9714 always fails the first read and returns
244ad85094bSMauro Carvalho Chehab 		 * zeroes for subsequent ones
245ad85094bSMauro Carvalho Chehab 		 */
246ad85094bSMauro Carvalho Chehab 		if (i == 0 && ret == -EREMOTEIO) {
247ad85094bSMauro Carvalho Chehab 			data0 = 0;
248ad85094bSMauro Carvalho Chehab 			continue;
249ad85094bSMauro Carvalho Chehab 		}
250ad85094bSMauro Carvalho Chehab 
251ad85094bSMauro Carvalho Chehab 		if (i == 0)
252ad85094bSMauro Carvalho Chehab 			data0 = data;
253ad85094bSMauro Carvalho Chehab 
254ad85094bSMauro Carvalho Chehab 		if (data != data0)
255ad85094bSMauro Carvalho Chehab 			return VCM_AD5823;
256ad85094bSMauro Carvalho Chehab 	}
257ad85094bSMauro Carvalho Chehab 	return ret == 1 ? VCM_DW9714 : ret;
258ad85094bSMauro Carvalho Chehab }
259ad85094bSMauro Carvalho Chehab 
260ad85094bSMauro Carvalho Chehab static int ov5693_write_reg(struct i2c_client *client, u16 data_length,
261ad85094bSMauro Carvalho Chehab 							u16 reg, u16 val)
262ad85094bSMauro Carvalho Chehab {
263ad85094bSMauro Carvalho Chehab 	int ret;
264ad85094bSMauro Carvalho Chehab 	unsigned char data[4] = {0};
265ad85094bSMauro Carvalho Chehab 	__be16 *wreg = (void *)data;
266ad85094bSMauro Carvalho Chehab 	const u16 len = data_length + sizeof(u16); /* 16-bit address + data */
267ad85094bSMauro Carvalho Chehab 
268ad85094bSMauro Carvalho Chehab 	if (data_length != OV5693_8BIT && data_length != OV5693_16BIT) {
269ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev,
270ad85094bSMauro Carvalho Chehab 			"%s error, invalid data_length\n", __func__);
271ad85094bSMauro Carvalho Chehab 		return -EINVAL;
272ad85094bSMauro Carvalho Chehab 	}
273ad85094bSMauro Carvalho Chehab 
274ad85094bSMauro Carvalho Chehab 	/* high byte goes out first */
275ad85094bSMauro Carvalho Chehab 	*wreg = cpu_to_be16(reg);
276ad85094bSMauro Carvalho Chehab 
277ad85094bSMauro Carvalho Chehab 	if (data_length == OV5693_8BIT) {
278ad85094bSMauro Carvalho Chehab 		data[2] = (u8)(val);
279ad85094bSMauro Carvalho Chehab 	} else {
280ad85094bSMauro Carvalho Chehab 		/* OV5693_16BIT */
281ad85094bSMauro Carvalho Chehab 		__be16 *wdata = (void *)&data[2];
282ad85094bSMauro Carvalho Chehab 
283ad85094bSMauro Carvalho Chehab 		*wdata = cpu_to_be16(val);
284ad85094bSMauro Carvalho Chehab 	}
285ad85094bSMauro Carvalho Chehab 
286ad85094bSMauro Carvalho Chehab 	ret = ov5693_i2c_write(client, len, data);
287ad85094bSMauro Carvalho Chehab 	if (ret)
288ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev,
289ad85094bSMauro Carvalho Chehab 			"write error: wrote 0x%x to offset 0x%x error %d",
290ad85094bSMauro Carvalho Chehab 			val, reg, ret);
291ad85094bSMauro Carvalho Chehab 
292ad85094bSMauro Carvalho Chehab 	return ret;
293ad85094bSMauro Carvalho Chehab }
294ad85094bSMauro Carvalho Chehab 
295ad85094bSMauro Carvalho Chehab /*
296ad85094bSMauro Carvalho Chehab  * ov5693_write_reg_array - Initializes a list of OV5693 registers
297ad85094bSMauro Carvalho Chehab  * @client: i2c driver client structure
298ad85094bSMauro Carvalho Chehab  * @reglist: list of registers to be written
299ad85094bSMauro Carvalho Chehab  *
300ad85094bSMauro Carvalho Chehab  * This function initializes a list of registers. When consecutive addresses
301ad85094bSMauro Carvalho Chehab  * are found in a row on the list, this function creates a buffer and sends
302ad85094bSMauro Carvalho Chehab  * consecutive data in a single i2c_transfer().
303ad85094bSMauro Carvalho Chehab  *
304ad85094bSMauro Carvalho Chehab  * __ov5693_flush_reg_array, __ov5693_buf_reg_array() and
305ad85094bSMauro Carvalho Chehab  * __ov5693_write_reg_is_consecutive() are internal functions to
306ad85094bSMauro Carvalho Chehab  * ov5693_write_reg_array_fast() and should be not used anywhere else.
307ad85094bSMauro Carvalho Chehab  *
308ad85094bSMauro Carvalho Chehab  */
309ad85094bSMauro Carvalho Chehab 
310ad85094bSMauro Carvalho Chehab static int __ov5693_flush_reg_array(struct i2c_client *client,
311ad85094bSMauro Carvalho Chehab 				    struct ov5693_write_ctrl *ctrl)
312ad85094bSMauro Carvalho Chehab {
313ad85094bSMauro Carvalho Chehab 	u16 size;
314ad85094bSMauro Carvalho Chehab 	__be16 *reg = (void *)&ctrl->buffer.addr;
315ad85094bSMauro Carvalho Chehab 
316ad85094bSMauro Carvalho Chehab 	if (ctrl->index == 0)
317ad85094bSMauro Carvalho Chehab 		return 0;
318ad85094bSMauro Carvalho Chehab 
319ad85094bSMauro Carvalho Chehab 	size = sizeof(u16) + ctrl->index; /* 16-bit address + data */
320ad85094bSMauro Carvalho Chehab 
321ad85094bSMauro Carvalho Chehab 	*reg = cpu_to_be16(ctrl->buffer.addr);
322ad85094bSMauro Carvalho Chehab 	ctrl->index = 0;
323ad85094bSMauro Carvalho Chehab 
324ad85094bSMauro Carvalho Chehab 	return ov5693_i2c_write(client, size, (u8 *)reg);
325ad85094bSMauro Carvalho Chehab }
326ad85094bSMauro Carvalho Chehab 
327ad85094bSMauro Carvalho Chehab static int __ov5693_buf_reg_array(struct i2c_client *client,
328ad85094bSMauro Carvalho Chehab 				  struct ov5693_write_ctrl *ctrl,
329ad85094bSMauro Carvalho Chehab 				  const struct ov5693_reg *next)
330ad85094bSMauro Carvalho Chehab {
331ad85094bSMauro Carvalho Chehab 	int size;
332ad85094bSMauro Carvalho Chehab 	__be16 *data16;
333ad85094bSMauro Carvalho Chehab 
334ad85094bSMauro Carvalho Chehab 	switch (next->type) {
335ad85094bSMauro Carvalho Chehab 	case OV5693_8BIT:
336ad85094bSMauro Carvalho Chehab 		size = 1;
337ad85094bSMauro Carvalho Chehab 		ctrl->buffer.data[ctrl->index] = (u8)next->val;
338ad85094bSMauro Carvalho Chehab 		break;
339ad85094bSMauro Carvalho Chehab 	case OV5693_16BIT:
340ad85094bSMauro Carvalho Chehab 		size = 2;
341ad85094bSMauro Carvalho Chehab 
342ad85094bSMauro Carvalho Chehab 		data16 = (void *)&ctrl->buffer.data[ctrl->index];
343ad85094bSMauro Carvalho Chehab 		*data16 = cpu_to_be16((u16)next->val);
344ad85094bSMauro Carvalho Chehab 		break;
345ad85094bSMauro Carvalho Chehab 	default:
346ad85094bSMauro Carvalho Chehab 		return -EINVAL;
347ad85094bSMauro Carvalho Chehab 	}
348ad85094bSMauro Carvalho Chehab 
349ad85094bSMauro Carvalho Chehab 	/* When first item is added, we need to store its starting address */
350ad85094bSMauro Carvalho Chehab 	if (ctrl->index == 0)
351ad85094bSMauro Carvalho Chehab 		ctrl->buffer.addr = next->reg;
352ad85094bSMauro Carvalho Chehab 
353ad85094bSMauro Carvalho Chehab 	ctrl->index += size;
354ad85094bSMauro Carvalho Chehab 
355ad85094bSMauro Carvalho Chehab 	/*
356ad85094bSMauro Carvalho Chehab 	 * Buffer cannot guarantee free space for u32? Better flush it to avoid
357ad85094bSMauro Carvalho Chehab 	 * possible lack of memory for next item.
358ad85094bSMauro Carvalho Chehab 	 */
359ad85094bSMauro Carvalho Chehab 	if (ctrl->index + sizeof(u16) >= OV5693_MAX_WRITE_BUF_SIZE)
360ad85094bSMauro Carvalho Chehab 		return __ov5693_flush_reg_array(client, ctrl);
361ad85094bSMauro Carvalho Chehab 
362ad85094bSMauro Carvalho Chehab 	return 0;
363ad85094bSMauro Carvalho Chehab }
364ad85094bSMauro Carvalho Chehab 
365ad85094bSMauro Carvalho Chehab static int __ov5693_write_reg_is_consecutive(struct i2c_client *client,
366ad85094bSMauro Carvalho Chehab 					     struct ov5693_write_ctrl *ctrl,
367ad85094bSMauro Carvalho Chehab 					     const struct ov5693_reg *next)
368ad85094bSMauro Carvalho Chehab {
369ad85094bSMauro Carvalho Chehab 	if (ctrl->index == 0)
370ad85094bSMauro Carvalho Chehab 		return 1;
371ad85094bSMauro Carvalho Chehab 
372ad85094bSMauro Carvalho Chehab 	return ctrl->buffer.addr + ctrl->index == next->reg;
373ad85094bSMauro Carvalho Chehab }
374ad85094bSMauro Carvalho Chehab 
375ad85094bSMauro Carvalho Chehab static int ov5693_write_reg_array(struct i2c_client *client,
376ad85094bSMauro Carvalho Chehab 				  const struct ov5693_reg *reglist)
377ad85094bSMauro Carvalho Chehab {
378ad85094bSMauro Carvalho Chehab 	const struct ov5693_reg *next = reglist;
379ad85094bSMauro Carvalho Chehab 	struct ov5693_write_ctrl ctrl;
380ad85094bSMauro Carvalho Chehab 	int err;
381ad85094bSMauro Carvalho Chehab 
382ad85094bSMauro Carvalho Chehab 	ctrl.index = 0;
383ad85094bSMauro Carvalho Chehab 	for (; next->type != OV5693_TOK_TERM; next++) {
384ad85094bSMauro Carvalho Chehab 		switch (next->type & OV5693_TOK_MASK) {
385ad85094bSMauro Carvalho Chehab 		case OV5693_TOK_DELAY:
386ad85094bSMauro Carvalho Chehab 			err = __ov5693_flush_reg_array(client, &ctrl);
387ad85094bSMauro Carvalho Chehab 			if (err)
388ad85094bSMauro Carvalho Chehab 				return err;
389ad85094bSMauro Carvalho Chehab 			msleep(next->val);
390ad85094bSMauro Carvalho Chehab 			break;
391ad85094bSMauro Carvalho Chehab 		default:
392ad85094bSMauro Carvalho Chehab 			/*
393ad85094bSMauro Carvalho Chehab 			 * If next address is not consecutive, data needs to be
394ad85094bSMauro Carvalho Chehab 			 * flushed before proceed.
395ad85094bSMauro Carvalho Chehab 			 */
396ad85094bSMauro Carvalho Chehab 			if (!__ov5693_write_reg_is_consecutive(client, &ctrl,
397ad85094bSMauro Carvalho Chehab 								next)) {
398ad85094bSMauro Carvalho Chehab 				err = __ov5693_flush_reg_array(client, &ctrl);
399ad85094bSMauro Carvalho Chehab 				if (err)
400ad85094bSMauro Carvalho Chehab 					return err;
401ad85094bSMauro Carvalho Chehab 			}
402ad85094bSMauro Carvalho Chehab 			err = __ov5693_buf_reg_array(client, &ctrl, next);
403ad85094bSMauro Carvalho Chehab 			if (err) {
404ad85094bSMauro Carvalho Chehab 				dev_err(&client->dev,
405ad85094bSMauro Carvalho Chehab 					"%s: write error, aborted\n",
406ad85094bSMauro Carvalho Chehab 					__func__);
407ad85094bSMauro Carvalho Chehab 				return err;
408ad85094bSMauro Carvalho Chehab 			}
409ad85094bSMauro Carvalho Chehab 			break;
410ad85094bSMauro Carvalho Chehab 		}
411ad85094bSMauro Carvalho Chehab 	}
412ad85094bSMauro Carvalho Chehab 
413ad85094bSMauro Carvalho Chehab 	return __ov5693_flush_reg_array(client, &ctrl);
414ad85094bSMauro Carvalho Chehab }
415bdfe0bebSMauro Carvalho Chehab 
416ad85094bSMauro Carvalho Chehab static int ov5693_g_focal(struct v4l2_subdev *sd, s32 *val)
417ad85094bSMauro Carvalho Chehab {
418ad85094bSMauro Carvalho Chehab 	*val = (OV5693_FOCAL_LENGTH_NUM << 16) | OV5693_FOCAL_LENGTH_DEM;
419ad85094bSMauro Carvalho Chehab 	return 0;
420ad85094bSMauro Carvalho Chehab }
421ad85094bSMauro Carvalho Chehab 
422ad85094bSMauro Carvalho Chehab static int ov5693_g_fnumber(struct v4l2_subdev *sd, s32 *val)
423ad85094bSMauro Carvalho Chehab {
424ad85094bSMauro Carvalho Chehab 	/*const f number for imx*/
425ad85094bSMauro Carvalho Chehab 	*val = (OV5693_F_NUMBER_DEFAULT_NUM << 16) | OV5693_F_NUMBER_DEM;
426ad85094bSMauro Carvalho Chehab 	return 0;
427ad85094bSMauro Carvalho Chehab }
428ad85094bSMauro Carvalho Chehab 
429ad85094bSMauro Carvalho Chehab static int ov5693_g_fnumber_range(struct v4l2_subdev *sd, s32 *val)
430ad85094bSMauro Carvalho Chehab {
431ad85094bSMauro Carvalho Chehab 	*val = (OV5693_F_NUMBER_DEFAULT_NUM << 24) |
432ad85094bSMauro Carvalho Chehab 		(OV5693_F_NUMBER_DEM << 16) |
433ad85094bSMauro Carvalho Chehab 		(OV5693_F_NUMBER_DEFAULT_NUM << 8) | OV5693_F_NUMBER_DEM;
434ad85094bSMauro Carvalho Chehab 	return 0;
435ad85094bSMauro Carvalho Chehab }
436ad85094bSMauro Carvalho Chehab 
437ad85094bSMauro Carvalho Chehab static int ov5693_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val)
438ad85094bSMauro Carvalho Chehab {
439ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
440ad85094bSMauro Carvalho Chehab 
441ad85094bSMauro Carvalho Chehab 	*val = ov5693_res[dev->fmt_idx].bin_factor_x;
442ad85094bSMauro Carvalho Chehab 
443ad85094bSMauro Carvalho Chehab 	return 0;
444ad85094bSMauro Carvalho Chehab }
445ad85094bSMauro Carvalho Chehab 
446ad85094bSMauro Carvalho Chehab static int ov5693_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val)
447ad85094bSMauro Carvalho Chehab {
448ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
449ad85094bSMauro Carvalho Chehab 
450ad85094bSMauro Carvalho Chehab 	*val = ov5693_res[dev->fmt_idx].bin_factor_y;
451ad85094bSMauro Carvalho Chehab 
452ad85094bSMauro Carvalho Chehab 	return 0;
453ad85094bSMauro Carvalho Chehab }
454ad85094bSMauro Carvalho Chehab 
455ad85094bSMauro Carvalho Chehab static int ov5693_get_intg_factor(struct i2c_client *client,
456ad85094bSMauro Carvalho Chehab 				struct camera_mipi_info *info,
457ad85094bSMauro Carvalho Chehab 				const struct ov5693_resolution *res)
458ad85094bSMauro Carvalho Chehab {
459ad85094bSMauro Carvalho Chehab 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
460ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
461ad85094bSMauro Carvalho Chehab 	struct atomisp_sensor_mode_data *buf = &info->data;
462ad85094bSMauro Carvalho Chehab 	unsigned int pix_clk_freq_hz;
463ad85094bSMauro Carvalho Chehab 	u16 reg_val;
464ad85094bSMauro Carvalho Chehab 	int ret;
465ad85094bSMauro Carvalho Chehab 
466bdfe0bebSMauro Carvalho Chehab 	if (!info)
467ad85094bSMauro Carvalho Chehab 		return -EINVAL;
468ad85094bSMauro Carvalho Chehab 
469ad85094bSMauro Carvalho Chehab 	/* pixel clock */
470ad85094bSMauro Carvalho Chehab 	pix_clk_freq_hz = res->pix_clk_freq * 1000000;
471ad85094bSMauro Carvalho Chehab 
472ad85094bSMauro Carvalho Chehab 	dev->vt_pix_clk_freq_mhz = pix_clk_freq_hz;
473ad85094bSMauro Carvalho Chehab 	buf->vt_pix_clk_freq_mhz = pix_clk_freq_hz;
474ad85094bSMauro Carvalho Chehab 
475ad85094bSMauro Carvalho Chehab 	/* get integration time */
476ad85094bSMauro Carvalho Chehab 	buf->coarse_integration_time_min = OV5693_COARSE_INTG_TIME_MIN;
477ad85094bSMauro Carvalho Chehab 	buf->coarse_integration_time_max_margin =
478ad85094bSMauro Carvalho Chehab 					OV5693_COARSE_INTG_TIME_MAX_MARGIN;
479ad85094bSMauro Carvalho Chehab 
480ad85094bSMauro Carvalho Chehab 	buf->fine_integration_time_min = OV5693_FINE_INTG_TIME_MIN;
481ad85094bSMauro Carvalho Chehab 	buf->fine_integration_time_max_margin =
482ad85094bSMauro Carvalho Chehab 					OV5693_FINE_INTG_TIME_MAX_MARGIN;
483ad85094bSMauro Carvalho Chehab 
484ad85094bSMauro Carvalho Chehab 	buf->fine_integration_time_def = OV5693_FINE_INTG_TIME_MIN;
485ad85094bSMauro Carvalho Chehab 	buf->frame_length_lines = res->lines_per_frame;
486ad85094bSMauro Carvalho Chehab 	buf->line_length_pck = res->pixels_per_line;
487ad85094bSMauro Carvalho Chehab 	buf->read_mode = res->bin_mode;
488ad85094bSMauro Carvalho Chehab 
489ad85094bSMauro Carvalho Chehab 	/* get the cropping and output resolution to ISP for this mode. */
490ad85094bSMauro Carvalho Chehab 	ret =  ov5693_read_reg(client, OV5693_16BIT,
491ad85094bSMauro Carvalho Chehab 					OV5693_HORIZONTAL_START_H, &reg_val);
492ad85094bSMauro Carvalho Chehab 	if (ret)
493ad85094bSMauro Carvalho Chehab 		return ret;
494ad85094bSMauro Carvalho Chehab 	buf->crop_horizontal_start = reg_val;
495ad85094bSMauro Carvalho Chehab 
496ad85094bSMauro Carvalho Chehab 	ret =  ov5693_read_reg(client, OV5693_16BIT,
497ad85094bSMauro Carvalho Chehab 					OV5693_VERTICAL_START_H, &reg_val);
498ad85094bSMauro Carvalho Chehab 	if (ret)
499ad85094bSMauro Carvalho Chehab 		return ret;
500ad85094bSMauro Carvalho Chehab 	buf->crop_vertical_start = reg_val;
501ad85094bSMauro Carvalho Chehab 
502ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_16BIT,
503ad85094bSMauro Carvalho Chehab 					OV5693_HORIZONTAL_END_H, &reg_val);
504ad85094bSMauro Carvalho Chehab 	if (ret)
505ad85094bSMauro Carvalho Chehab 		return ret;
506ad85094bSMauro Carvalho Chehab 	buf->crop_horizontal_end = reg_val;
507ad85094bSMauro Carvalho Chehab 
508ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_16BIT,
509ad85094bSMauro Carvalho Chehab 					OV5693_VERTICAL_END_H, &reg_val);
510ad85094bSMauro Carvalho Chehab 	if (ret)
511ad85094bSMauro Carvalho Chehab 		return ret;
512ad85094bSMauro Carvalho Chehab 	buf->crop_vertical_end = reg_val;
513ad85094bSMauro Carvalho Chehab 
514ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_16BIT,
515ad85094bSMauro Carvalho Chehab 				OV5693_HORIZONTAL_OUTPUT_SIZE_H, &reg_val);
516ad85094bSMauro Carvalho Chehab 	if (ret)
517ad85094bSMauro Carvalho Chehab 		return ret;
518ad85094bSMauro Carvalho Chehab 	buf->output_width = reg_val;
519ad85094bSMauro Carvalho Chehab 
520ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_16BIT,
521ad85094bSMauro Carvalho Chehab 				OV5693_VERTICAL_OUTPUT_SIZE_H, &reg_val);
522ad85094bSMauro Carvalho Chehab 	if (ret)
523ad85094bSMauro Carvalho Chehab 		return ret;
524ad85094bSMauro Carvalho Chehab 	buf->output_height = reg_val;
525ad85094bSMauro Carvalho Chehab 
526ad85094bSMauro Carvalho Chehab 	buf->binning_factor_x = res->bin_factor_x ?
527ad85094bSMauro Carvalho Chehab 					res->bin_factor_x : 1;
528ad85094bSMauro Carvalho Chehab 	buf->binning_factor_y = res->bin_factor_y ?
529ad85094bSMauro Carvalho Chehab 					res->bin_factor_y : 1;
530ad85094bSMauro Carvalho Chehab 	return 0;
531ad85094bSMauro Carvalho Chehab }
532ad85094bSMauro Carvalho Chehab 
533ad85094bSMauro Carvalho Chehab static long __ov5693_set_exposure(struct v4l2_subdev *sd, int coarse_itg,
534ad85094bSMauro Carvalho Chehab 				 int gain, int digitgain)
535ad85094bSMauro Carvalho Chehab 
536ad85094bSMauro Carvalho Chehab {
537ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
538ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
539ad85094bSMauro Carvalho Chehab 	u16 vts, hts;
540ad85094bSMauro Carvalho Chehab 	int ret, exp_val;
541ad85094bSMauro Carvalho Chehab 
542ad85094bSMauro Carvalho Chehab 	hts = ov5693_res[dev->fmt_idx].pixels_per_line;
543ad85094bSMauro Carvalho Chehab 	vts = ov5693_res[dev->fmt_idx].lines_per_frame;
544ad85094bSMauro Carvalho Chehab 	/*
545ad85094bSMauro Carvalho Chehab 	 * If coarse_itg is larger than 1<<15, can not write to reg directly.
546ad85094bSMauro Carvalho Chehab 	 * The way is to write coarse_itg/2 to the reg, meanwhile write 2*hts
547ad85094bSMauro Carvalho Chehab 	 * to the reg.
548ad85094bSMauro Carvalho Chehab 	 */
549ad85094bSMauro Carvalho Chehab 	if (coarse_itg > (1 << 15)) {
550ad85094bSMauro Carvalho Chehab 		hts = hts * 2;
551ad85094bSMauro Carvalho Chehab 		coarse_itg = (int)coarse_itg / 2;
552ad85094bSMauro Carvalho Chehab 	}
553ad85094bSMauro Carvalho Chehab 	/* group hold */
554ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
555ad85094bSMauro Carvalho Chehab 				OV5693_GROUP_ACCESS, 0x00);
556ad85094bSMauro Carvalho Chehab 	if (ret) {
557ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
558ad85094bSMauro Carvalho Chehab 			__func__, OV5693_GROUP_ACCESS);
559ad85094bSMauro Carvalho Chehab 		return ret;
560ad85094bSMauro Carvalho Chehab 	}
561ad85094bSMauro Carvalho Chehab 
562ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
563ad85094bSMauro Carvalho Chehab 				OV5693_TIMING_HTS_H, (hts >> 8) & 0xFF);
564ad85094bSMauro Carvalho Chehab 	if (ret) {
565ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
566ad85094bSMauro Carvalho Chehab 			__func__, OV5693_TIMING_HTS_H);
567ad85094bSMauro Carvalho Chehab 		return ret;
568ad85094bSMauro Carvalho Chehab 	}
569ad85094bSMauro Carvalho Chehab 
570ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
571ad85094bSMauro Carvalho Chehab 				OV5693_TIMING_HTS_L, hts & 0xFF);
572ad85094bSMauro Carvalho Chehab 	if (ret) {
573ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
574ad85094bSMauro Carvalho Chehab 			__func__, OV5693_TIMING_HTS_L);
575ad85094bSMauro Carvalho Chehab 		return ret;
576ad85094bSMauro Carvalho Chehab 	}
577ad85094bSMauro Carvalho Chehab 	/* Increase the VTS to match exposure + MARGIN */
578ad85094bSMauro Carvalho Chehab 	if (coarse_itg > vts - OV5693_INTEGRATION_TIME_MARGIN)
579ad85094bSMauro Carvalho Chehab 		vts = (u16)coarse_itg + OV5693_INTEGRATION_TIME_MARGIN;
580ad85094bSMauro Carvalho Chehab 
581ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
582ad85094bSMauro Carvalho Chehab 				OV5693_TIMING_VTS_H, (vts >> 8) & 0xFF);
583ad85094bSMauro Carvalho Chehab 	if (ret) {
584ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
585ad85094bSMauro Carvalho Chehab 			__func__, OV5693_TIMING_VTS_H);
586ad85094bSMauro Carvalho Chehab 		return ret;
587ad85094bSMauro Carvalho Chehab 	}
588ad85094bSMauro Carvalho Chehab 
589ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
590ad85094bSMauro Carvalho Chehab 					OV5693_TIMING_VTS_L, vts & 0xFF);
591ad85094bSMauro Carvalho Chehab 	if (ret) {
592ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
593ad85094bSMauro Carvalho Chehab 			__func__, OV5693_TIMING_VTS_L);
594ad85094bSMauro Carvalho Chehab 		return ret;
595ad85094bSMauro Carvalho Chehab 	}
596ad85094bSMauro Carvalho Chehab 
597ad85094bSMauro Carvalho Chehab 	/* set exposure */
598ad85094bSMauro Carvalho Chehab 
599ad85094bSMauro Carvalho Chehab 	/* Lower four bit should be 0*/
600ad85094bSMauro Carvalho Chehab 	exp_val = coarse_itg << 4;
601ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
602ad85094bSMauro Carvalho Chehab 			       OV5693_EXPOSURE_L, exp_val & 0xFF);
603ad85094bSMauro Carvalho Chehab 	if (ret) {
604ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
605ad85094bSMauro Carvalho Chehab 			__func__, OV5693_EXPOSURE_L);
606ad85094bSMauro Carvalho Chehab 		return ret;
607ad85094bSMauro Carvalho Chehab 	}
608ad85094bSMauro Carvalho Chehab 
609ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
610ad85094bSMauro Carvalho Chehab 			       OV5693_EXPOSURE_M, (exp_val >> 8) & 0xFF);
611ad85094bSMauro Carvalho Chehab 	if (ret) {
612ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
613ad85094bSMauro Carvalho Chehab 			__func__, OV5693_EXPOSURE_M);
614ad85094bSMauro Carvalho Chehab 		return ret;
615ad85094bSMauro Carvalho Chehab 	}
616ad85094bSMauro Carvalho Chehab 
617ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
618ad85094bSMauro Carvalho Chehab 			       OV5693_EXPOSURE_H, (exp_val >> 16) & 0x0F);
619ad85094bSMauro Carvalho Chehab 	if (ret) {
620ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
621ad85094bSMauro Carvalho Chehab 			__func__, OV5693_EXPOSURE_H);
622ad85094bSMauro Carvalho Chehab 		return ret;
623ad85094bSMauro Carvalho Chehab 	}
624ad85094bSMauro Carvalho Chehab 
625ad85094bSMauro Carvalho Chehab 	/* Analog gain */
626ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
627ad85094bSMauro Carvalho Chehab 				OV5693_AGC_L, gain & 0xff);
628ad85094bSMauro Carvalho Chehab 	if (ret) {
629ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
630ad85094bSMauro Carvalho Chehab 			__func__, OV5693_AGC_L);
631ad85094bSMauro Carvalho Chehab 		return ret;
632ad85094bSMauro Carvalho Chehab 	}
633ad85094bSMauro Carvalho Chehab 
634ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
635ad85094bSMauro Carvalho Chehab 				OV5693_AGC_H, (gain >> 8) & 0xff);
636ad85094bSMauro Carvalho Chehab 	if (ret) {
637ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: write %x error, aborted\n",
638ad85094bSMauro Carvalho Chehab 			__func__, OV5693_AGC_H);
639ad85094bSMauro Carvalho Chehab 		return ret;
640ad85094bSMauro Carvalho Chehab 	}
641ad85094bSMauro Carvalho Chehab 
642ad85094bSMauro Carvalho Chehab 	/* Digital gain */
643ad85094bSMauro Carvalho Chehab 	if (digitgain) {
644ad85094bSMauro Carvalho Chehab 		ret = ov5693_write_reg(client, OV5693_16BIT,
645ad85094bSMauro Carvalho Chehab 				OV5693_MWB_RED_GAIN_H, digitgain);
646ad85094bSMauro Carvalho Chehab 		if (ret) {
647ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev, "%s: write %x error, aborted\n",
648ad85094bSMauro Carvalho Chehab 				__func__, OV5693_MWB_RED_GAIN_H);
649ad85094bSMauro Carvalho Chehab 			return ret;
650ad85094bSMauro Carvalho Chehab 		}
651ad85094bSMauro Carvalho Chehab 
652ad85094bSMauro Carvalho Chehab 		ret = ov5693_write_reg(client, OV5693_16BIT,
653ad85094bSMauro Carvalho Chehab 				OV5693_MWB_GREEN_GAIN_H, digitgain);
654ad85094bSMauro Carvalho Chehab 		if (ret) {
655ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev, "%s: write %x error, aborted\n",
656ad85094bSMauro Carvalho Chehab 				__func__, OV5693_MWB_RED_GAIN_H);
657ad85094bSMauro Carvalho Chehab 			return ret;
658ad85094bSMauro Carvalho Chehab 		}
659ad85094bSMauro Carvalho Chehab 
660ad85094bSMauro Carvalho Chehab 		ret = ov5693_write_reg(client, OV5693_16BIT,
661ad85094bSMauro Carvalho Chehab 				OV5693_MWB_BLUE_GAIN_H, digitgain);
662ad85094bSMauro Carvalho Chehab 		if (ret) {
663ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev, "%s: write %x error, aborted\n",
664ad85094bSMauro Carvalho Chehab 				__func__, OV5693_MWB_RED_GAIN_H);
665ad85094bSMauro Carvalho Chehab 			return ret;
666ad85094bSMauro Carvalho Chehab 		}
667ad85094bSMauro Carvalho Chehab 	}
668ad85094bSMauro Carvalho Chehab 
669ad85094bSMauro Carvalho Chehab 	/* End group */
670ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
671ad85094bSMauro Carvalho Chehab 				OV5693_GROUP_ACCESS, 0x10);
672ad85094bSMauro Carvalho Chehab 	if (ret)
673ad85094bSMauro Carvalho Chehab 		return ret;
674ad85094bSMauro Carvalho Chehab 
675ad85094bSMauro Carvalho Chehab 	/* Delay launch group */
676ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
677ad85094bSMauro Carvalho Chehab 				OV5693_GROUP_ACCESS, 0xa0);
678ad85094bSMauro Carvalho Chehab 	if (ret)
679ad85094bSMauro Carvalho Chehab 		return ret;
680ad85094bSMauro Carvalho Chehab 	return ret;
681ad85094bSMauro Carvalho Chehab }
682ad85094bSMauro Carvalho Chehab 
683ad85094bSMauro Carvalho Chehab static int ov5693_set_exposure(struct v4l2_subdev *sd, int exposure,
684ad85094bSMauro Carvalho Chehab 	int gain, int digitgain)
685ad85094bSMauro Carvalho Chehab {
686ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
687ad85094bSMauro Carvalho Chehab 	int ret;
688ad85094bSMauro Carvalho Chehab 
689ad85094bSMauro Carvalho Chehab 	mutex_lock(&dev->input_lock);
690ad85094bSMauro Carvalho Chehab 	ret = __ov5693_set_exposure(sd, exposure, gain, digitgain);
691ad85094bSMauro Carvalho Chehab 	mutex_unlock(&dev->input_lock);
692ad85094bSMauro Carvalho Chehab 
693ad85094bSMauro Carvalho Chehab 	return ret;
694ad85094bSMauro Carvalho Chehab }
695ad85094bSMauro Carvalho Chehab 
696ad85094bSMauro Carvalho Chehab static long ov5693_s_exposure(struct v4l2_subdev *sd,
697ad85094bSMauro Carvalho Chehab 			       struct atomisp_exposure *exposure)
698ad85094bSMauro Carvalho Chehab {
699ad85094bSMauro Carvalho Chehab 	u16 coarse_itg = exposure->integration_time[0];
700ad85094bSMauro Carvalho Chehab 	u16 analog_gain = exposure->gain[0];
701ad85094bSMauro Carvalho Chehab 	u16 digital_gain = exposure->gain[1];
702ad85094bSMauro Carvalho Chehab 
703ad85094bSMauro Carvalho Chehab 	/* we should not accept the invalid value below */
704ad85094bSMauro Carvalho Chehab 	if (analog_gain == 0) {
705ad85094bSMauro Carvalho Chehab 		struct i2c_client *client = v4l2_get_subdevdata(sd);
706ad85094bSMauro Carvalho Chehab 
707ad85094bSMauro Carvalho Chehab 		v4l2_err(client, "%s: invalid value\n", __func__);
708ad85094bSMauro Carvalho Chehab 		return -EINVAL;
709ad85094bSMauro Carvalho Chehab 	}
710ad85094bSMauro Carvalho Chehab 	return ov5693_set_exposure(sd, coarse_itg, analog_gain, digital_gain);
711ad85094bSMauro Carvalho Chehab }
712ad85094bSMauro Carvalho Chehab 
713ad85094bSMauro Carvalho Chehab static int ov5693_read_otp_reg_array(struct i2c_client *client, u16 size,
714ad85094bSMauro Carvalho Chehab 				     u16 addr, u8 *buf)
715ad85094bSMauro Carvalho Chehab {
716ad85094bSMauro Carvalho Chehab 	u16 index;
717ad85094bSMauro Carvalho Chehab 	int ret;
718ad85094bSMauro Carvalho Chehab 	u16 *pVal = NULL;
719ad85094bSMauro Carvalho Chehab 
720ad85094bSMauro Carvalho Chehab 	for (index = 0; index <= size; index++) {
721ad85094bSMauro Carvalho Chehab 		pVal = (u16 *)(buf + index);
722ad85094bSMauro Carvalho Chehab 		ret =
723ad85094bSMauro Carvalho Chehab 			ov5693_read_reg(client, OV5693_8BIT, addr + index,
724ad85094bSMauro Carvalho Chehab 				    pVal);
725ad85094bSMauro Carvalho Chehab 		if (ret)
726ad85094bSMauro Carvalho Chehab 			return ret;
727ad85094bSMauro Carvalho Chehab 	}
728ad85094bSMauro Carvalho Chehab 
729ad85094bSMauro Carvalho Chehab 	return 0;
730ad85094bSMauro Carvalho Chehab }
731ad85094bSMauro Carvalho Chehab 
732ad85094bSMauro Carvalho Chehab static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
733ad85094bSMauro Carvalho Chehab {
734ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
735ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
736ad85094bSMauro Carvalho Chehab 	int ret;
737ad85094bSMauro Carvalho Chehab 	int i;
738ad85094bSMauro Carvalho Chehab 	u8 *b = buf;
739ad85094bSMauro Carvalho Chehab 
740ad85094bSMauro Carvalho Chehab 	dev->otp_size = 0;
741ad85094bSMauro Carvalho Chehab 	for (i = 1; i < OV5693_OTP_BANK_MAX; i++) {
742ad85094bSMauro Carvalho Chehab 		/*set bank NO and OTP read mode. */
743ad85094bSMauro Carvalho Chehab 		ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_OTP_BANK_REG, (i | 0xc0));	//[7:6] 2'b11 [5:0] bank no
744ad85094bSMauro Carvalho Chehab 		if (ret) {
745ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev, "failed to prepare OTP page\n");
746ad85094bSMauro Carvalho Chehab 			return ret;
747ad85094bSMauro Carvalho Chehab 		}
748ad85094bSMauro Carvalho Chehab 		//pr_debug("write 0x%x->0x%x\n",OV5693_OTP_BANK_REG,(i|0xc0));
749ad85094bSMauro Carvalho Chehab 
750ad85094bSMauro Carvalho Chehab 		/*enable read */
751ad85094bSMauro Carvalho Chehab 		ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_OTP_READ_REG, OV5693_OTP_MODE_READ);	// enable :1
752ad85094bSMauro Carvalho Chehab 		if (ret) {
753ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev,
754ad85094bSMauro Carvalho Chehab 				"failed to set OTP reading mode page");
755ad85094bSMauro Carvalho Chehab 			return ret;
756ad85094bSMauro Carvalho Chehab 		}
757ad85094bSMauro Carvalho Chehab 		//pr_debug("write 0x%x->0x%x\n",OV5693_OTP_READ_REG,OV5693_OTP_MODE_READ);
758ad85094bSMauro Carvalho Chehab 
759ad85094bSMauro Carvalho Chehab 		/* Reading the OTP data array */
760ad85094bSMauro Carvalho Chehab 		ret = ov5693_read_otp_reg_array(client, OV5693_OTP_BANK_SIZE,
761ad85094bSMauro Carvalho Chehab 						OV5693_OTP_START_ADDR,
762ad85094bSMauro Carvalho Chehab 						b);
763ad85094bSMauro Carvalho Chehab 		if (ret) {
764ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev, "failed to read OTP data\n");
765ad85094bSMauro Carvalho Chehab 			return ret;
766ad85094bSMauro Carvalho Chehab 		}
767ad85094bSMauro Carvalho Chehab 
768ad85094bSMauro Carvalho Chehab 		//pr_debug("BANK[%2d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i, *b, *(b+1), *(b+2), *(b+3), *(b+4), *(b+5), *(b+6), *(b+7), *(b+8), *(b+9), *(b+10), *(b+11), *(b+12), *(b+13), *(b+14), *(b+15));
769ad85094bSMauro Carvalho Chehab 
770ad85094bSMauro Carvalho Chehab 		//Intel OTP map, try to read 320byts first.
771ad85094bSMauro Carvalho Chehab 		if (i == 21) {
772ad85094bSMauro Carvalho Chehab 			if ((*b) == 0) {
773ad85094bSMauro Carvalho Chehab 				dev->otp_size = 320;
774ad85094bSMauro Carvalho Chehab 				break;
775ad85094bSMauro Carvalho Chehab 			} else {
776ad85094bSMauro Carvalho Chehab 				b = buf;
777ad85094bSMauro Carvalho Chehab 				continue;
778ad85094bSMauro Carvalho Chehab 			}
779ad85094bSMauro Carvalho Chehab 		} else if (i == 24) {		//if the first 320bytes data doesn't not exist, try to read the next 32bytes data.
780ad85094bSMauro Carvalho Chehab 			if ((*b) == 0) {
781ad85094bSMauro Carvalho Chehab 				dev->otp_size = 32;
782ad85094bSMauro Carvalho Chehab 				break;
783ad85094bSMauro Carvalho Chehab 			} else {
784ad85094bSMauro Carvalho Chehab 				b = buf;
785ad85094bSMauro Carvalho Chehab 				continue;
786ad85094bSMauro Carvalho Chehab 			}
787ad85094bSMauro Carvalho Chehab 		} else if (i == 27) {		//if the prvious 32bytes data doesn't exist, try to read the next 32bytes data again.
788ad85094bSMauro Carvalho Chehab 			if ((*b) == 0) {
789ad85094bSMauro Carvalho Chehab 				dev->otp_size = 32;
790ad85094bSMauro Carvalho Chehab 				break;
791ad85094bSMauro Carvalho Chehab 			} else {
792ad85094bSMauro Carvalho Chehab 				dev->otp_size = 0;	// no OTP data.
793ad85094bSMauro Carvalho Chehab 				break;
794ad85094bSMauro Carvalho Chehab 			}
795ad85094bSMauro Carvalho Chehab 		}
796ad85094bSMauro Carvalho Chehab 
797ad85094bSMauro Carvalho Chehab 		b = b + OV5693_OTP_BANK_SIZE;
798ad85094bSMauro Carvalho Chehab 	}
799ad85094bSMauro Carvalho Chehab 	return 0;
800ad85094bSMauro Carvalho Chehab }
801ad85094bSMauro Carvalho Chehab 
802ad85094bSMauro Carvalho Chehab /*
803ad85094bSMauro Carvalho Chehab  * Read otp data and store it into a kmalloced buffer.
804ad85094bSMauro Carvalho Chehab  * The caller must kfree the buffer when no more needed.
805ad85094bSMauro Carvalho Chehab  * @size: set to the size of the returned otp data.
806ad85094bSMauro Carvalho Chehab  */
807ad85094bSMauro Carvalho Chehab static void *ov5693_otp_read(struct v4l2_subdev *sd)
808ad85094bSMauro Carvalho Chehab {
809ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
810ad85094bSMauro Carvalho Chehab 	u8 *buf;
811ad85094bSMauro Carvalho Chehab 	int ret;
812ad85094bSMauro Carvalho Chehab 
813ad85094bSMauro Carvalho Chehab 	buf = devm_kzalloc(&client->dev, (OV5693_OTP_DATA_SIZE + 16), GFP_KERNEL);
814ad85094bSMauro Carvalho Chehab 	if (!buf)
815ad85094bSMauro Carvalho Chehab 		return ERR_PTR(-ENOMEM);
816ad85094bSMauro Carvalho Chehab 
817ad85094bSMauro Carvalho Chehab 	//otp valid after mipi on and sw stream on
818ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_FRAME_OFF_NUM, 0x00);
819ad85094bSMauro Carvalho Chehab 
820ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
821ad85094bSMauro Carvalho Chehab 			       OV5693_SW_STREAM, OV5693_START_STREAMING);
822ad85094bSMauro Carvalho Chehab 
823ad85094bSMauro Carvalho Chehab 	ret = __ov5693_otp_read(sd, buf);
824ad85094bSMauro Carvalho Chehab 
825ad85094bSMauro Carvalho Chehab 	//mipi off and sw stream off after otp read
826ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_FRAME_OFF_NUM, 0x0f);
827ad85094bSMauro Carvalho Chehab 
828ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
829ad85094bSMauro Carvalho Chehab 			       OV5693_SW_STREAM, OV5693_STOP_STREAMING);
830ad85094bSMauro Carvalho Chehab 
831ad85094bSMauro Carvalho Chehab 	/* Driver has failed to find valid data */
832ad85094bSMauro Carvalho Chehab 	if (ret) {
833ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "sensor found no valid OTP data\n");
834ad85094bSMauro Carvalho Chehab 		return ERR_PTR(ret);
835ad85094bSMauro Carvalho Chehab 	}
836ad85094bSMauro Carvalho Chehab 
837ad85094bSMauro Carvalho Chehab 	return buf;
838ad85094bSMauro Carvalho Chehab }
839ad85094bSMauro Carvalho Chehab 
840ad85094bSMauro Carvalho Chehab static int ov5693_g_priv_int_data(struct v4l2_subdev *sd,
841ad85094bSMauro Carvalho Chehab 				  struct v4l2_private_int_data *priv)
842ad85094bSMauro Carvalho Chehab {
843ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
844ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
845ad85094bSMauro Carvalho Chehab 	u8 __user *to = priv->data;
846ad85094bSMauro Carvalho Chehab 	u32 read_size = priv->size;
847ad85094bSMauro Carvalho Chehab 	int ret;
848ad85094bSMauro Carvalho Chehab 
849ad85094bSMauro Carvalho Chehab 	/* No need to copy data if size is 0 */
850ad85094bSMauro Carvalho Chehab 	if (!read_size)
851ad85094bSMauro Carvalho Chehab 		goto out;
852ad85094bSMauro Carvalho Chehab 
853ad85094bSMauro Carvalho Chehab 	if (IS_ERR(dev->otp_data)) {
854ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "OTP data not available");
855ad85094bSMauro Carvalho Chehab 		return PTR_ERR(dev->otp_data);
856ad85094bSMauro Carvalho Chehab 	}
857ad85094bSMauro Carvalho Chehab 
858ad85094bSMauro Carvalho Chehab 	/* Correct read_size value only if bigger than maximum */
859ad85094bSMauro Carvalho Chehab 	if (read_size > OV5693_OTP_DATA_SIZE)
860ad85094bSMauro Carvalho Chehab 		read_size = OV5693_OTP_DATA_SIZE;
861ad85094bSMauro Carvalho Chehab 
862ad85094bSMauro Carvalho Chehab 	ret = copy_to_user(to, dev->otp_data, read_size);
863ad85094bSMauro Carvalho Chehab 	if (ret) {
864ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "%s: failed to copy OTP data to user\n",
865ad85094bSMauro Carvalho Chehab 			__func__);
866ad85094bSMauro Carvalho Chehab 		return -EFAULT;
867ad85094bSMauro Carvalho Chehab 	}
868ad85094bSMauro Carvalho Chehab 
869ad85094bSMauro Carvalho Chehab 	pr_debug("%s read_size:%d\n", __func__, read_size);
870ad85094bSMauro Carvalho Chehab 
871ad85094bSMauro Carvalho Chehab out:
872ad85094bSMauro Carvalho Chehab 	/* Return correct size */
873ad85094bSMauro Carvalho Chehab 	priv->size = dev->otp_size;
874ad85094bSMauro Carvalho Chehab 
875ad85094bSMauro Carvalho Chehab 	return 0;
876ad85094bSMauro Carvalho Chehab }
877ad85094bSMauro Carvalho Chehab 
878ad85094bSMauro Carvalho Chehab static long ov5693_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
879ad85094bSMauro Carvalho Chehab {
880ad85094bSMauro Carvalho Chehab 	switch (cmd) {
881ad85094bSMauro Carvalho Chehab 	case ATOMISP_IOC_S_EXPOSURE:
882ad85094bSMauro Carvalho Chehab 		return ov5693_s_exposure(sd, arg);
883ad85094bSMauro Carvalho Chehab 	case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA:
884ad85094bSMauro Carvalho Chehab 		return ov5693_g_priv_int_data(sd, arg);
885ad85094bSMauro Carvalho Chehab 	default:
886ad85094bSMauro Carvalho Chehab 		return -EINVAL;
887ad85094bSMauro Carvalho Chehab 	}
888ad85094bSMauro Carvalho Chehab 	return 0;
889ad85094bSMauro Carvalho Chehab }
890ad85094bSMauro Carvalho Chehab 
891ad85094bSMauro Carvalho Chehab /*
892ad85094bSMauro Carvalho Chehab  * This returns the exposure time being used. This should only be used
893ad85094bSMauro Carvalho Chehab  * for filling in EXIF data, not for actual image processing.
894ad85094bSMauro Carvalho Chehab  */
895ad85094bSMauro Carvalho Chehab static int ov5693_q_exposure(struct v4l2_subdev *sd, s32 *value)
896ad85094bSMauro Carvalho Chehab {
897ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
898ad85094bSMauro Carvalho Chehab 	u16 reg_v, reg_v2;
899ad85094bSMauro Carvalho Chehab 	int ret;
900ad85094bSMauro Carvalho Chehab 
901ad85094bSMauro Carvalho Chehab 	/* get exposure */
902ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_8BIT,
903ad85094bSMauro Carvalho Chehab 					OV5693_EXPOSURE_L,
904ad85094bSMauro Carvalho Chehab 					&reg_v);
905ad85094bSMauro Carvalho Chehab 	if (ret)
906ad85094bSMauro Carvalho Chehab 		goto err;
907ad85094bSMauro Carvalho Chehab 
908ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_8BIT,
909ad85094bSMauro Carvalho Chehab 					OV5693_EXPOSURE_M,
910ad85094bSMauro Carvalho Chehab 					&reg_v2);
911ad85094bSMauro Carvalho Chehab 	if (ret)
912ad85094bSMauro Carvalho Chehab 		goto err;
913ad85094bSMauro Carvalho Chehab 
914ad85094bSMauro Carvalho Chehab 	reg_v += reg_v2 << 8;
915ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_8BIT,
916ad85094bSMauro Carvalho Chehab 					OV5693_EXPOSURE_H,
917ad85094bSMauro Carvalho Chehab 					&reg_v2);
918ad85094bSMauro Carvalho Chehab 	if (ret)
919ad85094bSMauro Carvalho Chehab 		goto err;
920ad85094bSMauro Carvalho Chehab 
921ad85094bSMauro Carvalho Chehab 	*value = reg_v + (((u32)reg_v2 << 16));
922ad85094bSMauro Carvalho Chehab err:
923ad85094bSMauro Carvalho Chehab 	return ret;
924ad85094bSMauro Carvalho Chehab }
925ad85094bSMauro Carvalho Chehab 
926ad85094bSMauro Carvalho Chehab static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val)
927ad85094bSMauro Carvalho Chehab {
928ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
929ad85094bSMauro Carvalho Chehab 	int ret = -EINVAL;
930ad85094bSMauro Carvalho Chehab 	u8 vcm_code;
931ad85094bSMauro Carvalho Chehab 
932ad85094bSMauro Carvalho Chehab 	ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code);
933ad85094bSMauro Carvalho Chehab 	if (ret)
934ad85094bSMauro Carvalho Chehab 		return ret;
935ad85094bSMauro Carvalho Chehab 
936ad85094bSMauro Carvalho Chehab 	/* set reg VCM_CODE_MSB Bit[1:0] */
937ad85094bSMauro Carvalho Chehab 	vcm_code = (vcm_code & VCM_CODE_MSB_MASK) |
938ad85094bSMauro Carvalho Chehab 		((val >> 8) & ~VCM_CODE_MSB_MASK);
939ad85094bSMauro Carvalho Chehab 	ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, vcm_code);
940ad85094bSMauro Carvalho Chehab 	if (ret)
941ad85094bSMauro Carvalho Chehab 		return ret;
942ad85094bSMauro Carvalho Chehab 
943ad85094bSMauro Carvalho Chehab 	/* set reg VCM_CODE_LSB Bit[7:0] */
944ad85094bSMauro Carvalho Chehab 	ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_LSB, (val & 0xff));
945ad85094bSMauro Carvalho Chehab 	if (ret)
946ad85094bSMauro Carvalho Chehab 		return ret;
947ad85094bSMauro Carvalho Chehab 
948ad85094bSMauro Carvalho Chehab 	/* set required vcm move time */
949ad85094bSMauro Carvalho Chehab 	vcm_code = AD5823_RESONANCE_PERIOD / AD5823_RESONANCE_COEF
950ad85094bSMauro Carvalho Chehab 		- AD5823_HIGH_FREQ_RANGE;
951ad85094bSMauro Carvalho Chehab 	ret = ad5823_i2c_write(client, AD5823_REG_VCM_MOVE_TIME, vcm_code);
952ad85094bSMauro Carvalho Chehab 
953ad85094bSMauro Carvalho Chehab 	return ret;
954ad85094bSMauro Carvalho Chehab }
955ad85094bSMauro Carvalho Chehab 
956ad85094bSMauro Carvalho Chehab static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
957ad85094bSMauro Carvalho Chehab {
958ad85094bSMauro Carvalho Chehab 	value = min(value, AD5823_MAX_FOCUS_POS);
959ad85094bSMauro Carvalho Chehab 	return ad5823_t_focus_vcm(sd, value);
960ad85094bSMauro Carvalho Chehab }
961ad85094bSMauro Carvalho Chehab 
962ad85094bSMauro Carvalho Chehab static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
963ad85094bSMauro Carvalho Chehab {
964ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
965ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
966ad85094bSMauro Carvalho Chehab 	int ret = 0;
967ad85094bSMauro Carvalho Chehab 
968ad85094bSMauro Carvalho Chehab 	dev_dbg(&client->dev, "%s: FOCUS_POS: 0x%x\n", __func__, value);
969ad85094bSMauro Carvalho Chehab 	value = clamp(value, 0, OV5693_VCM_MAX_FOCUS_POS);
970ad85094bSMauro Carvalho Chehab 	if (dev->vcm == VCM_DW9714) {
971ad85094bSMauro Carvalho Chehab 		if (dev->vcm_update) {
972ad85094bSMauro Carvalho Chehab 			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_OFF);
973ad85094bSMauro Carvalho Chehab 			if (ret)
974ad85094bSMauro Carvalho Chehab 				return ret;
975ad85094bSMauro Carvalho Chehab 			ret = vcm_dw_i2c_write(client, DIRECT_VCM);
976ad85094bSMauro Carvalho Chehab 			if (ret)
977ad85094bSMauro Carvalho Chehab 				return ret;
978ad85094bSMauro Carvalho Chehab 			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_ON);
979ad85094bSMauro Carvalho Chehab 			if (ret)
980ad85094bSMauro Carvalho Chehab 				return ret;
981ad85094bSMauro Carvalho Chehab 			dev->vcm_update = false;
982ad85094bSMauro Carvalho Chehab 		}
983ad85094bSMauro Carvalho Chehab 		ret = vcm_dw_i2c_write(client,
984ad85094bSMauro Carvalho Chehab 				       vcm_val(value, VCM_DEFAULT_S));
985ad85094bSMauro Carvalho Chehab 	} else if (dev->vcm == VCM_AD5823) {
986ad85094bSMauro Carvalho Chehab 		ad5823_t_focus_abs(sd, value);
987ad85094bSMauro Carvalho Chehab 	}
988ad85094bSMauro Carvalho Chehab 	if (ret == 0) {
989ad85094bSMauro Carvalho Chehab 		dev->number_of_steps = value - dev->focus;
990ad85094bSMauro Carvalho Chehab 		dev->focus = value;
991ad85094bSMauro Carvalho Chehab 		dev->timestamp_t_focus_abs = ktime_get();
992ad85094bSMauro Carvalho Chehab 	} else
993ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev,
994ad85094bSMauro Carvalho Chehab 			"%s: i2c failed. ret %d\n", __func__, ret);
995ad85094bSMauro Carvalho Chehab 
996ad85094bSMauro Carvalho Chehab 	return ret;
997ad85094bSMauro Carvalho Chehab }
998ad85094bSMauro Carvalho Chehab 
999ad85094bSMauro Carvalho Chehab static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
1000ad85094bSMauro Carvalho Chehab {
1001ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1002ad85094bSMauro Carvalho Chehab 
1003ad85094bSMauro Carvalho Chehab 	return ov5693_t_focus_abs(sd, dev->focus + value);
1004ad85094bSMauro Carvalho Chehab }
1005ad85094bSMauro Carvalho Chehab 
1006ad85094bSMauro Carvalho Chehab #define DELAY_PER_STEP_NS	1000000
1007ad85094bSMauro Carvalho Chehab #define DELAY_MAX_PER_STEP_NS	(1000000 * 1023)
1008ad85094bSMauro Carvalho Chehab static int ov5693_q_focus_status(struct v4l2_subdev *sd, s32 *value)
1009ad85094bSMauro Carvalho Chehab {
1010ad85094bSMauro Carvalho Chehab 	u32 status = 0;
1011ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1012ad85094bSMauro Carvalho Chehab 	ktime_t temptime;
1013ad85094bSMauro Carvalho Chehab 	ktime_t timedelay = ns_to_ktime(min_t(u32,
1014ad85094bSMauro Carvalho Chehab 			abs(dev->number_of_steps) * DELAY_PER_STEP_NS,
1015ad85094bSMauro Carvalho Chehab 			DELAY_MAX_PER_STEP_NS));
1016ad85094bSMauro Carvalho Chehab 
1017ad85094bSMauro Carvalho Chehab 	temptime = ktime_sub(ktime_get(), (dev->timestamp_t_focus_abs));
1018ad85094bSMauro Carvalho Chehab 	if (ktime_compare(temptime, timedelay) <= 0) {
1019ad85094bSMauro Carvalho Chehab 		status |= ATOMISP_FOCUS_STATUS_MOVING;
1020ad85094bSMauro Carvalho Chehab 		status |= ATOMISP_FOCUS_HP_IN_PROGRESS;
1021ad85094bSMauro Carvalho Chehab 	} else {
1022ad85094bSMauro Carvalho Chehab 		status |= ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE;
1023ad85094bSMauro Carvalho Chehab 		status |= ATOMISP_FOCUS_HP_COMPLETE;
1024ad85094bSMauro Carvalho Chehab 	}
1025ad85094bSMauro Carvalho Chehab 
1026ad85094bSMauro Carvalho Chehab 	*value = status;
1027ad85094bSMauro Carvalho Chehab 
1028ad85094bSMauro Carvalho Chehab 	return 0;
1029ad85094bSMauro Carvalho Chehab }
1030ad85094bSMauro Carvalho Chehab 
1031ad85094bSMauro Carvalho Chehab static int ov5693_q_focus_abs(struct v4l2_subdev *sd, s32 *value)
1032ad85094bSMauro Carvalho Chehab {
1033ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1034ad85094bSMauro Carvalho Chehab 	s32 val;
1035ad85094bSMauro Carvalho Chehab 
1036ad85094bSMauro Carvalho Chehab 	ov5693_q_focus_status(sd, &val);
1037ad85094bSMauro Carvalho Chehab 
1038ad85094bSMauro Carvalho Chehab 	if (val & ATOMISP_FOCUS_STATUS_MOVING)
1039ad85094bSMauro Carvalho Chehab 		*value  = dev->focus - dev->number_of_steps;
1040ad85094bSMauro Carvalho Chehab 	else
1041ad85094bSMauro Carvalho Chehab 		*value  = dev->focus;
1042ad85094bSMauro Carvalho Chehab 
1043ad85094bSMauro Carvalho Chehab 	return 0;
1044ad85094bSMauro Carvalho Chehab }
1045ad85094bSMauro Carvalho Chehab 
1046ad85094bSMauro Carvalho Chehab static int ov5693_t_vcm_slew(struct v4l2_subdev *sd, s32 value)
1047ad85094bSMauro Carvalho Chehab {
1048ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1049ad85094bSMauro Carvalho Chehab 
1050ad85094bSMauro Carvalho Chehab 	dev->number_of_steps = value;
1051ad85094bSMauro Carvalho Chehab 	dev->vcm_update = true;
1052ad85094bSMauro Carvalho Chehab 	return 0;
1053ad85094bSMauro Carvalho Chehab }
1054ad85094bSMauro Carvalho Chehab 
1055ad85094bSMauro Carvalho Chehab static int ov5693_t_vcm_timing(struct v4l2_subdev *sd, s32 value)
1056ad85094bSMauro Carvalho Chehab {
1057ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1058ad85094bSMauro Carvalho Chehab 
1059ad85094bSMauro Carvalho Chehab 	dev->number_of_steps = value;
1060ad85094bSMauro Carvalho Chehab 	dev->vcm_update = true;
1061ad85094bSMauro Carvalho Chehab 	return 0;
1062ad85094bSMauro Carvalho Chehab }
1063ad85094bSMauro Carvalho Chehab 
1064ad85094bSMauro Carvalho Chehab static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
1065ad85094bSMauro Carvalho Chehab {
1066ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev =
1067ad85094bSMauro Carvalho Chehab 	    container_of(ctrl->handler, struct ov5693_device, ctrl_handler);
1068ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
1069ad85094bSMauro Carvalho Chehab 	int ret = 0;
1070ad85094bSMauro Carvalho Chehab 
1071ad85094bSMauro Carvalho Chehab 	switch (ctrl->id) {
1072ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FOCUS_ABSOLUTE:
1073ad85094bSMauro Carvalho Chehab 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
1074ad85094bSMauro Carvalho Chehab 			__func__, ctrl->val);
1075ad85094bSMauro Carvalho Chehab 		ret = ov5693_t_focus_abs(&dev->sd, ctrl->val);
1076ad85094bSMauro Carvalho Chehab 		break;
1077ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FOCUS_RELATIVE:
1078ad85094bSMauro Carvalho Chehab 		dev_dbg(&client->dev, "%s: CID_FOCUS_RELATIVE:%d.\n",
1079ad85094bSMauro Carvalho Chehab 			__func__, ctrl->val);
1080ad85094bSMauro Carvalho Chehab 		ret = ov5693_t_focus_rel(&dev->sd, ctrl->val);
1081ad85094bSMauro Carvalho Chehab 		break;
1082ad85094bSMauro Carvalho Chehab 	case V4L2_CID_VCM_SLEW:
1083ad85094bSMauro Carvalho Chehab 		ret = ov5693_t_vcm_slew(&dev->sd, ctrl->val);
1084ad85094bSMauro Carvalho Chehab 		break;
1085ad85094bSMauro Carvalho Chehab 	case V4L2_CID_VCM_TIMEING:
1086ad85094bSMauro Carvalho Chehab 		ret = ov5693_t_vcm_timing(&dev->sd, ctrl->val);
1087ad85094bSMauro Carvalho Chehab 		break;
1088ad85094bSMauro Carvalho Chehab 	default:
1089ad85094bSMauro Carvalho Chehab 		ret = -EINVAL;
1090ad85094bSMauro Carvalho Chehab 	}
1091ad85094bSMauro Carvalho Chehab 	return ret;
1092ad85094bSMauro Carvalho Chehab }
1093ad85094bSMauro Carvalho Chehab 
1094ad85094bSMauro Carvalho Chehab static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1095ad85094bSMauro Carvalho Chehab {
1096ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev =
1097ad85094bSMauro Carvalho Chehab 	    container_of(ctrl->handler, struct ov5693_device, ctrl_handler);
1098ad85094bSMauro Carvalho Chehab 	int ret = 0;
1099ad85094bSMauro Carvalho Chehab 
1100ad85094bSMauro Carvalho Chehab 	switch (ctrl->id) {
1101ad85094bSMauro Carvalho Chehab 	case V4L2_CID_EXPOSURE_ABSOLUTE:
1102ad85094bSMauro Carvalho Chehab 		ret = ov5693_q_exposure(&dev->sd, &ctrl->val);
1103ad85094bSMauro Carvalho Chehab 		break;
1104ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FOCAL_ABSOLUTE:
1105ad85094bSMauro Carvalho Chehab 		ret = ov5693_g_focal(&dev->sd, &ctrl->val);
1106ad85094bSMauro Carvalho Chehab 		break;
1107ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FNUMBER_ABSOLUTE:
1108ad85094bSMauro Carvalho Chehab 		ret = ov5693_g_fnumber(&dev->sd, &ctrl->val);
1109ad85094bSMauro Carvalho Chehab 		break;
1110ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FNUMBER_RANGE:
1111ad85094bSMauro Carvalho Chehab 		ret = ov5693_g_fnumber_range(&dev->sd, &ctrl->val);
1112ad85094bSMauro Carvalho Chehab 		break;
1113ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FOCUS_ABSOLUTE:
1114ad85094bSMauro Carvalho Chehab 		ret = ov5693_q_focus_abs(&dev->sd, &ctrl->val);
1115ad85094bSMauro Carvalho Chehab 		break;
1116ad85094bSMauro Carvalho Chehab 	case V4L2_CID_FOCUS_STATUS:
1117ad85094bSMauro Carvalho Chehab 		ret = ov5693_q_focus_status(&dev->sd, &ctrl->val);
1118ad85094bSMauro Carvalho Chehab 		break;
1119ad85094bSMauro Carvalho Chehab 	case V4L2_CID_BIN_FACTOR_HORZ:
1120ad85094bSMauro Carvalho Chehab 		ret = ov5693_g_bin_factor_x(&dev->sd, &ctrl->val);
1121ad85094bSMauro Carvalho Chehab 		break;
1122ad85094bSMauro Carvalho Chehab 	case V4L2_CID_BIN_FACTOR_VERT:
1123ad85094bSMauro Carvalho Chehab 		ret = ov5693_g_bin_factor_y(&dev->sd, &ctrl->val);
1124ad85094bSMauro Carvalho Chehab 		break;
1125ad85094bSMauro Carvalho Chehab 	default:
1126ad85094bSMauro Carvalho Chehab 		ret = -EINVAL;
1127ad85094bSMauro Carvalho Chehab 	}
1128ad85094bSMauro Carvalho Chehab 
1129ad85094bSMauro Carvalho Chehab 	return ret;
1130ad85094bSMauro Carvalho Chehab }
1131ad85094bSMauro Carvalho Chehab 
1132ad85094bSMauro Carvalho Chehab static const struct v4l2_ctrl_ops ctrl_ops = {
1133ad85094bSMauro Carvalho Chehab 	.s_ctrl = ov5693_s_ctrl,
1134ad85094bSMauro Carvalho Chehab 	.g_volatile_ctrl = ov5693_g_volatile_ctrl
1135ad85094bSMauro Carvalho Chehab };
1136ad85094bSMauro Carvalho Chehab 
1137ad85094bSMauro Carvalho Chehab static const struct v4l2_ctrl_config ov5693_controls[] = {
1138ad85094bSMauro Carvalho Chehab 	{
1139ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1140ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_EXPOSURE_ABSOLUTE,
1141ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1142ad85094bSMauro Carvalho Chehab 	 .name = "exposure",
1143ad85094bSMauro Carvalho Chehab 	 .min = 0x0,
1144ad85094bSMauro Carvalho Chehab 	 .max = 0xffff,
1145ad85094bSMauro Carvalho Chehab 	 .step = 0x01,
1146ad85094bSMauro Carvalho Chehab 	 .def = 0x00,
1147ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1148ad85094bSMauro Carvalho Chehab 	 },
1149ad85094bSMauro Carvalho Chehab 	{
1150ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1151ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_FOCAL_ABSOLUTE,
1152ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1153ad85094bSMauro Carvalho Chehab 	 .name = "focal length",
1154ad85094bSMauro Carvalho Chehab 	 .min = OV5693_FOCAL_LENGTH_DEFAULT,
1155ad85094bSMauro Carvalho Chehab 	 .max = OV5693_FOCAL_LENGTH_DEFAULT,
1156ad85094bSMauro Carvalho Chehab 	 .step = 0x01,
1157ad85094bSMauro Carvalho Chehab 	 .def = OV5693_FOCAL_LENGTH_DEFAULT,
1158ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1159ad85094bSMauro Carvalho Chehab 	 },
1160ad85094bSMauro Carvalho Chehab 	{
1161ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1162ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_FNUMBER_ABSOLUTE,
1163ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1164ad85094bSMauro Carvalho Chehab 	 .name = "f-number",
1165ad85094bSMauro Carvalho Chehab 	 .min = OV5693_F_NUMBER_DEFAULT,
1166ad85094bSMauro Carvalho Chehab 	 .max = OV5693_F_NUMBER_DEFAULT,
1167ad85094bSMauro Carvalho Chehab 	 .step = 0x01,
1168ad85094bSMauro Carvalho Chehab 	 .def = OV5693_F_NUMBER_DEFAULT,
1169ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1170ad85094bSMauro Carvalho Chehab 	 },
1171ad85094bSMauro Carvalho Chehab 	{
1172ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1173ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_FNUMBER_RANGE,
1174ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1175ad85094bSMauro Carvalho Chehab 	 .name = "f-number range",
1176ad85094bSMauro Carvalho Chehab 	 .min = OV5693_F_NUMBER_RANGE,
1177ad85094bSMauro Carvalho Chehab 	 .max = OV5693_F_NUMBER_RANGE,
1178ad85094bSMauro Carvalho Chehab 	 .step = 0x01,
1179ad85094bSMauro Carvalho Chehab 	 .def = OV5693_F_NUMBER_RANGE,
1180ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1181ad85094bSMauro Carvalho Chehab 	 },
1182ad85094bSMauro Carvalho Chehab 	{
1183ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1184ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_FOCUS_ABSOLUTE,
1185ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1186ad85094bSMauro Carvalho Chehab 	 .name = "focus move absolute",
1187ad85094bSMauro Carvalho Chehab 	 .min = 0,
1188ad85094bSMauro Carvalho Chehab 	 .max = OV5693_VCM_MAX_FOCUS_POS,
1189ad85094bSMauro Carvalho Chehab 	 .step = 1,
1190ad85094bSMauro Carvalho Chehab 	 .def = 0,
1191ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1192ad85094bSMauro Carvalho Chehab 	 },
1193ad85094bSMauro Carvalho Chehab 	{
1194ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1195ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_FOCUS_RELATIVE,
1196ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1197ad85094bSMauro Carvalho Chehab 	 .name = "focus move relative",
1198ad85094bSMauro Carvalho Chehab 	 .min = OV5693_VCM_MAX_FOCUS_NEG,
1199ad85094bSMauro Carvalho Chehab 	 .max = OV5693_VCM_MAX_FOCUS_POS,
1200ad85094bSMauro Carvalho Chehab 	 .step = 1,
1201ad85094bSMauro Carvalho Chehab 	 .def = 0,
1202ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1203ad85094bSMauro Carvalho Chehab 	 },
1204ad85094bSMauro Carvalho Chehab 	{
1205ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1206ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_FOCUS_STATUS,
1207ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1208ad85094bSMauro Carvalho Chehab 	 .name = "focus status",
1209ad85094bSMauro Carvalho Chehab 	 .min = 0,
1210ad85094bSMauro Carvalho Chehab 	 .max = 100,		/* allow enum to grow in the future */
1211ad85094bSMauro Carvalho Chehab 	 .step = 1,
1212ad85094bSMauro Carvalho Chehab 	 .def = 0,
1213ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1214ad85094bSMauro Carvalho Chehab 	 },
1215ad85094bSMauro Carvalho Chehab 	{
1216ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1217ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_VCM_SLEW,
1218ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1219ad85094bSMauro Carvalho Chehab 	 .name = "vcm slew",
1220ad85094bSMauro Carvalho Chehab 	 .min = 0,
1221ad85094bSMauro Carvalho Chehab 	 .max = OV5693_VCM_SLEW_STEP_MAX,
1222ad85094bSMauro Carvalho Chehab 	 .step = 1,
1223ad85094bSMauro Carvalho Chehab 	 .def = 0,
1224ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1225ad85094bSMauro Carvalho Chehab 	 },
1226ad85094bSMauro Carvalho Chehab 	{
1227ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1228ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_VCM_TIMEING,
1229ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1230ad85094bSMauro Carvalho Chehab 	 .name = "vcm step time",
1231ad85094bSMauro Carvalho Chehab 	 .min = 0,
1232ad85094bSMauro Carvalho Chehab 	 .max = OV5693_VCM_SLEW_TIME_MAX,
1233ad85094bSMauro Carvalho Chehab 	 .step = 1,
1234ad85094bSMauro Carvalho Chehab 	 .def = 0,
1235ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1236ad85094bSMauro Carvalho Chehab 	 },
1237ad85094bSMauro Carvalho Chehab 	{
1238ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1239ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_BIN_FACTOR_HORZ,
1240ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1241ad85094bSMauro Carvalho Chehab 	 .name = "horizontal binning factor",
1242ad85094bSMauro Carvalho Chehab 	 .min = 0,
1243ad85094bSMauro Carvalho Chehab 	 .max = OV5693_BIN_FACTOR_MAX,
1244ad85094bSMauro Carvalho Chehab 	 .step = 1,
1245ad85094bSMauro Carvalho Chehab 	 .def = 0,
1246ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1247ad85094bSMauro Carvalho Chehab 	 },
1248ad85094bSMauro Carvalho Chehab 	{
1249ad85094bSMauro Carvalho Chehab 	 .ops = &ctrl_ops,
1250ad85094bSMauro Carvalho Chehab 	 .id = V4L2_CID_BIN_FACTOR_VERT,
1251ad85094bSMauro Carvalho Chehab 	 .type = V4L2_CTRL_TYPE_INTEGER,
1252ad85094bSMauro Carvalho Chehab 	 .name = "vertical binning factor",
1253ad85094bSMauro Carvalho Chehab 	 .min = 0,
1254ad85094bSMauro Carvalho Chehab 	 .max = OV5693_BIN_FACTOR_MAX,
1255ad85094bSMauro Carvalho Chehab 	 .step = 1,
1256ad85094bSMauro Carvalho Chehab 	 .def = 0,
1257ad85094bSMauro Carvalho Chehab 	 .flags = 0,
1258ad85094bSMauro Carvalho Chehab 	 },
1259ad85094bSMauro Carvalho Chehab };
1260ad85094bSMauro Carvalho Chehab 
1261ad85094bSMauro Carvalho Chehab static int ov5693_init(struct v4l2_subdev *sd)
1262ad85094bSMauro Carvalho Chehab {
1263ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1264ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1265ad85094bSMauro Carvalho Chehab 	int ret;
1266ad85094bSMauro Carvalho Chehab 
1267ad85094bSMauro Carvalho Chehab 	pr_info("%s\n", __func__);
1268ad85094bSMauro Carvalho Chehab 	mutex_lock(&dev->input_lock);
1269ad85094bSMauro Carvalho Chehab 	dev->vcm_update = false;
1270ad85094bSMauro Carvalho Chehab 
1271ad85094bSMauro Carvalho Chehab 	if (dev->vcm == VCM_AD5823) {
1272ad85094bSMauro Carvalho Chehab 		ret = vcm_ad_i2c_wr8(client, 0x01, 0x01); /* vcm init test */
1273ad85094bSMauro Carvalho Chehab 		if (ret)
1274ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev,
1275ad85094bSMauro Carvalho Chehab 				"vcm reset failed\n");
1276ad85094bSMauro Carvalho Chehab 		/*change the mode*/
1277ad85094bSMauro Carvalho Chehab 		ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB,
1278ad85094bSMauro Carvalho Chehab 				       AD5823_RING_CTRL_ENABLE);
1279ad85094bSMauro Carvalho Chehab 		if (ret)
1280ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev,
1281ad85094bSMauro Carvalho Chehab 				"vcm enable ringing failed\n");
1282ad85094bSMauro Carvalho Chehab 		ret = ad5823_i2c_write(client, AD5823_REG_MODE,
1283ad85094bSMauro Carvalho Chehab 					AD5823_ARC_RES1);
1284ad85094bSMauro Carvalho Chehab 		if (ret)
1285ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev,
1286ad85094bSMauro Carvalho Chehab 				"vcm change mode failed\n");
1287ad85094bSMauro Carvalho Chehab 	}
1288ad85094bSMauro Carvalho Chehab 
1289ad85094bSMauro Carvalho Chehab 	/*change initial focus value for ad5823*/
1290ad85094bSMauro Carvalho Chehab 	if (dev->vcm == VCM_AD5823) {
1291ad85094bSMauro Carvalho Chehab 		dev->focus = AD5823_INIT_FOCUS_POS;
1292ad85094bSMauro Carvalho Chehab 		ov5693_t_focus_abs(sd, AD5823_INIT_FOCUS_POS);
1293ad85094bSMauro Carvalho Chehab 	} else {
1294ad85094bSMauro Carvalho Chehab 		dev->focus = 0;
1295ad85094bSMauro Carvalho Chehab 		ov5693_t_focus_abs(sd, 0);
1296ad85094bSMauro Carvalho Chehab 	}
1297ad85094bSMauro Carvalho Chehab 
1298ad85094bSMauro Carvalho Chehab 	mutex_unlock(&dev->input_lock);
1299ad85094bSMauro Carvalho Chehab 
1300ad85094bSMauro Carvalho Chehab 	return 0;
1301ad85094bSMauro Carvalho Chehab }
1302ad85094bSMauro Carvalho Chehab 
1303ad85094bSMauro Carvalho Chehab static int power_ctrl(struct v4l2_subdev *sd, bool flag)
1304ad85094bSMauro Carvalho Chehab {
1305ad85094bSMauro Carvalho Chehab 	int ret;
1306ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1307ad85094bSMauro Carvalho Chehab 
1308ad85094bSMauro Carvalho Chehab 	if (!dev || !dev->platform_data)
1309ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1310ad85094bSMauro Carvalho Chehab 
1311ad85094bSMauro Carvalho Chehab 	/*
1312ad85094bSMauro Carvalho Chehab 	 * This driver assumes "internal DVDD, PWDNB tied to DOVDD".
1313ad85094bSMauro Carvalho Chehab 	 * In this set up only gpio0 (XSHUTDN) should be available
1314ad85094bSMauro Carvalho Chehab 	 * but in some products (for example ECS) gpio1 (PWDNB) is
1315ad85094bSMauro Carvalho Chehab 	 * also available. If gpio1 is available we emulate it being
1316ad85094bSMauro Carvalho Chehab 	 * tied to DOVDD here.
1317ad85094bSMauro Carvalho Chehab 	 */
1318ad85094bSMauro Carvalho Chehab 	if (flag) {
1319ad85094bSMauro Carvalho Chehab 		ret = dev->platform_data->v2p8_ctrl(sd, 1);
1320ad85094bSMauro Carvalho Chehab 		dev->platform_data->gpio1_ctrl(sd, 1);
1321ad85094bSMauro Carvalho Chehab 		if (ret == 0) {
1322ad85094bSMauro Carvalho Chehab 			ret = dev->platform_data->v1p8_ctrl(sd, 1);
1323ad85094bSMauro Carvalho Chehab 			if (ret) {
1324ad85094bSMauro Carvalho Chehab 				dev->platform_data->gpio1_ctrl(sd, 0);
1325ad85094bSMauro Carvalho Chehab 				ret = dev->platform_data->v2p8_ctrl(sd, 0);
1326ad85094bSMauro Carvalho Chehab 			}
1327ad85094bSMauro Carvalho Chehab 		}
1328ad85094bSMauro Carvalho Chehab 	} else {
1329ad85094bSMauro Carvalho Chehab 		dev->platform_data->gpio1_ctrl(sd, 0);
1330ad85094bSMauro Carvalho Chehab 		ret = dev->platform_data->v1p8_ctrl(sd, 0);
1331ad85094bSMauro Carvalho Chehab 		ret |= dev->platform_data->v2p8_ctrl(sd, 0);
1332ad85094bSMauro Carvalho Chehab 	}
1333ad85094bSMauro Carvalho Chehab 
1334ad85094bSMauro Carvalho Chehab 	return ret;
1335ad85094bSMauro Carvalho Chehab }
1336ad85094bSMauro Carvalho Chehab 
1337ad85094bSMauro Carvalho Chehab static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
1338ad85094bSMauro Carvalho Chehab {
1339ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1340ad85094bSMauro Carvalho Chehab 
1341ad85094bSMauro Carvalho Chehab 	if (!dev || !dev->platform_data)
1342ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1343ad85094bSMauro Carvalho Chehab 
1344ad85094bSMauro Carvalho Chehab 	return dev->platform_data->gpio0_ctrl(sd, flag);
1345ad85094bSMauro Carvalho Chehab }
1346ad85094bSMauro Carvalho Chehab 
1347ad85094bSMauro Carvalho Chehab static int __power_up(struct v4l2_subdev *sd)
1348ad85094bSMauro Carvalho Chehab {
1349ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1350ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1351ad85094bSMauro Carvalho Chehab 	int ret;
1352ad85094bSMauro Carvalho Chehab 
1353ad85094bSMauro Carvalho Chehab 	if (!dev->platform_data) {
1354ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev,
1355ad85094bSMauro Carvalho Chehab 			"no camera_sensor_platform_data");
1356ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1357ad85094bSMauro Carvalho Chehab 	}
1358ad85094bSMauro Carvalho Chehab 
1359ad85094bSMauro Carvalho Chehab 	/* power control */
1360ad85094bSMauro Carvalho Chehab 	ret = power_ctrl(sd, 1);
1361ad85094bSMauro Carvalho Chehab 	if (ret)
1362ad85094bSMauro Carvalho Chehab 		goto fail_power;
1363ad85094bSMauro Carvalho Chehab 
1364ad85094bSMauro Carvalho Chehab 	/* according to DS, at least 5ms is needed between DOVDD and PWDN */
1365ad85094bSMauro Carvalho Chehab 	/* add this delay time to 10~11ms*/
1366ad85094bSMauro Carvalho Chehab 	usleep_range(10000, 11000);
1367ad85094bSMauro Carvalho Chehab 
1368ad85094bSMauro Carvalho Chehab 	/* gpio ctrl */
1369ad85094bSMauro Carvalho Chehab 	ret = gpio_ctrl(sd, 1);
1370ad85094bSMauro Carvalho Chehab 	if (ret) {
1371ad85094bSMauro Carvalho Chehab 		ret = gpio_ctrl(sd, 1);
1372ad85094bSMauro Carvalho Chehab 		if (ret)
1373ad85094bSMauro Carvalho Chehab 			goto fail_power;
1374ad85094bSMauro Carvalho Chehab 	}
1375ad85094bSMauro Carvalho Chehab 
1376ad85094bSMauro Carvalho Chehab 	/* flis clock control */
1377ad85094bSMauro Carvalho Chehab 	ret = dev->platform_data->flisclk_ctrl(sd, 1);
1378ad85094bSMauro Carvalho Chehab 	if (ret)
1379ad85094bSMauro Carvalho Chehab 		goto fail_clk;
1380ad85094bSMauro Carvalho Chehab 
1381ad85094bSMauro Carvalho Chehab 	__cci_delay(up_delay);
1382ad85094bSMauro Carvalho Chehab 
1383ad85094bSMauro Carvalho Chehab 	return 0;
1384ad85094bSMauro Carvalho Chehab 
1385ad85094bSMauro Carvalho Chehab fail_clk:
1386ad85094bSMauro Carvalho Chehab 	gpio_ctrl(sd, 0);
1387ad85094bSMauro Carvalho Chehab fail_power:
1388ad85094bSMauro Carvalho Chehab 	power_ctrl(sd, 0);
1389ad85094bSMauro Carvalho Chehab 	dev_err(&client->dev, "sensor power-up failed\n");
1390ad85094bSMauro Carvalho Chehab 
1391ad85094bSMauro Carvalho Chehab 	return ret;
1392ad85094bSMauro Carvalho Chehab }
1393ad85094bSMauro Carvalho Chehab 
1394ad85094bSMauro Carvalho Chehab static int power_down(struct v4l2_subdev *sd)
1395ad85094bSMauro Carvalho Chehab {
1396ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1397ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1398ad85094bSMauro Carvalho Chehab 	int ret = 0;
1399ad85094bSMauro Carvalho Chehab 
1400ad85094bSMauro Carvalho Chehab 	dev->focus = OV5693_INVALID_CONFIG;
1401ad85094bSMauro Carvalho Chehab 	if (!dev->platform_data) {
1402ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev,
1403ad85094bSMauro Carvalho Chehab 			"no camera_sensor_platform_data");
1404ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1405ad85094bSMauro Carvalho Chehab 	}
1406ad85094bSMauro Carvalho Chehab 
1407ad85094bSMauro Carvalho Chehab 	ret = dev->platform_data->flisclk_ctrl(sd, 0);
1408ad85094bSMauro Carvalho Chehab 	if (ret)
1409ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "flisclk failed\n");
1410ad85094bSMauro Carvalho Chehab 
1411ad85094bSMauro Carvalho Chehab 	/* gpio ctrl */
1412ad85094bSMauro Carvalho Chehab 	ret = gpio_ctrl(sd, 0);
1413ad85094bSMauro Carvalho Chehab 	if (ret) {
1414ad85094bSMauro Carvalho Chehab 		ret = gpio_ctrl(sd, 0);
1415ad85094bSMauro Carvalho Chehab 		if (ret)
1416ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev, "gpio failed 2\n");
1417ad85094bSMauro Carvalho Chehab 	}
1418ad85094bSMauro Carvalho Chehab 
1419ad85094bSMauro Carvalho Chehab 	/* power control */
1420ad85094bSMauro Carvalho Chehab 	ret = power_ctrl(sd, 0);
1421ad85094bSMauro Carvalho Chehab 	if (ret)
1422ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "vprog failed.\n");
1423ad85094bSMauro Carvalho Chehab 
1424ad85094bSMauro Carvalho Chehab 	return ret;
1425ad85094bSMauro Carvalho Chehab }
1426ad85094bSMauro Carvalho Chehab 
1427ad85094bSMauro Carvalho Chehab static int power_up(struct v4l2_subdev *sd)
1428ad85094bSMauro Carvalho Chehab {
1429ad85094bSMauro Carvalho Chehab 	static const int retry_count = 4;
1430ad85094bSMauro Carvalho Chehab 	int i, ret;
1431ad85094bSMauro Carvalho Chehab 
1432ad85094bSMauro Carvalho Chehab 	for (i = 0; i < retry_count; i++) {
1433ad85094bSMauro Carvalho Chehab 		ret = __power_up(sd);
1434ad85094bSMauro Carvalho Chehab 		if (!ret)
1435ad85094bSMauro Carvalho Chehab 			return 0;
1436ad85094bSMauro Carvalho Chehab 
1437ad85094bSMauro Carvalho Chehab 		power_down(sd);
1438ad85094bSMauro Carvalho Chehab 	}
1439ad85094bSMauro Carvalho Chehab 	return ret;
1440ad85094bSMauro Carvalho Chehab }
1441ad85094bSMauro Carvalho Chehab 
1442ad85094bSMauro Carvalho Chehab static int ov5693_s_power(struct v4l2_subdev *sd, int on)
1443ad85094bSMauro Carvalho Chehab {
1444ad85094bSMauro Carvalho Chehab 	int ret;
1445ad85094bSMauro Carvalho Chehab 
1446ad85094bSMauro Carvalho Chehab 	pr_info("%s: on %d\n", __func__, on);
1447ad85094bSMauro Carvalho Chehab 	if (on == 0)
1448ad85094bSMauro Carvalho Chehab 		return power_down(sd);
1449ad85094bSMauro Carvalho Chehab 	else {
1450ad85094bSMauro Carvalho Chehab 		ret = power_up(sd);
1451ad85094bSMauro Carvalho Chehab 		if (!ret) {
1452ad85094bSMauro Carvalho Chehab 			ret = ov5693_init(sd);
1453ad85094bSMauro Carvalho Chehab 			/* restore settings */
1454ad85094bSMauro Carvalho Chehab 			ov5693_res = ov5693_res_preview;
1455ad85094bSMauro Carvalho Chehab 			N_RES = N_RES_PREVIEW;
1456ad85094bSMauro Carvalho Chehab 		}
1457ad85094bSMauro Carvalho Chehab 	}
1458ad85094bSMauro Carvalho Chehab 	return ret;
1459ad85094bSMauro Carvalho Chehab }
1460ad85094bSMauro Carvalho Chehab 
1461ad85094bSMauro Carvalho Chehab /*
1462ad85094bSMauro Carvalho Chehab  * distance - calculate the distance
1463ad85094bSMauro Carvalho Chehab  * @res: resolution
1464ad85094bSMauro Carvalho Chehab  * @w: width
1465ad85094bSMauro Carvalho Chehab  * @h: height
1466ad85094bSMauro Carvalho Chehab  *
1467ad85094bSMauro Carvalho Chehab  * Get the gap between res_w/res_h and w/h.
1468ad85094bSMauro Carvalho Chehab  * distance = (res_w/res_h - w/h) / (w/h) * 8192
1469ad85094bSMauro Carvalho Chehab  * res->width/height smaller than w/h wouldn't be considered.
1470ad85094bSMauro Carvalho Chehab  * The gap of ratio larger than 1/8 wouldn't be considered.
1471ad85094bSMauro Carvalho Chehab  * Returns the value of gap or -1 if fail.
1472ad85094bSMauro Carvalho Chehab  */
1473ad85094bSMauro Carvalho Chehab #define LARGEST_ALLOWED_RATIO_MISMATCH 1024
1474ad85094bSMauro Carvalho Chehab static int distance(struct ov5693_resolution *res, u32 w, u32 h)
1475ad85094bSMauro Carvalho Chehab {
1476ad85094bSMauro Carvalho Chehab 	int ratio;
1477ad85094bSMauro Carvalho Chehab 	int distance;
1478ad85094bSMauro Carvalho Chehab 
1479ad85094bSMauro Carvalho Chehab 	if (w == 0 || h == 0 ||
1480ad85094bSMauro Carvalho Chehab 	    res->width < w || res->height < h)
1481ad85094bSMauro Carvalho Chehab 		return -1;
1482ad85094bSMauro Carvalho Chehab 
1483ad85094bSMauro Carvalho Chehab 	ratio = res->width << 13;
1484ad85094bSMauro Carvalho Chehab 	ratio /= w;
1485ad85094bSMauro Carvalho Chehab 	ratio *= h;
1486ad85094bSMauro Carvalho Chehab 	ratio /= res->height;
1487ad85094bSMauro Carvalho Chehab 
1488ad85094bSMauro Carvalho Chehab 	distance = abs(ratio - 8192);
1489ad85094bSMauro Carvalho Chehab 
1490ad85094bSMauro Carvalho Chehab 	if (distance > LARGEST_ALLOWED_RATIO_MISMATCH)
1491ad85094bSMauro Carvalho Chehab 		return -1;
1492ad85094bSMauro Carvalho Chehab 
1493ad85094bSMauro Carvalho Chehab 	return distance;
1494ad85094bSMauro Carvalho Chehab }
1495ad85094bSMauro Carvalho Chehab 
1496ad85094bSMauro Carvalho Chehab /* Return the nearest higher resolution index
1497ad85094bSMauro Carvalho Chehab  * Firstly try to find the approximate aspect ratio resolution
1498ad85094bSMauro Carvalho Chehab  * If we find multiple same AR resolutions, choose the
1499ad85094bSMauro Carvalho Chehab  * minimal size.
1500ad85094bSMauro Carvalho Chehab  */
1501ad85094bSMauro Carvalho Chehab static int nearest_resolution_index(int w, int h)
1502ad85094bSMauro Carvalho Chehab {
1503ad85094bSMauro Carvalho Chehab 	int i;
1504ad85094bSMauro Carvalho Chehab 	int idx = -1;
1505ad85094bSMauro Carvalho Chehab 	int dist;
1506ad85094bSMauro Carvalho Chehab 	int min_dist = INT_MAX;
1507ad85094bSMauro Carvalho Chehab 	int min_res_w = INT_MAX;
1508ad85094bSMauro Carvalho Chehab 	struct ov5693_resolution *tmp_res = NULL;
1509ad85094bSMauro Carvalho Chehab 
1510ad85094bSMauro Carvalho Chehab 	for (i = 0; i < N_RES; i++) {
1511ad85094bSMauro Carvalho Chehab 		tmp_res = &ov5693_res[i];
1512ad85094bSMauro Carvalho Chehab 		dist = distance(tmp_res, w, h);
1513ad85094bSMauro Carvalho Chehab 		if (dist == -1)
1514ad85094bSMauro Carvalho Chehab 			continue;
1515ad85094bSMauro Carvalho Chehab 		if (dist < min_dist) {
1516ad85094bSMauro Carvalho Chehab 			min_dist = dist;
1517ad85094bSMauro Carvalho Chehab 			idx = i;
1518ad85094bSMauro Carvalho Chehab 			min_res_w = ov5693_res[i].width;
1519ad85094bSMauro Carvalho Chehab 			continue;
1520ad85094bSMauro Carvalho Chehab 		}
1521ad85094bSMauro Carvalho Chehab 		if (dist == min_dist && ov5693_res[i].width < min_res_w)
1522ad85094bSMauro Carvalho Chehab 			idx = i;
1523ad85094bSMauro Carvalho Chehab 	}
1524ad85094bSMauro Carvalho Chehab 
1525ad85094bSMauro Carvalho Chehab 	return idx;
1526ad85094bSMauro Carvalho Chehab }
1527ad85094bSMauro Carvalho Chehab 
1528ad85094bSMauro Carvalho Chehab static int get_resolution_index(int w, int h)
1529ad85094bSMauro Carvalho Chehab {
1530ad85094bSMauro Carvalho Chehab 	int i;
1531ad85094bSMauro Carvalho Chehab 
1532ad85094bSMauro Carvalho Chehab 	for (i = 0; i < N_RES; i++) {
1533ad85094bSMauro Carvalho Chehab 		if (w != ov5693_res[i].width)
1534ad85094bSMauro Carvalho Chehab 			continue;
1535ad85094bSMauro Carvalho Chehab 		if (h != ov5693_res[i].height)
1536ad85094bSMauro Carvalho Chehab 			continue;
1537ad85094bSMauro Carvalho Chehab 
1538ad85094bSMauro Carvalho Chehab 		return i;
1539ad85094bSMauro Carvalho Chehab 	}
1540ad85094bSMauro Carvalho Chehab 
1541ad85094bSMauro Carvalho Chehab 	return -1;
1542ad85094bSMauro Carvalho Chehab }
1543ad85094bSMauro Carvalho Chehab 
1544ad85094bSMauro Carvalho Chehab /* TODO: remove it. */
1545ad85094bSMauro Carvalho Chehab static int startup(struct v4l2_subdev *sd)
1546ad85094bSMauro Carvalho Chehab {
1547ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1548ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1549ad85094bSMauro Carvalho Chehab 	int ret = 0;
1550ad85094bSMauro Carvalho Chehab 
1551ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT,
1552ad85094bSMauro Carvalho Chehab 					OV5693_SW_RESET, 0x01);
1553ad85094bSMauro Carvalho Chehab 	if (ret) {
1554ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 reset err.\n");
1555ad85094bSMauro Carvalho Chehab 		return ret;
1556ad85094bSMauro Carvalho Chehab 	}
1557ad85094bSMauro Carvalho Chehab 
1558ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg_array(client, ov5693_global_setting);
1559ad85094bSMauro Carvalho Chehab 	if (ret) {
1560ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 write register err.\n");
1561ad85094bSMauro Carvalho Chehab 		return ret;
1562ad85094bSMauro Carvalho Chehab 	}
1563ad85094bSMauro Carvalho Chehab 
1564ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg_array(client, ov5693_res[dev->fmt_idx].regs);
1565ad85094bSMauro Carvalho Chehab 	if (ret) {
1566ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 write register err.\n");
1567ad85094bSMauro Carvalho Chehab 		return ret;
1568ad85094bSMauro Carvalho Chehab 	}
1569ad85094bSMauro Carvalho Chehab 
1570ad85094bSMauro Carvalho Chehab 	return ret;
1571ad85094bSMauro Carvalho Chehab }
1572ad85094bSMauro Carvalho Chehab 
1573ad85094bSMauro Carvalho Chehab static int ov5693_set_fmt(struct v4l2_subdev *sd,
1574ad85094bSMauro Carvalho Chehab 			  struct v4l2_subdev_pad_config *cfg,
1575ad85094bSMauro Carvalho Chehab 			  struct v4l2_subdev_format *format)
1576ad85094bSMauro Carvalho Chehab {
1577ad85094bSMauro Carvalho Chehab 	struct v4l2_mbus_framefmt *fmt = &format->format;
1578ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1579ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1580ad85094bSMauro Carvalho Chehab 	struct camera_mipi_info *ov5693_info = NULL;
1581ad85094bSMauro Carvalho Chehab 	int ret = 0;
1582ad85094bSMauro Carvalho Chehab 	int idx;
1583ad85094bSMauro Carvalho Chehab 
1584ad85094bSMauro Carvalho Chehab 	if (format->pad)
1585ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1586ad85094bSMauro Carvalho Chehab 	if (!fmt)
1587ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1588ad85094bSMauro Carvalho Chehab 	ov5693_info = v4l2_get_subdev_hostdata(sd);
1589bdfe0bebSMauro Carvalho Chehab 	if (!ov5693_info)
1590ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1591ad85094bSMauro Carvalho Chehab 
1592ad85094bSMauro Carvalho Chehab 	mutex_lock(&dev->input_lock);
1593ad85094bSMauro Carvalho Chehab 	idx = nearest_resolution_index(fmt->width, fmt->height);
1594ad85094bSMauro Carvalho Chehab 	if (idx == -1) {
1595ad85094bSMauro Carvalho Chehab 		/* return the largest resolution */
1596ad85094bSMauro Carvalho Chehab 		fmt->width = ov5693_res[N_RES - 1].width;
1597ad85094bSMauro Carvalho Chehab 		fmt->height = ov5693_res[N_RES - 1].height;
1598ad85094bSMauro Carvalho Chehab 	} else {
1599ad85094bSMauro Carvalho Chehab 		fmt->width = ov5693_res[idx].width;
1600ad85094bSMauro Carvalho Chehab 		fmt->height = ov5693_res[idx].height;
1601ad85094bSMauro Carvalho Chehab 	}
1602ad85094bSMauro Carvalho Chehab 
1603ad85094bSMauro Carvalho Chehab 	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
1604ad85094bSMauro Carvalho Chehab 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
1605ad85094bSMauro Carvalho Chehab 		cfg->try_fmt = *fmt;
1606ad85094bSMauro Carvalho Chehab 		mutex_unlock(&dev->input_lock);
1607ad85094bSMauro Carvalho Chehab 		return 0;
1608ad85094bSMauro Carvalho Chehab 	}
1609ad85094bSMauro Carvalho Chehab 
1610ad85094bSMauro Carvalho Chehab 	dev->fmt_idx = get_resolution_index(fmt->width, fmt->height);
1611ad85094bSMauro Carvalho Chehab 	if (dev->fmt_idx == -1) {
1612ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "get resolution fail\n");
1613ad85094bSMauro Carvalho Chehab 		mutex_unlock(&dev->input_lock);
1614ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1615ad85094bSMauro Carvalho Chehab 	}
1616ad85094bSMauro Carvalho Chehab 
1617ad85094bSMauro Carvalho Chehab 	ret = startup(sd);
1618ad85094bSMauro Carvalho Chehab 	if (ret) {
1619ad85094bSMauro Carvalho Chehab 		int i = 0;
1620ad85094bSMauro Carvalho Chehab 
1621ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 startup err, retry to power up\n");
1622ad85094bSMauro Carvalho Chehab 		for (i = 0; i < OV5693_POWER_UP_RETRY_NUM; i++) {
1623ad85094bSMauro Carvalho Chehab 			dev_err(&client->dev,
1624ad85094bSMauro Carvalho Chehab 				"ov5693 retry to power up %d/%d times, result: ",
1625ad85094bSMauro Carvalho Chehab 				i + 1, OV5693_POWER_UP_RETRY_NUM);
1626ad85094bSMauro Carvalho Chehab 			power_down(sd);
1627ad85094bSMauro Carvalho Chehab 			ret = power_up(sd);
1628ad85094bSMauro Carvalho Chehab 			if (!ret) {
1629ad85094bSMauro Carvalho Chehab 				mutex_unlock(&dev->input_lock);
1630ad85094bSMauro Carvalho Chehab 				ov5693_init(sd);
1631ad85094bSMauro Carvalho Chehab 				mutex_lock(&dev->input_lock);
1632ad85094bSMauro Carvalho Chehab 			} else {
1633ad85094bSMauro Carvalho Chehab 				dev_err(&client->dev, "power up failed, continue\n");
1634ad85094bSMauro Carvalho Chehab 				continue;
1635ad85094bSMauro Carvalho Chehab 			}
1636ad85094bSMauro Carvalho Chehab 			ret = startup(sd);
1637ad85094bSMauro Carvalho Chehab 			if (ret) {
1638ad85094bSMauro Carvalho Chehab 				dev_err(&client->dev, " startup FAILED!\n");
1639ad85094bSMauro Carvalho Chehab 			} else {
1640ad85094bSMauro Carvalho Chehab 				dev_err(&client->dev, " startup SUCCESS!\n");
1641ad85094bSMauro Carvalho Chehab 				break;
1642ad85094bSMauro Carvalho Chehab 			}
1643ad85094bSMauro Carvalho Chehab 		}
1644ad85094bSMauro Carvalho Chehab 	}
1645ad85094bSMauro Carvalho Chehab 
1646ad85094bSMauro Carvalho Chehab 	/*
1647ad85094bSMauro Carvalho Chehab 	 * After sensor settings are set to HW, sometimes stream is started.
1648ad85094bSMauro Carvalho Chehab 	 * This would cause ISP timeout because ISP is not ready to receive
1649ad85094bSMauro Carvalho Chehab 	 * data yet. So add stop streaming here.
1650ad85094bSMauro Carvalho Chehab 	 */
1651ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
1652ad85094bSMauro Carvalho Chehab 				OV5693_STOP_STREAMING);
1653ad85094bSMauro Carvalho Chehab 	if (ret)
1654ad85094bSMauro Carvalho Chehab 		dev_warn(&client->dev, "ov5693 stream off err\n");
1655ad85094bSMauro Carvalho Chehab 
1656ad85094bSMauro Carvalho Chehab 	ret = ov5693_get_intg_factor(client, ov5693_info,
1657ad85094bSMauro Carvalho Chehab 					&ov5693_res[dev->fmt_idx]);
1658ad85094bSMauro Carvalho Chehab 	if (ret) {
1659ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "failed to get integration_factor\n");
1660ad85094bSMauro Carvalho Chehab 		goto err;
1661ad85094bSMauro Carvalho Chehab 	}
1662ad85094bSMauro Carvalho Chehab 
1663ad85094bSMauro Carvalho Chehab 	ov5693_info->metadata_width = fmt->width * 10 / 8;
1664ad85094bSMauro Carvalho Chehab 	ov5693_info->metadata_height = 1;
1665ad85094bSMauro Carvalho Chehab 	ov5693_info->metadata_effective_width = &ov5693_embedded_effective_size;
1666ad85094bSMauro Carvalho Chehab 
1667ad85094bSMauro Carvalho Chehab err:
1668ad85094bSMauro Carvalho Chehab 	mutex_unlock(&dev->input_lock);
1669ad85094bSMauro Carvalho Chehab 	return ret;
1670ad85094bSMauro Carvalho Chehab }
1671bdfe0bebSMauro Carvalho Chehab 
1672ad85094bSMauro Carvalho Chehab static int ov5693_get_fmt(struct v4l2_subdev *sd,
1673ad85094bSMauro Carvalho Chehab 			  struct v4l2_subdev_pad_config *cfg,
1674ad85094bSMauro Carvalho Chehab 			  struct v4l2_subdev_format *format)
1675ad85094bSMauro Carvalho Chehab {
1676ad85094bSMauro Carvalho Chehab 	struct v4l2_mbus_framefmt *fmt = &format->format;
1677ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1678ad85094bSMauro Carvalho Chehab 
1679ad85094bSMauro Carvalho Chehab 	if (format->pad)
1680ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1681ad85094bSMauro Carvalho Chehab 
1682ad85094bSMauro Carvalho Chehab 	if (!fmt)
1683ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1684ad85094bSMauro Carvalho Chehab 
1685ad85094bSMauro Carvalho Chehab 	fmt->width = ov5693_res[dev->fmt_idx].width;
1686ad85094bSMauro Carvalho Chehab 	fmt->height = ov5693_res[dev->fmt_idx].height;
1687ad85094bSMauro Carvalho Chehab 	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
1688ad85094bSMauro Carvalho Chehab 
1689ad85094bSMauro Carvalho Chehab 	return 0;
1690ad85094bSMauro Carvalho Chehab }
1691ad85094bSMauro Carvalho Chehab 
1692ad85094bSMauro Carvalho Chehab static int ov5693_detect(struct i2c_client *client)
1693ad85094bSMauro Carvalho Chehab {
1694ad85094bSMauro Carvalho Chehab 	struct i2c_adapter *adapter = client->adapter;
1695ad85094bSMauro Carvalho Chehab 	u16 high, low;
1696ad85094bSMauro Carvalho Chehab 	int ret;
1697ad85094bSMauro Carvalho Chehab 	u16 id;
1698ad85094bSMauro Carvalho Chehab 	u8 revision;
1699ad85094bSMauro Carvalho Chehab 
1700ad85094bSMauro Carvalho Chehab 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
1701ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1702ad85094bSMauro Carvalho Chehab 
1703ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_8BIT,
1704ad85094bSMauro Carvalho Chehab 					OV5693_SC_CMMN_CHIP_ID_H, &high);
1705ad85094bSMauro Carvalho Chehab 	if (ret) {
1706ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "sensor_id_high = 0x%x\n", high);
1707ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1708ad85094bSMauro Carvalho Chehab 	}
1709ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_8BIT,
1710ad85094bSMauro Carvalho Chehab 					OV5693_SC_CMMN_CHIP_ID_L, &low);
1711ad85094bSMauro Carvalho Chehab 	id = ((((u16)high) << 8) | (u16)low);
1712ad85094bSMauro Carvalho Chehab 
1713ad85094bSMauro Carvalho Chehab 	if (id != OV5693_ID) {
1714ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "sensor ID error 0x%x\n", id);
1715ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1716ad85094bSMauro Carvalho Chehab 	}
1717ad85094bSMauro Carvalho Chehab 
1718ad85094bSMauro Carvalho Chehab 	ret = ov5693_read_reg(client, OV5693_8BIT,
1719ad85094bSMauro Carvalho Chehab 					OV5693_SC_CMMN_SUB_ID, &high);
1720ad85094bSMauro Carvalho Chehab 	revision = (u8)high & 0x0f;
1721ad85094bSMauro Carvalho Chehab 
1722ad85094bSMauro Carvalho Chehab 	dev_dbg(&client->dev, "sensor_revision = 0x%x\n", revision);
1723ad85094bSMauro Carvalho Chehab 	dev_dbg(&client->dev, "detect ov5693 success\n");
1724ad85094bSMauro Carvalho Chehab 	return 0;
1725ad85094bSMauro Carvalho Chehab }
1726ad85094bSMauro Carvalho Chehab 
1727ad85094bSMauro Carvalho Chehab static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
1728ad85094bSMauro Carvalho Chehab {
1729ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1730ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1731ad85094bSMauro Carvalho Chehab 	int ret;
1732ad85094bSMauro Carvalho Chehab 
1733ad85094bSMauro Carvalho Chehab 	mutex_lock(&dev->input_lock);
1734ad85094bSMauro Carvalho Chehab 
1735ad85094bSMauro Carvalho Chehab 	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
1736ad85094bSMauro Carvalho Chehab 				enable ? OV5693_START_STREAMING :
1737ad85094bSMauro Carvalho Chehab 				OV5693_STOP_STREAMING);
1738ad85094bSMauro Carvalho Chehab 
1739ad85094bSMauro Carvalho Chehab 	mutex_unlock(&dev->input_lock);
1740ad85094bSMauro Carvalho Chehab 
1741ad85094bSMauro Carvalho Chehab 	return ret;
1742ad85094bSMauro Carvalho Chehab }
1743ad85094bSMauro Carvalho Chehab 
1744ad85094bSMauro Carvalho Chehab static int ov5693_s_config(struct v4l2_subdev *sd,
1745ad85094bSMauro Carvalho Chehab 			   int irq, void *platform_data)
1746ad85094bSMauro Carvalho Chehab {
1747ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1748ad85094bSMauro Carvalho Chehab 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1749ad85094bSMauro Carvalho Chehab 	int ret = 0;
1750ad85094bSMauro Carvalho Chehab 
1751bdfe0bebSMauro Carvalho Chehab 	if (!platform_data)
1752ad85094bSMauro Carvalho Chehab 		return -ENODEV;
1753ad85094bSMauro Carvalho Chehab 
1754ad85094bSMauro Carvalho Chehab 	dev->platform_data =
1755ad85094bSMauro Carvalho Chehab 		(struct camera_sensor_platform_data *)platform_data;
1756ad85094bSMauro Carvalho Chehab 
1757ad85094bSMauro Carvalho Chehab 	mutex_lock(&dev->input_lock);
1758ad85094bSMauro Carvalho Chehab 	/* power off the module, then power on it in future
1759ad85094bSMauro Carvalho Chehab 	 * as first power on by board may not fulfill the
1760ad85094bSMauro Carvalho Chehab 	 * power on sequqence needed by the module
1761ad85094bSMauro Carvalho Chehab 	 */
1762ad85094bSMauro Carvalho Chehab 	ret = power_down(sd);
1763ad85094bSMauro Carvalho Chehab 	if (ret) {
1764ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 power-off err.\n");
1765ad85094bSMauro Carvalho Chehab 		goto fail_power_off;
1766ad85094bSMauro Carvalho Chehab 	}
1767ad85094bSMauro Carvalho Chehab 
1768ad85094bSMauro Carvalho Chehab 	ret = power_up(sd);
1769ad85094bSMauro Carvalho Chehab 	if (ret) {
1770ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 power-up err.\n");
1771ad85094bSMauro Carvalho Chehab 		goto fail_power_on;
1772ad85094bSMauro Carvalho Chehab 	}
1773ad85094bSMauro Carvalho Chehab 
1774ad85094bSMauro Carvalho Chehab 	if (!dev->vcm)
1775ad85094bSMauro Carvalho Chehab 		dev->vcm = vcm_detect(client);
1776ad85094bSMauro Carvalho Chehab 
1777ad85094bSMauro Carvalho Chehab 	ret = dev->platform_data->csi_cfg(sd, 1);
1778ad85094bSMauro Carvalho Chehab 	if (ret)
1779ad85094bSMauro Carvalho Chehab 		goto fail_csi_cfg;
1780ad85094bSMauro Carvalho Chehab 
1781ad85094bSMauro Carvalho Chehab 	/* config & detect sensor */
1782ad85094bSMauro Carvalho Chehab 	ret = ov5693_detect(client);
1783ad85094bSMauro Carvalho Chehab 	if (ret) {
1784ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693_detect err s_config.\n");
1785ad85094bSMauro Carvalho Chehab 		goto fail_csi_cfg;
1786ad85094bSMauro Carvalho Chehab 	}
1787ad85094bSMauro Carvalho Chehab 
1788ad85094bSMauro Carvalho Chehab 	dev->otp_data = ov5693_otp_read(sd);
1789ad85094bSMauro Carvalho Chehab 
1790ad85094bSMauro Carvalho Chehab 	/* turn off sensor, after probed */
1791ad85094bSMauro Carvalho Chehab 	ret = power_down(sd);
1792ad85094bSMauro Carvalho Chehab 	if (ret) {
1793ad85094bSMauro Carvalho Chehab 		dev_err(&client->dev, "ov5693 power-off err.\n");
1794ad85094bSMauro Carvalho Chehab 		goto fail_csi_cfg;
1795ad85094bSMauro Carvalho Chehab 	}
1796ad85094bSMauro Carvalho Chehab 	mutex_unlock(&dev->input_lock);
1797ad85094bSMauro Carvalho Chehab 
1798ad85094bSMauro Carvalho Chehab 	return ret;
1799ad85094bSMauro Carvalho Chehab 
1800ad85094bSMauro Carvalho Chehab fail_csi_cfg:
1801ad85094bSMauro Carvalho Chehab 	dev->platform_data->csi_cfg(sd, 0);
1802ad85094bSMauro Carvalho Chehab fail_power_on:
1803ad85094bSMauro Carvalho Chehab 	power_down(sd);
1804ad85094bSMauro Carvalho Chehab 	dev_err(&client->dev, "sensor power-gating failed\n");
1805ad85094bSMauro Carvalho Chehab fail_power_off:
1806ad85094bSMauro Carvalho Chehab 	mutex_unlock(&dev->input_lock);
1807ad85094bSMauro Carvalho Chehab 	return ret;
1808ad85094bSMauro Carvalho Chehab }
1809ad85094bSMauro Carvalho Chehab 
1810ad85094bSMauro Carvalho Chehab static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
1811ad85094bSMauro Carvalho Chehab 				   struct v4l2_subdev_frame_interval *interval)
1812ad85094bSMauro Carvalho Chehab {
1813ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1814ad85094bSMauro Carvalho Chehab 
1815ad85094bSMauro Carvalho Chehab 	interval->interval.numerator = 1;
1816ad85094bSMauro Carvalho Chehab 	interval->interval.denominator = ov5693_res[dev->fmt_idx].fps;
1817ad85094bSMauro Carvalho Chehab 
1818ad85094bSMauro Carvalho Chehab 	return 0;
1819ad85094bSMauro Carvalho Chehab }
1820ad85094bSMauro Carvalho Chehab 
1821ad85094bSMauro Carvalho Chehab static int ov5693_enum_mbus_code(struct v4l2_subdev *sd,
1822ad85094bSMauro Carvalho Chehab 				 struct v4l2_subdev_pad_config *cfg,
1823ad85094bSMauro Carvalho Chehab 				 struct v4l2_subdev_mbus_code_enum *code)
1824ad85094bSMauro Carvalho Chehab {
1825ad85094bSMauro Carvalho Chehab 	if (code->index >= MAX_FMTS)
1826ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1827ad85094bSMauro Carvalho Chehab 
1828ad85094bSMauro Carvalho Chehab 	code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
1829ad85094bSMauro Carvalho Chehab 	return 0;
1830ad85094bSMauro Carvalho Chehab }
1831ad85094bSMauro Carvalho Chehab 
1832ad85094bSMauro Carvalho Chehab static int ov5693_enum_frame_size(struct v4l2_subdev *sd,
1833ad85094bSMauro Carvalho Chehab 				  struct v4l2_subdev_pad_config *cfg,
1834ad85094bSMauro Carvalho Chehab 				  struct v4l2_subdev_frame_size_enum *fse)
1835ad85094bSMauro Carvalho Chehab {
1836ad85094bSMauro Carvalho Chehab 	int index = fse->index;
1837ad85094bSMauro Carvalho Chehab 
1838ad85094bSMauro Carvalho Chehab 	if (index >= N_RES)
1839ad85094bSMauro Carvalho Chehab 		return -EINVAL;
1840ad85094bSMauro Carvalho Chehab 
1841ad85094bSMauro Carvalho Chehab 	fse->min_width = ov5693_res[index].width;
1842ad85094bSMauro Carvalho Chehab 	fse->min_height = ov5693_res[index].height;
1843ad85094bSMauro Carvalho Chehab 	fse->max_width = ov5693_res[index].width;
1844ad85094bSMauro Carvalho Chehab 	fse->max_height = ov5693_res[index].height;
1845ad85094bSMauro Carvalho Chehab 
1846ad85094bSMauro Carvalho Chehab 	return 0;
1847ad85094bSMauro Carvalho Chehab }
1848ad85094bSMauro Carvalho Chehab 
1849ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_video_ops ov5693_video_ops = {
1850ad85094bSMauro Carvalho Chehab 	.s_stream = ov5693_s_stream,
1851ad85094bSMauro Carvalho Chehab 	.g_frame_interval = ov5693_g_frame_interval,
1852ad85094bSMauro Carvalho Chehab };
1853ad85094bSMauro Carvalho Chehab 
1854ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_core_ops ov5693_core_ops = {
1855ad85094bSMauro Carvalho Chehab 	.s_power = ov5693_s_power,
1856ad85094bSMauro Carvalho Chehab 	.ioctl = ov5693_ioctl,
1857ad85094bSMauro Carvalho Chehab };
1858ad85094bSMauro Carvalho Chehab 
1859ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
1860ad85094bSMauro Carvalho Chehab 	.enum_mbus_code = ov5693_enum_mbus_code,
1861ad85094bSMauro Carvalho Chehab 	.enum_frame_size = ov5693_enum_frame_size,
1862ad85094bSMauro Carvalho Chehab 	.get_fmt = ov5693_get_fmt,
1863ad85094bSMauro Carvalho Chehab 	.set_fmt = ov5693_set_fmt,
1864ad85094bSMauro Carvalho Chehab };
1865ad85094bSMauro Carvalho Chehab 
1866ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_ops ov5693_ops = {
1867ad85094bSMauro Carvalho Chehab 	.core = &ov5693_core_ops,
1868ad85094bSMauro Carvalho Chehab 	.video = &ov5693_video_ops,
1869ad85094bSMauro Carvalho Chehab 	.pad = &ov5693_pad_ops,
1870ad85094bSMauro Carvalho Chehab };
1871ad85094bSMauro Carvalho Chehab 
1872ad85094bSMauro Carvalho Chehab static int ov5693_remove(struct i2c_client *client)
1873ad85094bSMauro Carvalho Chehab {
1874ad85094bSMauro Carvalho Chehab 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1875ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev = to_ov5693_sensor(sd);
1876ad85094bSMauro Carvalho Chehab 
1877ad85094bSMauro Carvalho Chehab 	dev_dbg(&client->dev, "ov5693_remove...\n");
1878ad85094bSMauro Carvalho Chehab 
1879ad85094bSMauro Carvalho Chehab 	dev->platform_data->csi_cfg(sd, 0);
1880ad85094bSMauro Carvalho Chehab 
1881ad85094bSMauro Carvalho Chehab 	v4l2_device_unregister_subdev(sd);
1882ad85094bSMauro Carvalho Chehab 
1883ad85094bSMauro Carvalho Chehab 	atomisp_gmin_remove_subdev(sd);
1884ad85094bSMauro Carvalho Chehab 
1885ad85094bSMauro Carvalho Chehab 	media_entity_cleanup(&dev->sd.entity);
1886ad85094bSMauro Carvalho Chehab 	v4l2_ctrl_handler_free(&dev->ctrl_handler);
1887ad85094bSMauro Carvalho Chehab 	kfree(dev);
1888ad85094bSMauro Carvalho Chehab 
1889ad85094bSMauro Carvalho Chehab 	return 0;
1890ad85094bSMauro Carvalho Chehab }
1891ad85094bSMauro Carvalho Chehab 
1892ad85094bSMauro Carvalho Chehab static int ov5693_probe(struct i2c_client *client)
1893ad85094bSMauro Carvalho Chehab {
1894ad85094bSMauro Carvalho Chehab 	struct ov5693_device *dev;
1895ad85094bSMauro Carvalho Chehab 	int i2c;
1896ad85094bSMauro Carvalho Chehab 	int ret = 0;
1897ad85094bSMauro Carvalho Chehab 	void *pdata;
1898ad85094bSMauro Carvalho Chehab 	unsigned int i;
1899ad85094bSMauro Carvalho Chehab 
1900ad85094bSMauro Carvalho Chehab 	/*
1901ad85094bSMauro Carvalho Chehab 	 * Firmware workaround: Some modules use a "secondary default"
1902ad85094bSMauro Carvalho Chehab 	 * address of 0x10 which doesn't appear on schematics, and
1903ad85094bSMauro Carvalho Chehab 	 * some BIOS versions haven't gotten the memo.  Work around
1904ad85094bSMauro Carvalho Chehab 	 * via config.
1905ad85094bSMauro Carvalho Chehab 	 */
1906ad85094bSMauro Carvalho Chehab 	i2c = gmin_get_var_int(&client->dev, "I2CAddr", -1);
1907ad85094bSMauro Carvalho Chehab 	if (i2c != -1) {
1908ad85094bSMauro Carvalho Chehab 		dev_info(&client->dev,
1909ad85094bSMauro Carvalho Chehab 		"Overriding firmware-provided I2C address (0x%x) with 0x%x\n",
1910ad85094bSMauro Carvalho Chehab 			 client->addr, i2c);
1911ad85094bSMauro Carvalho Chehab 		client->addr = i2c;
1912ad85094bSMauro Carvalho Chehab 	}
1913ad85094bSMauro Carvalho Chehab 
1914ad85094bSMauro Carvalho Chehab 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1915ad85094bSMauro Carvalho Chehab 	if (!dev)
1916ad85094bSMauro Carvalho Chehab 		return -ENOMEM;
1917ad85094bSMauro Carvalho Chehab 
1918ad85094bSMauro Carvalho Chehab 	mutex_init(&dev->input_lock);
1919ad85094bSMauro Carvalho Chehab 
1920ad85094bSMauro Carvalho Chehab 	dev->fmt_idx = 0;
1921bdfe0bebSMauro Carvalho Chehab 	v4l2_i2c_subdev_init(&dev->sd, client, &ov5693_ops);
1922ad85094bSMauro Carvalho Chehab 
1923ad85094bSMauro Carvalho Chehab 	pdata = gmin_camera_platform_data(&dev->sd,
1924ad85094bSMauro Carvalho Chehab 					  ATOMISP_INPUT_FORMAT_RAW_10,
1925ad85094bSMauro Carvalho Chehab 					  atomisp_bayer_order_bggr);
1926ad85094bSMauro Carvalho Chehab 	if (!pdata)
1927ad85094bSMauro Carvalho Chehab 		goto out_free;
1928ad85094bSMauro Carvalho Chehab 
1929ad85094bSMauro Carvalho Chehab 	ret = ov5693_s_config(&dev->sd, client->irq, pdata);
1930ad85094bSMauro Carvalho Chehab 	if (ret)
1931ad85094bSMauro Carvalho Chehab 		goto out_free;
1932ad85094bSMauro Carvalho Chehab 
1933ad85094bSMauro Carvalho Chehab 	ret = atomisp_register_i2c_module(&dev->sd, pdata, RAW_CAMERA);
1934ad85094bSMauro Carvalho Chehab 	if (ret)
1935ad85094bSMauro Carvalho Chehab 		goto out_free;
1936ad85094bSMauro Carvalho Chehab 
1937ad85094bSMauro Carvalho Chehab 	dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1938ad85094bSMauro Carvalho Chehab 	dev->pad.flags = MEDIA_PAD_FL_SOURCE;
1939ad85094bSMauro Carvalho Chehab 	dev->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
1940ad85094bSMauro Carvalho Chehab 	dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1941ad85094bSMauro Carvalho Chehab 	ret =
1942ad85094bSMauro Carvalho Chehab 	    v4l2_ctrl_handler_init(&dev->ctrl_handler,
1943ad85094bSMauro Carvalho Chehab 				   ARRAY_SIZE(ov5693_controls));
1944ad85094bSMauro Carvalho Chehab 	if (ret) {
1945ad85094bSMauro Carvalho Chehab 		ov5693_remove(client);
1946ad85094bSMauro Carvalho Chehab 		return ret;
1947ad85094bSMauro Carvalho Chehab 	}
1948ad85094bSMauro Carvalho Chehab 
1949ad85094bSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(ov5693_controls); i++)
1950ad85094bSMauro Carvalho Chehab 		v4l2_ctrl_new_custom(&dev->ctrl_handler, &ov5693_controls[i],
1951ad85094bSMauro Carvalho Chehab 				     NULL);
1952ad85094bSMauro Carvalho Chehab 
1953ad85094bSMauro Carvalho Chehab 	if (dev->ctrl_handler.error) {
1954ad85094bSMauro Carvalho Chehab 		ov5693_remove(client);
1955ad85094bSMauro Carvalho Chehab 		return dev->ctrl_handler.error;
1956ad85094bSMauro Carvalho Chehab 	}
1957ad85094bSMauro Carvalho Chehab 
1958ad85094bSMauro Carvalho Chehab 	/* Use same lock for controls as for everything else. */
1959ad85094bSMauro Carvalho Chehab 	dev->ctrl_handler.lock = &dev->input_lock;
1960ad85094bSMauro Carvalho Chehab 	dev->sd.ctrl_handler = &dev->ctrl_handler;
1961ad85094bSMauro Carvalho Chehab 
1962ad85094bSMauro Carvalho Chehab 	ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
1963ad85094bSMauro Carvalho Chehab 	if (ret)
1964ad85094bSMauro Carvalho Chehab 		ov5693_remove(client);
1965ad85094bSMauro Carvalho Chehab 
1966ad85094bSMauro Carvalho Chehab 	return ret;
1967ad85094bSMauro Carvalho Chehab out_free:
1968ad85094bSMauro Carvalho Chehab 	v4l2_device_unregister_subdev(&dev->sd);
1969ad85094bSMauro Carvalho Chehab 	kfree(dev);
1970ad85094bSMauro Carvalho Chehab 	return ret;
1971ad85094bSMauro Carvalho Chehab }
1972ad85094bSMauro Carvalho Chehab 
1973ad85094bSMauro Carvalho Chehab static const struct acpi_device_id ov5693_acpi_match[] = {
1974ad85094bSMauro Carvalho Chehab 	{"INT33BE"},
1975ad85094bSMauro Carvalho Chehab 	{},
1976ad85094bSMauro Carvalho Chehab };
1977ad85094bSMauro Carvalho Chehab MODULE_DEVICE_TABLE(acpi, ov5693_acpi_match);
1978ad85094bSMauro Carvalho Chehab 
1979ad85094bSMauro Carvalho Chehab static struct i2c_driver ov5693_driver = {
1980ad85094bSMauro Carvalho Chehab 	.driver = {
1981ad85094bSMauro Carvalho Chehab 		.name = "ov5693",
1982ad85094bSMauro Carvalho Chehab 		.acpi_match_table = ov5693_acpi_match,
1983ad85094bSMauro Carvalho Chehab 	},
1984ad85094bSMauro Carvalho Chehab 	.probe_new = ov5693_probe,
1985ad85094bSMauro Carvalho Chehab 	.remove = ov5693_remove,
1986ad85094bSMauro Carvalho Chehab };
1987ad85094bSMauro Carvalho Chehab module_i2c_driver(ov5693_driver);
1988ad85094bSMauro Carvalho Chehab 
1989ad85094bSMauro Carvalho Chehab MODULE_DESCRIPTION("A low-level driver for OmniVision 5693 sensors");
1990ad85094bSMauro Carvalho Chehab MODULE_LICENSE("GPL");
1991