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