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 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 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 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 */ 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 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 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 */ 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 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 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 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 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 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 418ad85094bSMauro Carvalho Chehab static int ov5693_g_focal(struct v4l2_subdev *sd, s32 *val) 419ad85094bSMauro Carvalho Chehab { 420ad85094bSMauro Carvalho Chehab *val = (OV5693_FOCAL_LENGTH_NUM << 16) | OV5693_FOCAL_LENGTH_DEM; 421ad85094bSMauro Carvalho Chehab return 0; 422ad85094bSMauro Carvalho Chehab } 423ad85094bSMauro Carvalho Chehab 424ad85094bSMauro Carvalho Chehab static int ov5693_g_fnumber(struct v4l2_subdev *sd, s32 *val) 425ad85094bSMauro Carvalho Chehab { 426ad85094bSMauro Carvalho Chehab /*const f number for imx*/ 427ad85094bSMauro Carvalho Chehab *val = (OV5693_F_NUMBER_DEFAULT_NUM << 16) | OV5693_F_NUMBER_DEM; 428ad85094bSMauro Carvalho Chehab return 0; 429ad85094bSMauro Carvalho Chehab } 430ad85094bSMauro Carvalho Chehab 431ad85094bSMauro Carvalho Chehab static int ov5693_g_fnumber_range(struct v4l2_subdev *sd, s32 *val) 432ad85094bSMauro Carvalho Chehab { 433ad85094bSMauro Carvalho Chehab *val = (OV5693_F_NUMBER_DEFAULT_NUM << 24) | 434ad85094bSMauro Carvalho Chehab (OV5693_F_NUMBER_DEM << 16) | 435ad85094bSMauro Carvalho Chehab (OV5693_F_NUMBER_DEFAULT_NUM << 8) | OV5693_F_NUMBER_DEM; 436ad85094bSMauro Carvalho Chehab return 0; 437ad85094bSMauro Carvalho Chehab } 438ad85094bSMauro Carvalho Chehab 439ad85094bSMauro Carvalho Chehab static int ov5693_g_bin_factor_x(struct v4l2_subdev *sd, s32 *val) 440ad85094bSMauro Carvalho Chehab { 441ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 442ad85094bSMauro Carvalho Chehab 443ad85094bSMauro Carvalho Chehab *val = ov5693_res[dev->fmt_idx].bin_factor_x; 444ad85094bSMauro Carvalho Chehab 445ad85094bSMauro Carvalho Chehab return 0; 446ad85094bSMauro Carvalho Chehab } 447ad85094bSMauro Carvalho Chehab 448ad85094bSMauro Carvalho Chehab static int ov5693_g_bin_factor_y(struct v4l2_subdev *sd, s32 *val) 449ad85094bSMauro Carvalho Chehab { 450ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 451ad85094bSMauro Carvalho Chehab 452ad85094bSMauro Carvalho Chehab *val = ov5693_res[dev->fmt_idx].bin_factor_y; 453ad85094bSMauro Carvalho Chehab 454ad85094bSMauro Carvalho Chehab return 0; 455ad85094bSMauro Carvalho Chehab } 456ad85094bSMauro Carvalho Chehab 457ad85094bSMauro Carvalho Chehab static int ov5693_get_intg_factor(struct i2c_client *client, 458ad85094bSMauro Carvalho Chehab struct camera_mipi_info *info, 459ad85094bSMauro Carvalho Chehab const struct ov5693_resolution *res) 460ad85094bSMauro Carvalho Chehab { 461ad85094bSMauro Carvalho Chehab struct v4l2_subdev *sd = i2c_get_clientdata(client); 462ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 463ad85094bSMauro Carvalho Chehab struct atomisp_sensor_mode_data *buf = &info->data; 464ad85094bSMauro Carvalho Chehab unsigned int pix_clk_freq_hz; 465ad85094bSMauro Carvalho Chehab u16 reg_val; 466ad85094bSMauro Carvalho Chehab int ret; 467ad85094bSMauro Carvalho Chehab 468bdfe0bebSMauro Carvalho Chehab if (!info) 469ad85094bSMauro Carvalho Chehab return -EINVAL; 470ad85094bSMauro Carvalho Chehab 471ad85094bSMauro Carvalho Chehab /* pixel clock */ 472ad85094bSMauro Carvalho Chehab pix_clk_freq_hz = res->pix_clk_freq * 1000000; 473ad85094bSMauro Carvalho Chehab 474ad85094bSMauro Carvalho Chehab dev->vt_pix_clk_freq_mhz = pix_clk_freq_hz; 475ad85094bSMauro Carvalho Chehab buf->vt_pix_clk_freq_mhz = pix_clk_freq_hz; 476ad85094bSMauro Carvalho Chehab 477ad85094bSMauro Carvalho Chehab /* get integration time */ 478ad85094bSMauro Carvalho Chehab buf->coarse_integration_time_min = OV5693_COARSE_INTG_TIME_MIN; 479ad85094bSMauro Carvalho Chehab buf->coarse_integration_time_max_margin = 480ad85094bSMauro Carvalho Chehab OV5693_COARSE_INTG_TIME_MAX_MARGIN; 481ad85094bSMauro Carvalho Chehab 482ad85094bSMauro Carvalho Chehab buf->fine_integration_time_min = OV5693_FINE_INTG_TIME_MIN; 483ad85094bSMauro Carvalho Chehab buf->fine_integration_time_max_margin = 484ad85094bSMauro Carvalho Chehab OV5693_FINE_INTG_TIME_MAX_MARGIN; 485ad85094bSMauro Carvalho Chehab 486ad85094bSMauro Carvalho Chehab buf->fine_integration_time_def = OV5693_FINE_INTG_TIME_MIN; 487ad85094bSMauro Carvalho Chehab buf->frame_length_lines = res->lines_per_frame; 488ad85094bSMauro Carvalho Chehab buf->line_length_pck = res->pixels_per_line; 489ad85094bSMauro Carvalho Chehab buf->read_mode = res->bin_mode; 490ad85094bSMauro Carvalho Chehab 491ad85094bSMauro Carvalho Chehab /* get the cropping and output resolution to ISP for this mode. */ 492ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_16BIT, 493ad85094bSMauro Carvalho Chehab OV5693_HORIZONTAL_START_H, ®_val); 494ad85094bSMauro Carvalho Chehab if (ret) 495ad85094bSMauro Carvalho Chehab return ret; 496ad85094bSMauro Carvalho Chehab buf->crop_horizontal_start = reg_val; 497ad85094bSMauro Carvalho Chehab 498ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_16BIT, 499ad85094bSMauro Carvalho Chehab OV5693_VERTICAL_START_H, ®_val); 500ad85094bSMauro Carvalho Chehab if (ret) 501ad85094bSMauro Carvalho Chehab return ret; 502ad85094bSMauro Carvalho Chehab buf->crop_vertical_start = reg_val; 503ad85094bSMauro Carvalho Chehab 504ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_16BIT, 505ad85094bSMauro Carvalho Chehab OV5693_HORIZONTAL_END_H, ®_val); 506ad85094bSMauro Carvalho Chehab if (ret) 507ad85094bSMauro Carvalho Chehab return ret; 508ad85094bSMauro Carvalho Chehab buf->crop_horizontal_end = reg_val; 509ad85094bSMauro Carvalho Chehab 510ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_16BIT, 511ad85094bSMauro Carvalho Chehab OV5693_VERTICAL_END_H, ®_val); 512ad85094bSMauro Carvalho Chehab if (ret) 513ad85094bSMauro Carvalho Chehab return ret; 514ad85094bSMauro Carvalho Chehab buf->crop_vertical_end = reg_val; 515ad85094bSMauro Carvalho Chehab 516ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_16BIT, 517ad85094bSMauro Carvalho Chehab OV5693_HORIZONTAL_OUTPUT_SIZE_H, ®_val); 518ad85094bSMauro Carvalho Chehab if (ret) 519ad85094bSMauro Carvalho Chehab return ret; 520ad85094bSMauro Carvalho Chehab buf->output_width = reg_val; 521ad85094bSMauro Carvalho Chehab 522ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_16BIT, 523ad85094bSMauro Carvalho Chehab OV5693_VERTICAL_OUTPUT_SIZE_H, ®_val); 524ad85094bSMauro Carvalho Chehab if (ret) 525ad85094bSMauro Carvalho Chehab return ret; 526ad85094bSMauro Carvalho Chehab buf->output_height = reg_val; 527ad85094bSMauro Carvalho Chehab 528ad85094bSMauro Carvalho Chehab buf->binning_factor_x = res->bin_factor_x ? 529ad85094bSMauro Carvalho Chehab res->bin_factor_x : 1; 530ad85094bSMauro Carvalho Chehab buf->binning_factor_y = res->bin_factor_y ? 531ad85094bSMauro Carvalho Chehab res->bin_factor_y : 1; 532ad85094bSMauro Carvalho Chehab return 0; 533ad85094bSMauro Carvalho Chehab } 534ad85094bSMauro Carvalho Chehab 535ad85094bSMauro Carvalho Chehab static long __ov5693_set_exposure(struct v4l2_subdev *sd, int coarse_itg, 536ad85094bSMauro Carvalho Chehab int gain, int digitgain) 537ad85094bSMauro Carvalho Chehab 538ad85094bSMauro Carvalho Chehab { 539ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 540ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 541ad85094bSMauro Carvalho Chehab u16 vts, hts; 542ad85094bSMauro Carvalho Chehab int ret, exp_val; 543ad85094bSMauro Carvalho Chehab 544ad85094bSMauro Carvalho Chehab hts = ov5693_res[dev->fmt_idx].pixels_per_line; 545ad85094bSMauro Carvalho Chehab vts = ov5693_res[dev->fmt_idx].lines_per_frame; 546ad85094bSMauro Carvalho Chehab /* 547ad85094bSMauro Carvalho Chehab * If coarse_itg is larger than 1<<15, can not write to reg directly. 548ad85094bSMauro Carvalho Chehab * The way is to write coarse_itg/2 to the reg, meanwhile write 2*hts 549ad85094bSMauro Carvalho Chehab * to the reg. 550ad85094bSMauro Carvalho Chehab */ 551ad85094bSMauro Carvalho Chehab if (coarse_itg > (1 << 15)) { 552ad85094bSMauro Carvalho Chehab hts = hts * 2; 553ad85094bSMauro Carvalho Chehab coarse_itg = (int)coarse_itg / 2; 554ad85094bSMauro Carvalho Chehab } 555ad85094bSMauro Carvalho Chehab /* group hold */ 556ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 557ad85094bSMauro Carvalho Chehab OV5693_GROUP_ACCESS, 0x00); 558ad85094bSMauro Carvalho Chehab if (ret) { 559ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 560ad85094bSMauro Carvalho Chehab __func__, OV5693_GROUP_ACCESS); 561ad85094bSMauro Carvalho Chehab return ret; 562ad85094bSMauro Carvalho Chehab } 563ad85094bSMauro Carvalho Chehab 564ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 565ad85094bSMauro Carvalho Chehab OV5693_TIMING_HTS_H, (hts >> 8) & 0xFF); 566ad85094bSMauro Carvalho Chehab if (ret) { 567ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 568ad85094bSMauro Carvalho Chehab __func__, OV5693_TIMING_HTS_H); 569ad85094bSMauro Carvalho Chehab return ret; 570ad85094bSMauro Carvalho Chehab } 571ad85094bSMauro Carvalho Chehab 572ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 573ad85094bSMauro Carvalho Chehab OV5693_TIMING_HTS_L, hts & 0xFF); 574ad85094bSMauro Carvalho Chehab if (ret) { 575ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 576ad85094bSMauro Carvalho Chehab __func__, OV5693_TIMING_HTS_L); 577ad85094bSMauro Carvalho Chehab return ret; 578ad85094bSMauro Carvalho Chehab } 579ad85094bSMauro Carvalho Chehab /* Increase the VTS to match exposure + MARGIN */ 580ad85094bSMauro Carvalho Chehab if (coarse_itg > vts - OV5693_INTEGRATION_TIME_MARGIN) 581ad85094bSMauro Carvalho Chehab vts = (u16)coarse_itg + OV5693_INTEGRATION_TIME_MARGIN; 582ad85094bSMauro Carvalho Chehab 583ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 584ad85094bSMauro Carvalho Chehab OV5693_TIMING_VTS_H, (vts >> 8) & 0xFF); 585ad85094bSMauro Carvalho Chehab if (ret) { 586ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 587ad85094bSMauro Carvalho Chehab __func__, OV5693_TIMING_VTS_H); 588ad85094bSMauro Carvalho Chehab return ret; 589ad85094bSMauro Carvalho Chehab } 590ad85094bSMauro Carvalho Chehab 591ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 592ad85094bSMauro Carvalho Chehab OV5693_TIMING_VTS_L, vts & 0xFF); 593ad85094bSMauro Carvalho Chehab if (ret) { 594ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 595ad85094bSMauro Carvalho Chehab __func__, OV5693_TIMING_VTS_L); 596ad85094bSMauro Carvalho Chehab return ret; 597ad85094bSMauro Carvalho Chehab } 598ad85094bSMauro Carvalho Chehab 599ad85094bSMauro Carvalho Chehab /* set exposure */ 600ad85094bSMauro Carvalho Chehab 601ad85094bSMauro Carvalho Chehab /* Lower four bit should be 0*/ 602ad85094bSMauro Carvalho Chehab exp_val = coarse_itg << 4; 603ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 604ad85094bSMauro Carvalho Chehab OV5693_EXPOSURE_L, exp_val & 0xFF); 605ad85094bSMauro Carvalho Chehab if (ret) { 606ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 607ad85094bSMauro Carvalho Chehab __func__, OV5693_EXPOSURE_L); 608ad85094bSMauro Carvalho Chehab return ret; 609ad85094bSMauro Carvalho Chehab } 610ad85094bSMauro Carvalho Chehab 611ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 612ad85094bSMauro Carvalho Chehab OV5693_EXPOSURE_M, (exp_val >> 8) & 0xFF); 613ad85094bSMauro Carvalho Chehab if (ret) { 614ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 615ad85094bSMauro Carvalho Chehab __func__, OV5693_EXPOSURE_M); 616ad85094bSMauro Carvalho Chehab return ret; 617ad85094bSMauro Carvalho Chehab } 618ad85094bSMauro Carvalho Chehab 619ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 620ad85094bSMauro Carvalho Chehab OV5693_EXPOSURE_H, (exp_val >> 16) & 0x0F); 621ad85094bSMauro Carvalho Chehab if (ret) { 622ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 623ad85094bSMauro Carvalho Chehab __func__, OV5693_EXPOSURE_H); 624ad85094bSMauro Carvalho Chehab return ret; 625ad85094bSMauro Carvalho Chehab } 626ad85094bSMauro Carvalho Chehab 627ad85094bSMauro Carvalho Chehab /* Analog gain */ 628ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 629ad85094bSMauro Carvalho Chehab OV5693_AGC_L, gain & 0xff); 630ad85094bSMauro Carvalho Chehab if (ret) { 631ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 632ad85094bSMauro Carvalho Chehab __func__, OV5693_AGC_L); 633ad85094bSMauro Carvalho Chehab return ret; 634ad85094bSMauro Carvalho Chehab } 635ad85094bSMauro Carvalho Chehab 636ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 637ad85094bSMauro Carvalho Chehab OV5693_AGC_H, (gain >> 8) & 0xff); 638ad85094bSMauro Carvalho Chehab if (ret) { 639ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 640ad85094bSMauro Carvalho Chehab __func__, OV5693_AGC_H); 641ad85094bSMauro Carvalho Chehab return ret; 642ad85094bSMauro Carvalho Chehab } 643ad85094bSMauro Carvalho Chehab 644ad85094bSMauro Carvalho Chehab /* Digital gain */ 645ad85094bSMauro Carvalho Chehab if (digitgain) { 646ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_16BIT, 647ad85094bSMauro Carvalho Chehab OV5693_MWB_RED_GAIN_H, digitgain); 648ad85094bSMauro Carvalho Chehab if (ret) { 649ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 650ad85094bSMauro Carvalho Chehab __func__, OV5693_MWB_RED_GAIN_H); 651ad85094bSMauro Carvalho Chehab return ret; 652ad85094bSMauro Carvalho Chehab } 653ad85094bSMauro Carvalho Chehab 654ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_16BIT, 655ad85094bSMauro Carvalho Chehab OV5693_MWB_GREEN_GAIN_H, digitgain); 656ad85094bSMauro Carvalho Chehab if (ret) { 657ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 658ad85094bSMauro Carvalho Chehab __func__, OV5693_MWB_RED_GAIN_H); 659ad85094bSMauro Carvalho Chehab return ret; 660ad85094bSMauro Carvalho Chehab } 661ad85094bSMauro Carvalho Chehab 662ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_16BIT, 663ad85094bSMauro Carvalho Chehab OV5693_MWB_BLUE_GAIN_H, digitgain); 664ad85094bSMauro Carvalho Chehab if (ret) { 665ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: write %x error, aborted\n", 666ad85094bSMauro Carvalho Chehab __func__, OV5693_MWB_RED_GAIN_H); 667ad85094bSMauro Carvalho Chehab return ret; 668ad85094bSMauro Carvalho Chehab } 669ad85094bSMauro Carvalho Chehab } 670ad85094bSMauro Carvalho Chehab 671ad85094bSMauro Carvalho Chehab /* End group */ 672ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 673ad85094bSMauro Carvalho Chehab OV5693_GROUP_ACCESS, 0x10); 674ad85094bSMauro Carvalho Chehab if (ret) 675ad85094bSMauro Carvalho Chehab return ret; 676ad85094bSMauro Carvalho Chehab 677ad85094bSMauro Carvalho Chehab /* Delay launch group */ 678ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 679ad85094bSMauro Carvalho Chehab OV5693_GROUP_ACCESS, 0xa0); 680ad85094bSMauro Carvalho Chehab if (ret) 681ad85094bSMauro Carvalho Chehab return ret; 682ad85094bSMauro Carvalho Chehab return ret; 683ad85094bSMauro Carvalho Chehab } 684ad85094bSMauro Carvalho Chehab 685ad85094bSMauro Carvalho Chehab static int ov5693_set_exposure(struct v4l2_subdev *sd, int exposure, 686ad85094bSMauro Carvalho Chehab int gain, int digitgain) 687ad85094bSMauro Carvalho Chehab { 688ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 689ad85094bSMauro Carvalho Chehab int ret; 690ad85094bSMauro Carvalho Chehab 691ad85094bSMauro Carvalho Chehab mutex_lock(&dev->input_lock); 692ad85094bSMauro Carvalho Chehab ret = __ov5693_set_exposure(sd, exposure, gain, digitgain); 693ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 694ad85094bSMauro Carvalho Chehab 695ad85094bSMauro Carvalho Chehab return ret; 696ad85094bSMauro Carvalho Chehab } 697ad85094bSMauro Carvalho Chehab 698ad85094bSMauro Carvalho Chehab static long ov5693_s_exposure(struct v4l2_subdev *sd, 699ad85094bSMauro Carvalho Chehab struct atomisp_exposure *exposure) 700ad85094bSMauro Carvalho Chehab { 701ad85094bSMauro Carvalho Chehab u16 coarse_itg = exposure->integration_time[0]; 702ad85094bSMauro Carvalho Chehab u16 analog_gain = exposure->gain[0]; 703ad85094bSMauro Carvalho Chehab u16 digital_gain = exposure->gain[1]; 704ad85094bSMauro Carvalho Chehab 705ad85094bSMauro Carvalho Chehab /* we should not accept the invalid value below */ 706ad85094bSMauro Carvalho Chehab if (analog_gain == 0) { 707ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 708ad85094bSMauro Carvalho Chehab 709ad85094bSMauro Carvalho Chehab v4l2_err(client, "%s: invalid value\n", __func__); 710ad85094bSMauro Carvalho Chehab return -EINVAL; 711ad85094bSMauro Carvalho Chehab } 712ad85094bSMauro Carvalho Chehab return ov5693_set_exposure(sd, coarse_itg, analog_gain, digital_gain); 713ad85094bSMauro Carvalho Chehab } 714ad85094bSMauro Carvalho Chehab 715ad85094bSMauro Carvalho Chehab static int ov5693_read_otp_reg_array(struct i2c_client *client, u16 size, 716ad85094bSMauro Carvalho Chehab u16 addr, u8 *buf) 717ad85094bSMauro Carvalho Chehab { 718ad85094bSMauro Carvalho Chehab u16 index; 719ad85094bSMauro Carvalho Chehab int ret; 720ad85094bSMauro Carvalho Chehab u16 *pVal = NULL; 721ad85094bSMauro Carvalho Chehab 722ad85094bSMauro Carvalho Chehab for (index = 0; index <= size; index++) { 723ad85094bSMauro Carvalho Chehab pVal = (u16 *)(buf + index); 724ad85094bSMauro Carvalho Chehab ret = 725ad85094bSMauro Carvalho Chehab ov5693_read_reg(client, OV5693_8BIT, addr + index, 726ad85094bSMauro Carvalho Chehab pVal); 727ad85094bSMauro Carvalho Chehab if (ret) 728ad85094bSMauro Carvalho Chehab return ret; 729ad85094bSMauro Carvalho Chehab } 730ad85094bSMauro Carvalho Chehab 731ad85094bSMauro Carvalho Chehab return 0; 732ad85094bSMauro Carvalho Chehab } 733ad85094bSMauro Carvalho Chehab 734ad85094bSMauro Carvalho Chehab static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf) 735ad85094bSMauro Carvalho Chehab { 736ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 737ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 738ad85094bSMauro Carvalho Chehab int ret; 739ad85094bSMauro Carvalho Chehab int i; 740ad85094bSMauro Carvalho Chehab u8 *b = buf; 741ad85094bSMauro Carvalho Chehab 742ad85094bSMauro Carvalho Chehab dev->otp_size = 0; 743ad85094bSMauro Carvalho Chehab for (i = 1; i < OV5693_OTP_BANK_MAX; i++) { 744ad85094bSMauro Carvalho Chehab /*set bank NO and OTP read mode. */ 745eaa399ebSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_OTP_BANK_REG, 746eaa399ebSMauro Carvalho Chehab (i | 0xc0)); //[7:6] 2'b11 [5:0] bank no 747ad85094bSMauro Carvalho Chehab if (ret) { 748ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "failed to prepare OTP page\n"); 749ad85094bSMauro Carvalho Chehab return ret; 750ad85094bSMauro Carvalho Chehab } 751ad85094bSMauro Carvalho Chehab //pr_debug("write 0x%x->0x%x\n",OV5693_OTP_BANK_REG,(i|0xc0)); 752ad85094bSMauro Carvalho Chehab 753ad85094bSMauro Carvalho Chehab /*enable read */ 754eaa399ebSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_OTP_READ_REG, 755eaa399ebSMauro Carvalho Chehab OV5693_OTP_MODE_READ); // enable :1 756ad85094bSMauro Carvalho Chehab if (ret) { 757ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 758ad85094bSMauro Carvalho Chehab "failed to set OTP reading mode page"); 759ad85094bSMauro Carvalho Chehab return ret; 760ad85094bSMauro Carvalho Chehab } 761ad85094bSMauro Carvalho Chehab //pr_debug("write 0x%x->0x%x\n",OV5693_OTP_READ_REG,OV5693_OTP_MODE_READ); 762ad85094bSMauro Carvalho Chehab 763ad85094bSMauro Carvalho Chehab /* Reading the OTP data array */ 764ad85094bSMauro Carvalho Chehab ret = ov5693_read_otp_reg_array(client, OV5693_OTP_BANK_SIZE, 765ad85094bSMauro Carvalho Chehab OV5693_OTP_START_ADDR, 766ad85094bSMauro Carvalho Chehab b); 767ad85094bSMauro Carvalho Chehab if (ret) { 768ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "failed to read OTP data\n"); 769ad85094bSMauro Carvalho Chehab return ret; 770ad85094bSMauro Carvalho Chehab } 771ad85094bSMauro Carvalho Chehab 772ad85094bSMauro 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)); 773ad85094bSMauro Carvalho Chehab 774ad85094bSMauro Carvalho Chehab //Intel OTP map, try to read 320byts first. 775ad85094bSMauro Carvalho Chehab if (i == 21) { 776ad85094bSMauro Carvalho Chehab if ((*b) == 0) { 777ad85094bSMauro Carvalho Chehab dev->otp_size = 320; 778ad85094bSMauro Carvalho Chehab break; 779ad85094bSMauro Carvalho Chehab } else { 780ad85094bSMauro Carvalho Chehab b = buf; 781ad85094bSMauro Carvalho Chehab continue; 782ad85094bSMauro Carvalho Chehab } 783eaa399ebSMauro Carvalho Chehab } else if (i == 784eaa399ebSMauro Carvalho Chehab 24) { //if the first 320bytes data doesn't not exist, try to read the next 32bytes data. 785ad85094bSMauro Carvalho Chehab if ((*b) == 0) { 786ad85094bSMauro Carvalho Chehab dev->otp_size = 32; 787ad85094bSMauro Carvalho Chehab break; 788ad85094bSMauro Carvalho Chehab } else { 789ad85094bSMauro Carvalho Chehab b = buf; 790ad85094bSMauro Carvalho Chehab continue; 791ad85094bSMauro Carvalho Chehab } 792eaa399ebSMauro Carvalho Chehab } else if (i == 793eaa399ebSMauro Carvalho Chehab 27) { //if the prvious 32bytes data doesn't exist, try to read the next 32bytes data again. 794ad85094bSMauro Carvalho Chehab if ((*b) == 0) { 795ad85094bSMauro Carvalho Chehab dev->otp_size = 32; 796ad85094bSMauro Carvalho Chehab break; 797ad85094bSMauro Carvalho Chehab } else { 798ad85094bSMauro Carvalho Chehab dev->otp_size = 0; // no OTP data. 799ad85094bSMauro Carvalho Chehab break; 800ad85094bSMauro Carvalho Chehab } 801ad85094bSMauro Carvalho Chehab } 802ad85094bSMauro Carvalho Chehab 803ad85094bSMauro Carvalho Chehab b = b + OV5693_OTP_BANK_SIZE; 804ad85094bSMauro Carvalho Chehab } 805ad85094bSMauro Carvalho Chehab return 0; 806ad85094bSMauro Carvalho Chehab } 807ad85094bSMauro Carvalho Chehab 808ad85094bSMauro Carvalho Chehab /* 809ad85094bSMauro Carvalho Chehab * Read otp data and store it into a kmalloced buffer. 810ad85094bSMauro Carvalho Chehab * The caller must kfree the buffer when no more needed. 811ad85094bSMauro Carvalho Chehab * @size: set to the size of the returned otp data. 812ad85094bSMauro Carvalho Chehab */ 813ad85094bSMauro Carvalho Chehab static void *ov5693_otp_read(struct v4l2_subdev *sd) 814ad85094bSMauro Carvalho Chehab { 815ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 816ad85094bSMauro Carvalho Chehab u8 *buf; 817ad85094bSMauro Carvalho Chehab int ret; 818ad85094bSMauro Carvalho Chehab 819ad85094bSMauro Carvalho Chehab buf = devm_kzalloc(&client->dev, (OV5693_OTP_DATA_SIZE + 16), GFP_KERNEL); 820ad85094bSMauro Carvalho Chehab if (!buf) 821ad85094bSMauro Carvalho Chehab return ERR_PTR(-ENOMEM); 822ad85094bSMauro Carvalho Chehab 823ad85094bSMauro Carvalho Chehab //otp valid after mipi on and sw stream on 824ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_FRAME_OFF_NUM, 0x00); 825ad85094bSMauro Carvalho Chehab 826ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 827ad85094bSMauro Carvalho Chehab OV5693_SW_STREAM, OV5693_START_STREAMING); 828ad85094bSMauro Carvalho Chehab 829ad85094bSMauro Carvalho Chehab ret = __ov5693_otp_read(sd, buf); 830ad85094bSMauro Carvalho Chehab 831ad85094bSMauro Carvalho Chehab //mipi off and sw stream off after otp read 832ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_FRAME_OFF_NUM, 0x0f); 833ad85094bSMauro Carvalho Chehab 834ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 835ad85094bSMauro Carvalho Chehab OV5693_SW_STREAM, OV5693_STOP_STREAMING); 836ad85094bSMauro Carvalho Chehab 837ad85094bSMauro Carvalho Chehab /* Driver has failed to find valid data */ 838ad85094bSMauro Carvalho Chehab if (ret) { 839ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "sensor found no valid OTP data\n"); 840ad85094bSMauro Carvalho Chehab return ERR_PTR(ret); 841ad85094bSMauro Carvalho Chehab } 842ad85094bSMauro Carvalho Chehab 843ad85094bSMauro Carvalho Chehab return buf; 844ad85094bSMauro Carvalho Chehab } 845ad85094bSMauro Carvalho Chehab 846ad85094bSMauro Carvalho Chehab static int ov5693_g_priv_int_data(struct v4l2_subdev *sd, 847ad85094bSMauro Carvalho Chehab struct v4l2_private_int_data *priv) 848ad85094bSMauro Carvalho Chehab { 849ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 850ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 851ad85094bSMauro Carvalho Chehab u8 __user *to = priv->data; 852ad85094bSMauro Carvalho Chehab u32 read_size = priv->size; 853ad85094bSMauro Carvalho Chehab int ret; 854ad85094bSMauro Carvalho Chehab 855ad85094bSMauro Carvalho Chehab /* No need to copy data if size is 0 */ 856ad85094bSMauro Carvalho Chehab if (!read_size) 857ad85094bSMauro Carvalho Chehab goto out; 858ad85094bSMauro Carvalho Chehab 859ad85094bSMauro Carvalho Chehab if (IS_ERR(dev->otp_data)) { 860ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "OTP data not available"); 861ad85094bSMauro Carvalho Chehab return PTR_ERR(dev->otp_data); 862ad85094bSMauro Carvalho Chehab } 863ad85094bSMauro Carvalho Chehab 864ad85094bSMauro Carvalho Chehab /* Correct read_size value only if bigger than maximum */ 865ad85094bSMauro Carvalho Chehab if (read_size > OV5693_OTP_DATA_SIZE) 866ad85094bSMauro Carvalho Chehab read_size = OV5693_OTP_DATA_SIZE; 867ad85094bSMauro Carvalho Chehab 868ad85094bSMauro Carvalho Chehab ret = copy_to_user(to, dev->otp_data, read_size); 869ad85094bSMauro Carvalho Chehab if (ret) { 870ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "%s: failed to copy OTP data to user\n", 871ad85094bSMauro Carvalho Chehab __func__); 872ad85094bSMauro Carvalho Chehab return -EFAULT; 873ad85094bSMauro Carvalho Chehab } 874ad85094bSMauro Carvalho Chehab 875ad85094bSMauro Carvalho Chehab pr_debug("%s read_size:%d\n", __func__, read_size); 876ad85094bSMauro Carvalho Chehab 877ad85094bSMauro Carvalho Chehab out: 878ad85094bSMauro Carvalho Chehab /* Return correct size */ 879ad85094bSMauro Carvalho Chehab priv->size = dev->otp_size; 880ad85094bSMauro Carvalho Chehab 881ad85094bSMauro Carvalho Chehab return 0; 882ad85094bSMauro Carvalho Chehab } 883ad85094bSMauro Carvalho Chehab 884ad85094bSMauro Carvalho Chehab static long ov5693_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) 885ad85094bSMauro Carvalho Chehab { 886ad85094bSMauro Carvalho Chehab switch (cmd) { 887ad85094bSMauro Carvalho Chehab case ATOMISP_IOC_S_EXPOSURE: 888ad85094bSMauro Carvalho Chehab return ov5693_s_exposure(sd, arg); 889ad85094bSMauro Carvalho Chehab case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA: 890ad85094bSMauro Carvalho Chehab return ov5693_g_priv_int_data(sd, arg); 891ad85094bSMauro Carvalho Chehab default: 892ad85094bSMauro Carvalho Chehab return -EINVAL; 893ad85094bSMauro Carvalho Chehab } 894ad85094bSMauro Carvalho Chehab return 0; 895ad85094bSMauro Carvalho Chehab } 896ad85094bSMauro Carvalho Chehab 897ad85094bSMauro Carvalho Chehab /* 898ad85094bSMauro Carvalho Chehab * This returns the exposure time being used. This should only be used 899ad85094bSMauro Carvalho Chehab * for filling in EXIF data, not for actual image processing. 900ad85094bSMauro Carvalho Chehab */ 901ad85094bSMauro Carvalho Chehab static int ov5693_q_exposure(struct v4l2_subdev *sd, s32 *value) 902ad85094bSMauro Carvalho Chehab { 903ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 904ad85094bSMauro Carvalho Chehab u16 reg_v, reg_v2; 905ad85094bSMauro Carvalho Chehab int ret; 906ad85094bSMauro Carvalho Chehab 907ad85094bSMauro Carvalho Chehab /* get exposure */ 908ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_8BIT, 909ad85094bSMauro Carvalho Chehab OV5693_EXPOSURE_L, 910ad85094bSMauro Carvalho Chehab ®_v); 911ad85094bSMauro Carvalho Chehab if (ret) 912ad85094bSMauro Carvalho Chehab goto err; 913ad85094bSMauro Carvalho Chehab 914ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_8BIT, 915ad85094bSMauro Carvalho Chehab OV5693_EXPOSURE_M, 916ad85094bSMauro Carvalho Chehab ®_v2); 917ad85094bSMauro Carvalho Chehab if (ret) 918ad85094bSMauro Carvalho Chehab goto err; 919ad85094bSMauro Carvalho Chehab 920ad85094bSMauro Carvalho Chehab reg_v += reg_v2 << 8; 921ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_8BIT, 922ad85094bSMauro Carvalho Chehab OV5693_EXPOSURE_H, 923ad85094bSMauro Carvalho Chehab ®_v2); 924ad85094bSMauro Carvalho Chehab if (ret) 925ad85094bSMauro Carvalho Chehab goto err; 926ad85094bSMauro Carvalho Chehab 927ad85094bSMauro Carvalho Chehab *value = reg_v + (((u32)reg_v2 << 16)); 928ad85094bSMauro Carvalho Chehab err: 929ad85094bSMauro Carvalho Chehab return ret; 930ad85094bSMauro Carvalho Chehab } 931ad85094bSMauro Carvalho Chehab 932ad85094bSMauro Carvalho Chehab static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val) 933ad85094bSMauro Carvalho Chehab { 934ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 935ad85094bSMauro Carvalho Chehab int ret = -EINVAL; 936ad85094bSMauro Carvalho Chehab u8 vcm_code; 937ad85094bSMauro Carvalho Chehab 938ad85094bSMauro Carvalho Chehab ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code); 939ad85094bSMauro Carvalho Chehab if (ret) 940ad85094bSMauro Carvalho Chehab return ret; 941ad85094bSMauro Carvalho Chehab 942ad85094bSMauro Carvalho Chehab /* set reg VCM_CODE_MSB Bit[1:0] */ 943ad85094bSMauro Carvalho Chehab vcm_code = (vcm_code & VCM_CODE_MSB_MASK) | 944ad85094bSMauro Carvalho Chehab ((val >> 8) & ~VCM_CODE_MSB_MASK); 945ad85094bSMauro Carvalho Chehab ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, vcm_code); 946ad85094bSMauro Carvalho Chehab if (ret) 947ad85094bSMauro Carvalho Chehab return ret; 948ad85094bSMauro Carvalho Chehab 949ad85094bSMauro Carvalho Chehab /* set reg VCM_CODE_LSB Bit[7:0] */ 950ad85094bSMauro Carvalho Chehab ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_LSB, (val & 0xff)); 951ad85094bSMauro Carvalho Chehab if (ret) 952ad85094bSMauro Carvalho Chehab return ret; 953ad85094bSMauro Carvalho Chehab 954ad85094bSMauro Carvalho Chehab /* set required vcm move time */ 955ad85094bSMauro Carvalho Chehab vcm_code = AD5823_RESONANCE_PERIOD / AD5823_RESONANCE_COEF 956ad85094bSMauro Carvalho Chehab - AD5823_HIGH_FREQ_RANGE; 957ad85094bSMauro Carvalho Chehab ret = ad5823_i2c_write(client, AD5823_REG_VCM_MOVE_TIME, vcm_code); 958ad85094bSMauro Carvalho Chehab 959ad85094bSMauro Carvalho Chehab return ret; 960ad85094bSMauro Carvalho Chehab } 961ad85094bSMauro Carvalho Chehab 962ad85094bSMauro Carvalho Chehab static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value) 963ad85094bSMauro Carvalho Chehab { 964ad85094bSMauro Carvalho Chehab value = min(value, AD5823_MAX_FOCUS_POS); 965ad85094bSMauro Carvalho Chehab return ad5823_t_focus_vcm(sd, value); 966ad85094bSMauro Carvalho Chehab } 967ad85094bSMauro Carvalho Chehab 968ad85094bSMauro Carvalho Chehab static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value) 969ad85094bSMauro Carvalho Chehab { 970ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 971ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 972ad85094bSMauro Carvalho Chehab int ret = 0; 973ad85094bSMauro Carvalho Chehab 974ad85094bSMauro Carvalho Chehab dev_dbg(&client->dev, "%s: FOCUS_POS: 0x%x\n", __func__, value); 975ad85094bSMauro Carvalho Chehab value = clamp(value, 0, OV5693_VCM_MAX_FOCUS_POS); 976ad85094bSMauro Carvalho Chehab if (dev->vcm == VCM_DW9714) { 977ad85094bSMauro Carvalho Chehab if (dev->vcm_update) { 978ad85094bSMauro Carvalho Chehab ret = vcm_dw_i2c_write(client, VCM_PROTECTION_OFF); 979ad85094bSMauro Carvalho Chehab if (ret) 980ad85094bSMauro Carvalho Chehab return ret; 981ad85094bSMauro Carvalho Chehab ret = vcm_dw_i2c_write(client, DIRECT_VCM); 982ad85094bSMauro Carvalho Chehab if (ret) 983ad85094bSMauro Carvalho Chehab return ret; 984ad85094bSMauro Carvalho Chehab ret = vcm_dw_i2c_write(client, VCM_PROTECTION_ON); 985ad85094bSMauro Carvalho Chehab if (ret) 986ad85094bSMauro Carvalho Chehab return ret; 987ad85094bSMauro Carvalho Chehab dev->vcm_update = false; 988ad85094bSMauro Carvalho Chehab } 989ad85094bSMauro Carvalho Chehab ret = vcm_dw_i2c_write(client, 990ad85094bSMauro Carvalho Chehab vcm_val(value, VCM_DEFAULT_S)); 991ad85094bSMauro Carvalho Chehab } else if (dev->vcm == VCM_AD5823) { 992ad85094bSMauro Carvalho Chehab ad5823_t_focus_abs(sd, value); 993ad85094bSMauro Carvalho Chehab } 994ad85094bSMauro Carvalho Chehab if (ret == 0) { 995ad85094bSMauro Carvalho Chehab dev->number_of_steps = value - dev->focus; 996ad85094bSMauro Carvalho Chehab dev->focus = value; 997ad85094bSMauro Carvalho Chehab dev->timestamp_t_focus_abs = ktime_get(); 998ad85094bSMauro Carvalho Chehab } else 999ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1000ad85094bSMauro Carvalho Chehab "%s: i2c failed. ret %d\n", __func__, ret); 1001ad85094bSMauro Carvalho Chehab 1002ad85094bSMauro Carvalho Chehab return ret; 1003ad85094bSMauro Carvalho Chehab } 1004ad85094bSMauro Carvalho Chehab 1005ad85094bSMauro Carvalho Chehab static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value) 1006ad85094bSMauro Carvalho Chehab { 1007ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1008ad85094bSMauro Carvalho Chehab 1009ad85094bSMauro Carvalho Chehab return ov5693_t_focus_abs(sd, dev->focus + value); 1010ad85094bSMauro Carvalho Chehab } 1011ad85094bSMauro Carvalho Chehab 1012ad85094bSMauro Carvalho Chehab #define DELAY_PER_STEP_NS 1000000 1013ad85094bSMauro Carvalho Chehab #define DELAY_MAX_PER_STEP_NS (1000000 * 1023) 1014ad85094bSMauro Carvalho Chehab static int ov5693_q_focus_status(struct v4l2_subdev *sd, s32 *value) 1015ad85094bSMauro Carvalho Chehab { 1016ad85094bSMauro Carvalho Chehab u32 status = 0; 1017ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1018ad85094bSMauro Carvalho Chehab ktime_t temptime; 1019ad85094bSMauro Carvalho Chehab ktime_t timedelay = ns_to_ktime(min_t(u32, 1020ad85094bSMauro Carvalho Chehab abs(dev->number_of_steps) * DELAY_PER_STEP_NS, 1021ad85094bSMauro Carvalho Chehab DELAY_MAX_PER_STEP_NS)); 1022ad85094bSMauro Carvalho Chehab 1023ad85094bSMauro Carvalho Chehab temptime = ktime_sub(ktime_get(), (dev->timestamp_t_focus_abs)); 1024ad85094bSMauro Carvalho Chehab if (ktime_compare(temptime, timedelay) <= 0) { 1025ad85094bSMauro Carvalho Chehab status |= ATOMISP_FOCUS_STATUS_MOVING; 1026ad85094bSMauro Carvalho Chehab status |= ATOMISP_FOCUS_HP_IN_PROGRESS; 1027ad85094bSMauro Carvalho Chehab } else { 1028ad85094bSMauro Carvalho Chehab status |= ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE; 1029ad85094bSMauro Carvalho Chehab status |= ATOMISP_FOCUS_HP_COMPLETE; 1030ad85094bSMauro Carvalho Chehab } 1031ad85094bSMauro Carvalho Chehab 1032ad85094bSMauro Carvalho Chehab *value = status; 1033ad85094bSMauro Carvalho Chehab 1034ad85094bSMauro Carvalho Chehab return 0; 1035ad85094bSMauro Carvalho Chehab } 1036ad85094bSMauro Carvalho Chehab 1037ad85094bSMauro Carvalho Chehab static int ov5693_q_focus_abs(struct v4l2_subdev *sd, s32 *value) 1038ad85094bSMauro Carvalho Chehab { 1039ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1040ad85094bSMauro Carvalho Chehab s32 val; 1041ad85094bSMauro Carvalho Chehab 1042ad85094bSMauro Carvalho Chehab ov5693_q_focus_status(sd, &val); 1043ad85094bSMauro Carvalho Chehab 1044ad85094bSMauro Carvalho Chehab if (val & ATOMISP_FOCUS_STATUS_MOVING) 1045ad85094bSMauro Carvalho Chehab *value = dev->focus - dev->number_of_steps; 1046ad85094bSMauro Carvalho Chehab else 1047ad85094bSMauro Carvalho Chehab *value = dev->focus; 1048ad85094bSMauro Carvalho Chehab 1049ad85094bSMauro Carvalho Chehab return 0; 1050ad85094bSMauro Carvalho Chehab } 1051ad85094bSMauro Carvalho Chehab 1052ad85094bSMauro Carvalho Chehab static int ov5693_t_vcm_slew(struct v4l2_subdev *sd, s32 value) 1053ad85094bSMauro Carvalho Chehab { 1054ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1055ad85094bSMauro Carvalho Chehab 1056ad85094bSMauro Carvalho Chehab dev->number_of_steps = value; 1057ad85094bSMauro Carvalho Chehab dev->vcm_update = true; 1058ad85094bSMauro Carvalho Chehab return 0; 1059ad85094bSMauro Carvalho Chehab } 1060ad85094bSMauro Carvalho Chehab 1061ad85094bSMauro Carvalho Chehab static int ov5693_t_vcm_timing(struct v4l2_subdev *sd, s32 value) 1062ad85094bSMauro Carvalho Chehab { 1063ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1064ad85094bSMauro Carvalho Chehab 1065ad85094bSMauro Carvalho Chehab dev->number_of_steps = value; 1066ad85094bSMauro Carvalho Chehab dev->vcm_update = true; 1067ad85094bSMauro Carvalho Chehab return 0; 1068ad85094bSMauro Carvalho Chehab } 1069ad85094bSMauro Carvalho Chehab 1070ad85094bSMauro Carvalho Chehab static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl) 1071ad85094bSMauro Carvalho Chehab { 1072ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = 1073ad85094bSMauro Carvalho Chehab container_of(ctrl->handler, struct ov5693_device, ctrl_handler); 1074ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(&dev->sd); 1075ad85094bSMauro Carvalho Chehab int ret = 0; 1076ad85094bSMauro Carvalho Chehab 1077ad85094bSMauro Carvalho Chehab switch (ctrl->id) { 1078ad85094bSMauro Carvalho Chehab case V4L2_CID_FOCUS_ABSOLUTE: 1079ad85094bSMauro Carvalho Chehab dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n", 1080ad85094bSMauro Carvalho Chehab __func__, ctrl->val); 1081ad85094bSMauro Carvalho Chehab ret = ov5693_t_focus_abs(&dev->sd, ctrl->val); 1082ad85094bSMauro Carvalho Chehab break; 1083ad85094bSMauro Carvalho Chehab case V4L2_CID_FOCUS_RELATIVE: 1084ad85094bSMauro Carvalho Chehab dev_dbg(&client->dev, "%s: CID_FOCUS_RELATIVE:%d.\n", 1085ad85094bSMauro Carvalho Chehab __func__, ctrl->val); 1086ad85094bSMauro Carvalho Chehab ret = ov5693_t_focus_rel(&dev->sd, ctrl->val); 1087ad85094bSMauro Carvalho Chehab break; 1088ad85094bSMauro Carvalho Chehab case V4L2_CID_VCM_SLEW: 1089ad85094bSMauro Carvalho Chehab ret = ov5693_t_vcm_slew(&dev->sd, ctrl->val); 1090ad85094bSMauro Carvalho Chehab break; 1091abbd669dSMauro Carvalho Chehab case V4L2_CID_VCM_TIMING: 1092ad85094bSMauro Carvalho Chehab ret = ov5693_t_vcm_timing(&dev->sd, ctrl->val); 1093ad85094bSMauro Carvalho Chehab break; 1094ad85094bSMauro Carvalho Chehab default: 1095ad85094bSMauro Carvalho Chehab ret = -EINVAL; 1096ad85094bSMauro Carvalho Chehab } 1097ad85094bSMauro Carvalho Chehab return ret; 1098ad85094bSMauro Carvalho Chehab } 1099ad85094bSMauro Carvalho Chehab 1100ad85094bSMauro Carvalho Chehab static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 1101ad85094bSMauro Carvalho Chehab { 1102ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = 1103ad85094bSMauro Carvalho Chehab container_of(ctrl->handler, struct ov5693_device, ctrl_handler); 1104ad85094bSMauro Carvalho Chehab int ret = 0; 1105ad85094bSMauro Carvalho Chehab 1106ad85094bSMauro Carvalho Chehab switch (ctrl->id) { 1107ad85094bSMauro Carvalho Chehab case V4L2_CID_EXPOSURE_ABSOLUTE: 1108ad85094bSMauro Carvalho Chehab ret = ov5693_q_exposure(&dev->sd, &ctrl->val); 1109ad85094bSMauro Carvalho Chehab break; 1110ad85094bSMauro Carvalho Chehab case V4L2_CID_FOCAL_ABSOLUTE: 1111ad85094bSMauro Carvalho Chehab ret = ov5693_g_focal(&dev->sd, &ctrl->val); 1112ad85094bSMauro Carvalho Chehab break; 1113ad85094bSMauro Carvalho Chehab case V4L2_CID_FNUMBER_ABSOLUTE: 1114ad85094bSMauro Carvalho Chehab ret = ov5693_g_fnumber(&dev->sd, &ctrl->val); 1115ad85094bSMauro Carvalho Chehab break; 1116ad85094bSMauro Carvalho Chehab case V4L2_CID_FNUMBER_RANGE: 1117ad85094bSMauro Carvalho Chehab ret = ov5693_g_fnumber_range(&dev->sd, &ctrl->val); 1118ad85094bSMauro Carvalho Chehab break; 1119ad85094bSMauro Carvalho Chehab case V4L2_CID_FOCUS_ABSOLUTE: 1120ad85094bSMauro Carvalho Chehab ret = ov5693_q_focus_abs(&dev->sd, &ctrl->val); 1121ad85094bSMauro Carvalho Chehab break; 1122ad85094bSMauro Carvalho Chehab case V4L2_CID_FOCUS_STATUS: 1123ad85094bSMauro Carvalho Chehab ret = ov5693_q_focus_status(&dev->sd, &ctrl->val); 1124ad85094bSMauro Carvalho Chehab break; 1125ad85094bSMauro Carvalho Chehab case V4L2_CID_BIN_FACTOR_HORZ: 1126ad85094bSMauro Carvalho Chehab ret = ov5693_g_bin_factor_x(&dev->sd, &ctrl->val); 1127ad85094bSMauro Carvalho Chehab break; 1128ad85094bSMauro Carvalho Chehab case V4L2_CID_BIN_FACTOR_VERT: 1129ad85094bSMauro Carvalho Chehab ret = ov5693_g_bin_factor_y(&dev->sd, &ctrl->val); 1130ad85094bSMauro Carvalho Chehab break; 1131ad85094bSMauro Carvalho Chehab default: 1132ad85094bSMauro Carvalho Chehab ret = -EINVAL; 1133ad85094bSMauro Carvalho Chehab } 1134ad85094bSMauro Carvalho Chehab 1135ad85094bSMauro Carvalho Chehab return ret; 1136ad85094bSMauro Carvalho Chehab } 1137ad85094bSMauro Carvalho Chehab 1138ad85094bSMauro Carvalho Chehab static const struct v4l2_ctrl_ops ctrl_ops = { 1139ad85094bSMauro Carvalho Chehab .s_ctrl = ov5693_s_ctrl, 1140ad85094bSMauro Carvalho Chehab .g_volatile_ctrl = ov5693_g_volatile_ctrl 1141ad85094bSMauro Carvalho Chehab }; 1142ad85094bSMauro Carvalho Chehab 1143ad85094bSMauro Carvalho Chehab static const struct v4l2_ctrl_config ov5693_controls[] = { 1144ad85094bSMauro Carvalho Chehab { 1145ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1146ad85094bSMauro Carvalho Chehab .id = V4L2_CID_EXPOSURE_ABSOLUTE, 1147ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1148ad85094bSMauro Carvalho Chehab .name = "exposure", 1149ad85094bSMauro Carvalho Chehab .min = 0x0, 1150ad85094bSMauro Carvalho Chehab .max = 0xffff, 1151ad85094bSMauro Carvalho Chehab .step = 0x01, 1152ad85094bSMauro Carvalho Chehab .def = 0x00, 1153ad85094bSMauro Carvalho Chehab .flags = 0, 1154ad85094bSMauro Carvalho Chehab }, 1155ad85094bSMauro Carvalho Chehab { 1156ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1157ad85094bSMauro Carvalho Chehab .id = V4L2_CID_FOCAL_ABSOLUTE, 1158ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1159ad85094bSMauro Carvalho Chehab .name = "focal length", 1160ad85094bSMauro Carvalho Chehab .min = OV5693_FOCAL_LENGTH_DEFAULT, 1161ad85094bSMauro Carvalho Chehab .max = OV5693_FOCAL_LENGTH_DEFAULT, 1162ad85094bSMauro Carvalho Chehab .step = 0x01, 1163ad85094bSMauro Carvalho Chehab .def = OV5693_FOCAL_LENGTH_DEFAULT, 1164ad85094bSMauro Carvalho Chehab .flags = 0, 1165ad85094bSMauro Carvalho Chehab }, 1166ad85094bSMauro Carvalho Chehab { 1167ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1168ad85094bSMauro Carvalho Chehab .id = V4L2_CID_FNUMBER_ABSOLUTE, 1169ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1170ad85094bSMauro Carvalho Chehab .name = "f-number", 1171ad85094bSMauro Carvalho Chehab .min = OV5693_F_NUMBER_DEFAULT, 1172ad85094bSMauro Carvalho Chehab .max = OV5693_F_NUMBER_DEFAULT, 1173ad85094bSMauro Carvalho Chehab .step = 0x01, 1174ad85094bSMauro Carvalho Chehab .def = OV5693_F_NUMBER_DEFAULT, 1175ad85094bSMauro Carvalho Chehab .flags = 0, 1176ad85094bSMauro Carvalho Chehab }, 1177ad85094bSMauro Carvalho Chehab { 1178ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1179ad85094bSMauro Carvalho Chehab .id = V4L2_CID_FNUMBER_RANGE, 1180ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1181ad85094bSMauro Carvalho Chehab .name = "f-number range", 1182ad85094bSMauro Carvalho Chehab .min = OV5693_F_NUMBER_RANGE, 1183ad85094bSMauro Carvalho Chehab .max = OV5693_F_NUMBER_RANGE, 1184ad85094bSMauro Carvalho Chehab .step = 0x01, 1185ad85094bSMauro Carvalho Chehab .def = OV5693_F_NUMBER_RANGE, 1186ad85094bSMauro Carvalho Chehab .flags = 0, 1187ad85094bSMauro Carvalho Chehab }, 1188ad85094bSMauro Carvalho Chehab { 1189ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1190ad85094bSMauro Carvalho Chehab .id = V4L2_CID_FOCUS_ABSOLUTE, 1191ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1192ad85094bSMauro Carvalho Chehab .name = "focus move absolute", 1193ad85094bSMauro Carvalho Chehab .min = 0, 1194ad85094bSMauro Carvalho Chehab .max = OV5693_VCM_MAX_FOCUS_POS, 1195ad85094bSMauro Carvalho Chehab .step = 1, 1196ad85094bSMauro Carvalho Chehab .def = 0, 1197ad85094bSMauro Carvalho Chehab .flags = 0, 1198ad85094bSMauro Carvalho Chehab }, 1199ad85094bSMauro Carvalho Chehab { 1200ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1201ad85094bSMauro Carvalho Chehab .id = V4L2_CID_FOCUS_RELATIVE, 1202ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1203ad85094bSMauro Carvalho Chehab .name = "focus move relative", 1204ad85094bSMauro Carvalho Chehab .min = OV5693_VCM_MAX_FOCUS_NEG, 1205ad85094bSMauro Carvalho Chehab .max = OV5693_VCM_MAX_FOCUS_POS, 1206ad85094bSMauro Carvalho Chehab .step = 1, 1207ad85094bSMauro Carvalho Chehab .def = 0, 1208ad85094bSMauro Carvalho Chehab .flags = 0, 1209ad85094bSMauro Carvalho Chehab }, 1210ad85094bSMauro Carvalho Chehab { 1211ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1212ad85094bSMauro Carvalho Chehab .id = V4L2_CID_FOCUS_STATUS, 1213ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1214ad85094bSMauro Carvalho Chehab .name = "focus status", 1215ad85094bSMauro Carvalho Chehab .min = 0, 1216ad85094bSMauro Carvalho Chehab .max = 100, /* allow enum to grow in the future */ 1217ad85094bSMauro Carvalho Chehab .step = 1, 1218ad85094bSMauro Carvalho Chehab .def = 0, 1219ad85094bSMauro Carvalho Chehab .flags = 0, 1220ad85094bSMauro Carvalho Chehab }, 1221ad85094bSMauro Carvalho Chehab { 1222ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1223ad85094bSMauro Carvalho Chehab .id = V4L2_CID_VCM_SLEW, 1224ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1225ad85094bSMauro Carvalho Chehab .name = "vcm slew", 1226ad85094bSMauro Carvalho Chehab .min = 0, 1227ad85094bSMauro Carvalho Chehab .max = OV5693_VCM_SLEW_STEP_MAX, 1228ad85094bSMauro Carvalho Chehab .step = 1, 1229ad85094bSMauro Carvalho Chehab .def = 0, 1230ad85094bSMauro Carvalho Chehab .flags = 0, 1231ad85094bSMauro Carvalho Chehab }, 1232ad85094bSMauro Carvalho Chehab { 1233ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1234abbd669dSMauro Carvalho Chehab .id = V4L2_CID_VCM_TIMING, 1235ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1236ad85094bSMauro Carvalho Chehab .name = "vcm step time", 1237ad85094bSMauro Carvalho Chehab .min = 0, 1238ad85094bSMauro Carvalho Chehab .max = OV5693_VCM_SLEW_TIME_MAX, 1239ad85094bSMauro Carvalho Chehab .step = 1, 1240ad85094bSMauro Carvalho Chehab .def = 0, 1241ad85094bSMauro Carvalho Chehab .flags = 0, 1242ad85094bSMauro Carvalho Chehab }, 1243ad85094bSMauro Carvalho Chehab { 1244ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1245ad85094bSMauro Carvalho Chehab .id = V4L2_CID_BIN_FACTOR_HORZ, 1246ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1247ad85094bSMauro Carvalho Chehab .name = "horizontal binning factor", 1248ad85094bSMauro Carvalho Chehab .min = 0, 1249ad85094bSMauro Carvalho Chehab .max = OV5693_BIN_FACTOR_MAX, 1250ad85094bSMauro Carvalho Chehab .step = 1, 1251ad85094bSMauro Carvalho Chehab .def = 0, 1252ad85094bSMauro Carvalho Chehab .flags = 0, 1253ad85094bSMauro Carvalho Chehab }, 1254ad85094bSMauro Carvalho Chehab { 1255ad85094bSMauro Carvalho Chehab .ops = &ctrl_ops, 1256ad85094bSMauro Carvalho Chehab .id = V4L2_CID_BIN_FACTOR_VERT, 1257ad85094bSMauro Carvalho Chehab .type = V4L2_CTRL_TYPE_INTEGER, 1258ad85094bSMauro Carvalho Chehab .name = "vertical binning factor", 1259ad85094bSMauro Carvalho Chehab .min = 0, 1260ad85094bSMauro Carvalho Chehab .max = OV5693_BIN_FACTOR_MAX, 1261ad85094bSMauro Carvalho Chehab .step = 1, 1262ad85094bSMauro Carvalho Chehab .def = 0, 1263ad85094bSMauro Carvalho Chehab .flags = 0, 1264ad85094bSMauro Carvalho Chehab }, 1265ad85094bSMauro Carvalho Chehab }; 1266ad85094bSMauro Carvalho Chehab 1267ad85094bSMauro Carvalho Chehab static int ov5693_init(struct v4l2_subdev *sd) 1268ad85094bSMauro Carvalho Chehab { 1269ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1270ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1271ad85094bSMauro Carvalho Chehab int ret; 1272ad85094bSMauro Carvalho Chehab 1273ad85094bSMauro Carvalho Chehab pr_info("%s\n", __func__); 1274ad85094bSMauro Carvalho Chehab mutex_lock(&dev->input_lock); 1275ad85094bSMauro Carvalho Chehab dev->vcm_update = false; 1276ad85094bSMauro Carvalho Chehab 1277ad85094bSMauro Carvalho Chehab if (dev->vcm == VCM_AD5823) { 1278ad85094bSMauro Carvalho Chehab ret = vcm_ad_i2c_wr8(client, 0x01, 0x01); /* vcm init test */ 1279ad85094bSMauro Carvalho Chehab if (ret) 1280ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1281ad85094bSMauro Carvalho Chehab "vcm reset failed\n"); 1282ad85094bSMauro Carvalho Chehab /*change the mode*/ 1283ad85094bSMauro Carvalho Chehab ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, 1284ad85094bSMauro Carvalho Chehab AD5823_RING_CTRL_ENABLE); 1285ad85094bSMauro Carvalho Chehab if (ret) 1286ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1287ad85094bSMauro Carvalho Chehab "vcm enable ringing failed\n"); 1288ad85094bSMauro Carvalho Chehab ret = ad5823_i2c_write(client, AD5823_REG_MODE, 1289ad85094bSMauro Carvalho Chehab AD5823_ARC_RES1); 1290ad85094bSMauro Carvalho Chehab if (ret) 1291ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1292ad85094bSMauro Carvalho Chehab "vcm change mode failed\n"); 1293ad85094bSMauro Carvalho Chehab } 1294ad85094bSMauro Carvalho Chehab 1295ad85094bSMauro Carvalho Chehab /*change initial focus value for ad5823*/ 1296ad85094bSMauro Carvalho Chehab if (dev->vcm == VCM_AD5823) { 1297ad85094bSMauro Carvalho Chehab dev->focus = AD5823_INIT_FOCUS_POS; 1298ad85094bSMauro Carvalho Chehab ov5693_t_focus_abs(sd, AD5823_INIT_FOCUS_POS); 1299ad85094bSMauro Carvalho Chehab } else { 1300ad85094bSMauro Carvalho Chehab dev->focus = 0; 1301ad85094bSMauro Carvalho Chehab ov5693_t_focus_abs(sd, 0); 1302ad85094bSMauro Carvalho Chehab } 1303ad85094bSMauro Carvalho Chehab 1304ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1305ad85094bSMauro Carvalho Chehab 1306ad85094bSMauro Carvalho Chehab return 0; 1307ad85094bSMauro Carvalho Chehab } 1308ad85094bSMauro Carvalho Chehab 1309ad85094bSMauro Carvalho Chehab static int power_ctrl(struct v4l2_subdev *sd, bool flag) 1310ad85094bSMauro Carvalho Chehab { 1311ad85094bSMauro Carvalho Chehab int ret; 1312ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1313ad85094bSMauro Carvalho Chehab 1314ad85094bSMauro Carvalho Chehab if (!dev || !dev->platform_data) 1315ad85094bSMauro Carvalho Chehab return -ENODEV; 1316ad85094bSMauro Carvalho Chehab 1317ad85094bSMauro Carvalho Chehab /* 1318ad85094bSMauro Carvalho Chehab * This driver assumes "internal DVDD, PWDNB tied to DOVDD". 1319ad85094bSMauro Carvalho Chehab * In this set up only gpio0 (XSHUTDN) should be available 1320ad85094bSMauro Carvalho Chehab * but in some products (for example ECS) gpio1 (PWDNB) is 1321ad85094bSMauro Carvalho Chehab * also available. If gpio1 is available we emulate it being 1322ad85094bSMauro Carvalho Chehab * tied to DOVDD here. 1323ad85094bSMauro Carvalho Chehab */ 1324ad85094bSMauro Carvalho Chehab if (flag) { 1325ad85094bSMauro Carvalho Chehab ret = dev->platform_data->v2p8_ctrl(sd, 1); 1326ad85094bSMauro Carvalho Chehab dev->platform_data->gpio1_ctrl(sd, 1); 1327ad85094bSMauro Carvalho Chehab if (ret == 0) { 1328ad85094bSMauro Carvalho Chehab ret = dev->platform_data->v1p8_ctrl(sd, 1); 1329ad85094bSMauro Carvalho Chehab if (ret) { 1330ad85094bSMauro Carvalho Chehab dev->platform_data->gpio1_ctrl(sd, 0); 1331ad85094bSMauro Carvalho Chehab ret = dev->platform_data->v2p8_ctrl(sd, 0); 1332ad85094bSMauro Carvalho Chehab } 1333ad85094bSMauro Carvalho Chehab } 1334ad85094bSMauro Carvalho Chehab } else { 1335ad85094bSMauro Carvalho Chehab dev->platform_data->gpio1_ctrl(sd, 0); 1336ad85094bSMauro Carvalho Chehab ret = dev->platform_data->v1p8_ctrl(sd, 0); 1337ad85094bSMauro Carvalho Chehab ret |= dev->platform_data->v2p8_ctrl(sd, 0); 1338ad85094bSMauro Carvalho Chehab } 1339ad85094bSMauro Carvalho Chehab 1340ad85094bSMauro Carvalho Chehab return ret; 1341ad85094bSMauro Carvalho Chehab } 1342ad85094bSMauro Carvalho Chehab 1343ad85094bSMauro Carvalho Chehab static int gpio_ctrl(struct v4l2_subdev *sd, bool flag) 1344ad85094bSMauro Carvalho Chehab { 1345ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1346ad85094bSMauro Carvalho Chehab 1347ad85094bSMauro Carvalho Chehab if (!dev || !dev->platform_data) 1348ad85094bSMauro Carvalho Chehab return -ENODEV; 1349ad85094bSMauro Carvalho Chehab 1350ad85094bSMauro Carvalho Chehab return dev->platform_data->gpio0_ctrl(sd, flag); 1351ad85094bSMauro Carvalho Chehab } 1352ad85094bSMauro Carvalho Chehab 1353ad85094bSMauro Carvalho Chehab static int __power_up(struct v4l2_subdev *sd) 1354ad85094bSMauro Carvalho Chehab { 1355ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1356ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1357ad85094bSMauro Carvalho Chehab int ret; 1358ad85094bSMauro Carvalho Chehab 1359ad85094bSMauro Carvalho Chehab if (!dev->platform_data) { 1360ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1361ad85094bSMauro Carvalho Chehab "no camera_sensor_platform_data"); 1362ad85094bSMauro Carvalho Chehab return -ENODEV; 1363ad85094bSMauro Carvalho Chehab } 1364ad85094bSMauro Carvalho Chehab 1365ad85094bSMauro Carvalho Chehab /* power control */ 1366ad85094bSMauro Carvalho Chehab ret = power_ctrl(sd, 1); 1367ad85094bSMauro Carvalho Chehab if (ret) 1368ad85094bSMauro Carvalho Chehab goto fail_power; 1369ad85094bSMauro Carvalho Chehab 1370ad85094bSMauro Carvalho Chehab /* according to DS, at least 5ms is needed between DOVDD and PWDN */ 1371ad85094bSMauro Carvalho Chehab /* add this delay time to 10~11ms*/ 1372ad85094bSMauro Carvalho Chehab usleep_range(10000, 11000); 1373ad85094bSMauro Carvalho Chehab 1374ad85094bSMauro Carvalho Chehab /* gpio ctrl */ 1375ad85094bSMauro Carvalho Chehab ret = gpio_ctrl(sd, 1); 1376ad85094bSMauro Carvalho Chehab if (ret) { 1377ad85094bSMauro Carvalho Chehab ret = gpio_ctrl(sd, 1); 1378ad85094bSMauro Carvalho Chehab if (ret) 1379ad85094bSMauro Carvalho Chehab goto fail_power; 1380ad85094bSMauro Carvalho Chehab } 1381ad85094bSMauro Carvalho Chehab 1382ad85094bSMauro Carvalho Chehab /* flis clock control */ 1383ad85094bSMauro Carvalho Chehab ret = dev->platform_data->flisclk_ctrl(sd, 1); 1384ad85094bSMauro Carvalho Chehab if (ret) 1385ad85094bSMauro Carvalho Chehab goto fail_clk; 1386ad85094bSMauro Carvalho Chehab 1387ad85094bSMauro Carvalho Chehab __cci_delay(up_delay); 1388ad85094bSMauro Carvalho Chehab 1389ad85094bSMauro Carvalho Chehab return 0; 1390ad85094bSMauro Carvalho Chehab 1391ad85094bSMauro Carvalho Chehab fail_clk: 1392ad85094bSMauro Carvalho Chehab gpio_ctrl(sd, 0); 1393ad85094bSMauro Carvalho Chehab fail_power: 1394ad85094bSMauro Carvalho Chehab power_ctrl(sd, 0); 1395ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "sensor power-up failed\n"); 1396ad85094bSMauro Carvalho Chehab 1397ad85094bSMauro Carvalho Chehab return ret; 1398ad85094bSMauro Carvalho Chehab } 1399ad85094bSMauro Carvalho Chehab 1400ad85094bSMauro Carvalho Chehab static int power_down(struct v4l2_subdev *sd) 1401ad85094bSMauro Carvalho Chehab { 1402ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1403ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1404ad85094bSMauro Carvalho Chehab int ret = 0; 1405ad85094bSMauro Carvalho Chehab 1406ad85094bSMauro Carvalho Chehab dev->focus = OV5693_INVALID_CONFIG; 1407ad85094bSMauro Carvalho Chehab if (!dev->platform_data) { 1408ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1409ad85094bSMauro Carvalho Chehab "no camera_sensor_platform_data"); 1410ad85094bSMauro Carvalho Chehab return -ENODEV; 1411ad85094bSMauro Carvalho Chehab } 1412ad85094bSMauro Carvalho Chehab 1413ad85094bSMauro Carvalho Chehab ret = dev->platform_data->flisclk_ctrl(sd, 0); 1414ad85094bSMauro Carvalho Chehab if (ret) 1415ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "flisclk failed\n"); 1416ad85094bSMauro Carvalho Chehab 1417ad85094bSMauro Carvalho Chehab /* gpio ctrl */ 1418ad85094bSMauro Carvalho Chehab ret = gpio_ctrl(sd, 0); 1419ad85094bSMauro Carvalho Chehab if (ret) { 1420ad85094bSMauro Carvalho Chehab ret = gpio_ctrl(sd, 0); 1421ad85094bSMauro Carvalho Chehab if (ret) 1422ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "gpio failed 2\n"); 1423ad85094bSMauro Carvalho Chehab } 1424ad85094bSMauro Carvalho Chehab 1425ad85094bSMauro Carvalho Chehab /* power control */ 1426ad85094bSMauro Carvalho Chehab ret = power_ctrl(sd, 0); 1427ad85094bSMauro Carvalho Chehab if (ret) 1428ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "vprog failed.\n"); 1429ad85094bSMauro Carvalho Chehab 1430ad85094bSMauro Carvalho Chehab return ret; 1431ad85094bSMauro Carvalho Chehab } 1432ad85094bSMauro Carvalho Chehab 1433ad85094bSMauro Carvalho Chehab static int power_up(struct v4l2_subdev *sd) 1434ad85094bSMauro Carvalho Chehab { 1435ad85094bSMauro Carvalho Chehab static const int retry_count = 4; 1436ad85094bSMauro Carvalho Chehab int i, ret; 1437ad85094bSMauro Carvalho Chehab 1438ad85094bSMauro Carvalho Chehab for (i = 0; i < retry_count; i++) { 1439ad85094bSMauro Carvalho Chehab ret = __power_up(sd); 1440ad85094bSMauro Carvalho Chehab if (!ret) 1441ad85094bSMauro Carvalho Chehab return 0; 1442ad85094bSMauro Carvalho Chehab 1443ad85094bSMauro Carvalho Chehab power_down(sd); 1444ad85094bSMauro Carvalho Chehab } 1445ad85094bSMauro Carvalho Chehab return ret; 1446ad85094bSMauro Carvalho Chehab } 1447ad85094bSMauro Carvalho Chehab 1448ad85094bSMauro Carvalho Chehab static int ov5693_s_power(struct v4l2_subdev *sd, int on) 1449ad85094bSMauro Carvalho Chehab { 1450ad85094bSMauro Carvalho Chehab int ret; 1451ad85094bSMauro Carvalho Chehab 1452ad85094bSMauro Carvalho Chehab pr_info("%s: on %d\n", __func__, on); 1453ad85094bSMauro Carvalho Chehab if (on == 0) 1454ad85094bSMauro Carvalho Chehab return power_down(sd); 1455ad85094bSMauro Carvalho Chehab else { 1456ad85094bSMauro Carvalho Chehab ret = power_up(sd); 1457ad85094bSMauro Carvalho Chehab if (!ret) { 1458ad85094bSMauro Carvalho Chehab ret = ov5693_init(sd); 1459ad85094bSMauro Carvalho Chehab /* restore settings */ 1460ad85094bSMauro Carvalho Chehab ov5693_res = ov5693_res_preview; 1461ad85094bSMauro Carvalho Chehab N_RES = N_RES_PREVIEW; 1462ad85094bSMauro Carvalho Chehab } 1463ad85094bSMauro Carvalho Chehab } 1464ad85094bSMauro Carvalho Chehab return ret; 1465ad85094bSMauro Carvalho Chehab } 1466ad85094bSMauro Carvalho Chehab 1467ad85094bSMauro Carvalho Chehab /* 1468ad85094bSMauro Carvalho Chehab * distance - calculate the distance 1469ad85094bSMauro Carvalho Chehab * @res: resolution 1470ad85094bSMauro Carvalho Chehab * @w: width 1471ad85094bSMauro Carvalho Chehab * @h: height 1472ad85094bSMauro Carvalho Chehab * 1473ad85094bSMauro Carvalho Chehab * Get the gap between res_w/res_h and w/h. 1474ad85094bSMauro Carvalho Chehab * distance = (res_w/res_h - w/h) / (w/h) * 8192 1475ad85094bSMauro Carvalho Chehab * res->width/height smaller than w/h wouldn't be considered. 1476ad85094bSMauro Carvalho Chehab * The gap of ratio larger than 1/8 wouldn't be considered. 1477ad85094bSMauro Carvalho Chehab * Returns the value of gap or -1 if fail. 1478ad85094bSMauro Carvalho Chehab */ 1479ad85094bSMauro Carvalho Chehab #define LARGEST_ALLOWED_RATIO_MISMATCH 1024 1480ad85094bSMauro Carvalho Chehab static int distance(struct ov5693_resolution *res, u32 w, u32 h) 1481ad85094bSMauro Carvalho Chehab { 1482ad85094bSMauro Carvalho Chehab int ratio; 1483ad85094bSMauro Carvalho Chehab int distance; 1484ad85094bSMauro Carvalho Chehab 1485ad85094bSMauro Carvalho Chehab if (w == 0 || h == 0 || 1486ad85094bSMauro Carvalho Chehab res->width < w || res->height < h) 1487ad85094bSMauro Carvalho Chehab return -1; 1488ad85094bSMauro Carvalho Chehab 1489ad85094bSMauro Carvalho Chehab ratio = res->width << 13; 1490ad85094bSMauro Carvalho Chehab ratio /= w; 1491ad85094bSMauro Carvalho Chehab ratio *= h; 1492ad85094bSMauro Carvalho Chehab ratio /= res->height; 1493ad85094bSMauro Carvalho Chehab 1494ad85094bSMauro Carvalho Chehab distance = abs(ratio - 8192); 1495ad85094bSMauro Carvalho Chehab 1496ad85094bSMauro Carvalho Chehab if (distance > LARGEST_ALLOWED_RATIO_MISMATCH) 1497ad85094bSMauro Carvalho Chehab return -1; 1498ad85094bSMauro Carvalho Chehab 1499ad85094bSMauro Carvalho Chehab return distance; 1500ad85094bSMauro Carvalho Chehab } 1501ad85094bSMauro Carvalho Chehab 1502ad85094bSMauro Carvalho Chehab /* Return the nearest higher resolution index 1503ad85094bSMauro Carvalho Chehab * Firstly try to find the approximate aspect ratio resolution 1504ad85094bSMauro Carvalho Chehab * If we find multiple same AR resolutions, choose the 1505ad85094bSMauro Carvalho Chehab * minimal size. 1506ad85094bSMauro Carvalho Chehab */ 1507ad85094bSMauro Carvalho Chehab static int nearest_resolution_index(int w, int h) 1508ad85094bSMauro Carvalho Chehab { 1509ad85094bSMauro Carvalho Chehab int i; 1510ad85094bSMauro Carvalho Chehab int idx = -1; 1511ad85094bSMauro Carvalho Chehab int dist; 1512ad85094bSMauro Carvalho Chehab int min_dist = INT_MAX; 1513ad85094bSMauro Carvalho Chehab int min_res_w = INT_MAX; 1514ad85094bSMauro Carvalho Chehab struct ov5693_resolution *tmp_res = NULL; 1515ad85094bSMauro Carvalho Chehab 1516ad85094bSMauro Carvalho Chehab for (i = 0; i < N_RES; i++) { 1517ad85094bSMauro Carvalho Chehab tmp_res = &ov5693_res[i]; 1518ad85094bSMauro Carvalho Chehab dist = distance(tmp_res, w, h); 1519ad85094bSMauro Carvalho Chehab if (dist == -1) 1520ad85094bSMauro Carvalho Chehab continue; 1521ad85094bSMauro Carvalho Chehab if (dist < min_dist) { 1522ad85094bSMauro Carvalho Chehab min_dist = dist; 1523ad85094bSMauro Carvalho Chehab idx = i; 1524ad85094bSMauro Carvalho Chehab min_res_w = ov5693_res[i].width; 1525ad85094bSMauro Carvalho Chehab continue; 1526ad85094bSMauro Carvalho Chehab } 1527ad85094bSMauro Carvalho Chehab if (dist == min_dist && ov5693_res[i].width < min_res_w) 1528ad85094bSMauro Carvalho Chehab idx = i; 1529ad85094bSMauro Carvalho Chehab } 1530ad85094bSMauro Carvalho Chehab 1531ad85094bSMauro Carvalho Chehab return idx; 1532ad85094bSMauro Carvalho Chehab } 1533ad85094bSMauro Carvalho Chehab 1534ad85094bSMauro Carvalho Chehab static int get_resolution_index(int w, int h) 1535ad85094bSMauro Carvalho Chehab { 1536ad85094bSMauro Carvalho Chehab int i; 1537ad85094bSMauro Carvalho Chehab 1538ad85094bSMauro Carvalho Chehab for (i = 0; i < N_RES; i++) { 1539ad85094bSMauro Carvalho Chehab if (w != ov5693_res[i].width) 1540ad85094bSMauro Carvalho Chehab continue; 1541ad85094bSMauro Carvalho Chehab if (h != ov5693_res[i].height) 1542ad85094bSMauro Carvalho Chehab continue; 1543ad85094bSMauro Carvalho Chehab 1544ad85094bSMauro Carvalho Chehab return i; 1545ad85094bSMauro Carvalho Chehab } 1546ad85094bSMauro Carvalho Chehab 1547ad85094bSMauro Carvalho Chehab return -1; 1548ad85094bSMauro Carvalho Chehab } 1549ad85094bSMauro Carvalho Chehab 1550ad85094bSMauro Carvalho Chehab /* TODO: remove it. */ 1551ad85094bSMauro Carvalho Chehab static int startup(struct v4l2_subdev *sd) 1552ad85094bSMauro Carvalho Chehab { 1553ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1554ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1555ad85094bSMauro Carvalho Chehab int ret = 0; 1556ad85094bSMauro Carvalho Chehab 1557ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, 1558ad85094bSMauro Carvalho Chehab OV5693_SW_RESET, 0x01); 1559ad85094bSMauro Carvalho Chehab if (ret) { 1560ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 reset err.\n"); 1561ad85094bSMauro Carvalho Chehab return ret; 1562ad85094bSMauro Carvalho Chehab } 1563ad85094bSMauro Carvalho Chehab 1564ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg_array(client, ov5693_global_setting); 1565ad85094bSMauro Carvalho Chehab if (ret) { 1566ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 write register err.\n"); 1567ad85094bSMauro Carvalho Chehab return ret; 1568ad85094bSMauro Carvalho Chehab } 1569ad85094bSMauro Carvalho Chehab 1570ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg_array(client, ov5693_res[dev->fmt_idx].regs); 1571ad85094bSMauro Carvalho Chehab if (ret) { 1572ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 write register err.\n"); 1573ad85094bSMauro Carvalho Chehab return ret; 1574ad85094bSMauro Carvalho Chehab } 1575ad85094bSMauro Carvalho Chehab 1576ad85094bSMauro Carvalho Chehab return ret; 1577ad85094bSMauro Carvalho Chehab } 1578ad85094bSMauro Carvalho Chehab 1579ad85094bSMauro Carvalho Chehab static int ov5693_set_fmt(struct v4l2_subdev *sd, 1580ad85094bSMauro Carvalho Chehab struct v4l2_subdev_pad_config *cfg, 1581ad85094bSMauro Carvalho Chehab struct v4l2_subdev_format *format) 1582ad85094bSMauro Carvalho Chehab { 1583ad85094bSMauro Carvalho Chehab struct v4l2_mbus_framefmt *fmt = &format->format; 1584ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1585ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1586ad85094bSMauro Carvalho Chehab struct camera_mipi_info *ov5693_info = NULL; 1587ad85094bSMauro Carvalho Chehab int ret = 0; 1588ad85094bSMauro Carvalho Chehab int idx; 1589ad85094bSMauro Carvalho Chehab 1590ad85094bSMauro Carvalho Chehab if (format->pad) 1591ad85094bSMauro Carvalho Chehab return -EINVAL; 1592ad85094bSMauro Carvalho Chehab if (!fmt) 1593ad85094bSMauro Carvalho Chehab return -EINVAL; 1594ad85094bSMauro Carvalho Chehab ov5693_info = v4l2_get_subdev_hostdata(sd); 1595bdfe0bebSMauro Carvalho Chehab if (!ov5693_info) 1596ad85094bSMauro Carvalho Chehab return -EINVAL; 1597ad85094bSMauro Carvalho Chehab 1598ad85094bSMauro Carvalho Chehab mutex_lock(&dev->input_lock); 1599ad85094bSMauro Carvalho Chehab idx = nearest_resolution_index(fmt->width, fmt->height); 1600ad85094bSMauro Carvalho Chehab if (idx == -1) { 1601ad85094bSMauro Carvalho Chehab /* return the largest resolution */ 1602ad85094bSMauro Carvalho Chehab fmt->width = ov5693_res[N_RES - 1].width; 1603ad85094bSMauro Carvalho Chehab fmt->height = ov5693_res[N_RES - 1].height; 1604ad85094bSMauro Carvalho Chehab } else { 1605ad85094bSMauro Carvalho Chehab fmt->width = ov5693_res[idx].width; 1606ad85094bSMauro Carvalho Chehab fmt->height = ov5693_res[idx].height; 1607ad85094bSMauro Carvalho Chehab } 1608ad85094bSMauro Carvalho Chehab 1609ad85094bSMauro Carvalho Chehab fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; 1610ad85094bSMauro Carvalho Chehab if (format->which == V4L2_SUBDEV_FORMAT_TRY) { 1611ad85094bSMauro Carvalho Chehab cfg->try_fmt = *fmt; 1612ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1613ad85094bSMauro Carvalho Chehab return 0; 1614ad85094bSMauro Carvalho Chehab } 1615ad85094bSMauro Carvalho Chehab 1616ad85094bSMauro Carvalho Chehab dev->fmt_idx = get_resolution_index(fmt->width, fmt->height); 1617ad85094bSMauro Carvalho Chehab if (dev->fmt_idx == -1) { 1618ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "get resolution fail\n"); 1619ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1620ad85094bSMauro Carvalho Chehab return -EINVAL; 1621ad85094bSMauro Carvalho Chehab } 1622ad85094bSMauro Carvalho Chehab 1623ad85094bSMauro Carvalho Chehab ret = startup(sd); 1624ad85094bSMauro Carvalho Chehab if (ret) { 1625ad85094bSMauro Carvalho Chehab int i = 0; 1626ad85094bSMauro Carvalho Chehab 1627ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 startup err, retry to power up\n"); 1628ad85094bSMauro Carvalho Chehab for (i = 0; i < OV5693_POWER_UP_RETRY_NUM; i++) { 1629ad85094bSMauro Carvalho Chehab dev_err(&client->dev, 1630ad85094bSMauro Carvalho Chehab "ov5693 retry to power up %d/%d times, result: ", 1631ad85094bSMauro Carvalho Chehab i + 1, OV5693_POWER_UP_RETRY_NUM); 1632ad85094bSMauro Carvalho Chehab power_down(sd); 1633ad85094bSMauro Carvalho Chehab ret = power_up(sd); 1634ad85094bSMauro Carvalho Chehab if (!ret) { 1635ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1636ad85094bSMauro Carvalho Chehab ov5693_init(sd); 1637ad85094bSMauro Carvalho Chehab mutex_lock(&dev->input_lock); 1638ad85094bSMauro Carvalho Chehab } else { 1639ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "power up failed, continue\n"); 1640ad85094bSMauro Carvalho Chehab continue; 1641ad85094bSMauro Carvalho Chehab } 1642ad85094bSMauro Carvalho Chehab ret = startup(sd); 1643ad85094bSMauro Carvalho Chehab if (ret) { 1644ad85094bSMauro Carvalho Chehab dev_err(&client->dev, " startup FAILED!\n"); 1645ad85094bSMauro Carvalho Chehab } else { 1646ad85094bSMauro Carvalho Chehab dev_err(&client->dev, " startup SUCCESS!\n"); 1647ad85094bSMauro Carvalho Chehab break; 1648ad85094bSMauro Carvalho Chehab } 1649ad85094bSMauro Carvalho Chehab } 1650ad85094bSMauro Carvalho Chehab } 1651ad85094bSMauro Carvalho Chehab 1652ad85094bSMauro Carvalho Chehab /* 1653ad85094bSMauro Carvalho Chehab * After sensor settings are set to HW, sometimes stream is started. 1654ad85094bSMauro Carvalho Chehab * This would cause ISP timeout because ISP is not ready to receive 1655ad85094bSMauro Carvalho Chehab * data yet. So add stop streaming here. 1656ad85094bSMauro Carvalho Chehab */ 1657ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM, 1658ad85094bSMauro Carvalho Chehab OV5693_STOP_STREAMING); 1659ad85094bSMauro Carvalho Chehab if (ret) 1660ad85094bSMauro Carvalho Chehab dev_warn(&client->dev, "ov5693 stream off err\n"); 1661ad85094bSMauro Carvalho Chehab 1662ad85094bSMauro Carvalho Chehab ret = ov5693_get_intg_factor(client, ov5693_info, 1663ad85094bSMauro Carvalho Chehab &ov5693_res[dev->fmt_idx]); 1664ad85094bSMauro Carvalho Chehab if (ret) { 1665ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "failed to get integration_factor\n"); 1666ad85094bSMauro Carvalho Chehab goto err; 1667ad85094bSMauro Carvalho Chehab } 1668ad85094bSMauro Carvalho Chehab 1669ad85094bSMauro Carvalho Chehab ov5693_info->metadata_width = fmt->width * 10 / 8; 1670ad85094bSMauro Carvalho Chehab ov5693_info->metadata_height = 1; 1671ad85094bSMauro Carvalho Chehab ov5693_info->metadata_effective_width = &ov5693_embedded_effective_size; 1672ad85094bSMauro Carvalho Chehab 1673ad85094bSMauro Carvalho Chehab err: 1674ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1675ad85094bSMauro Carvalho Chehab return ret; 1676ad85094bSMauro Carvalho Chehab } 1677bdfe0bebSMauro Carvalho Chehab 1678ad85094bSMauro Carvalho Chehab static int ov5693_get_fmt(struct v4l2_subdev *sd, 1679ad85094bSMauro Carvalho Chehab struct v4l2_subdev_pad_config *cfg, 1680ad85094bSMauro Carvalho Chehab struct v4l2_subdev_format *format) 1681ad85094bSMauro Carvalho Chehab { 1682ad85094bSMauro Carvalho Chehab struct v4l2_mbus_framefmt *fmt = &format->format; 1683ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1684ad85094bSMauro Carvalho Chehab 1685ad85094bSMauro Carvalho Chehab if (format->pad) 1686ad85094bSMauro Carvalho Chehab return -EINVAL; 1687ad85094bSMauro Carvalho Chehab 1688ad85094bSMauro Carvalho Chehab if (!fmt) 1689ad85094bSMauro Carvalho Chehab return -EINVAL; 1690ad85094bSMauro Carvalho Chehab 1691ad85094bSMauro Carvalho Chehab fmt->width = ov5693_res[dev->fmt_idx].width; 1692ad85094bSMauro Carvalho Chehab fmt->height = ov5693_res[dev->fmt_idx].height; 1693ad85094bSMauro Carvalho Chehab fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; 1694ad85094bSMauro Carvalho Chehab 1695ad85094bSMauro Carvalho Chehab return 0; 1696ad85094bSMauro Carvalho Chehab } 1697ad85094bSMauro Carvalho Chehab 1698ad85094bSMauro Carvalho Chehab static int ov5693_detect(struct i2c_client *client) 1699ad85094bSMauro Carvalho Chehab { 1700ad85094bSMauro Carvalho Chehab struct i2c_adapter *adapter = client->adapter; 1701ad85094bSMauro Carvalho Chehab u16 high, low; 1702ad85094bSMauro Carvalho Chehab int ret; 1703ad85094bSMauro Carvalho Chehab u16 id; 1704ad85094bSMauro Carvalho Chehab u8 revision; 1705ad85094bSMauro Carvalho Chehab 1706ad85094bSMauro Carvalho Chehab if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) 1707ad85094bSMauro Carvalho Chehab return -ENODEV; 1708ad85094bSMauro Carvalho Chehab 1709ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_8BIT, 1710ad85094bSMauro Carvalho Chehab OV5693_SC_CMMN_CHIP_ID_H, &high); 1711ad85094bSMauro Carvalho Chehab if (ret) { 1712ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "sensor_id_high = 0x%x\n", high); 1713ad85094bSMauro Carvalho Chehab return -ENODEV; 1714ad85094bSMauro Carvalho Chehab } 1715ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_8BIT, 1716ad85094bSMauro Carvalho Chehab OV5693_SC_CMMN_CHIP_ID_L, &low); 1717ad85094bSMauro Carvalho Chehab id = ((((u16)high) << 8) | (u16)low); 1718ad85094bSMauro Carvalho Chehab 1719ad85094bSMauro Carvalho Chehab if (id != OV5693_ID) { 1720ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "sensor ID error 0x%x\n", id); 1721ad85094bSMauro Carvalho Chehab return -ENODEV; 1722ad85094bSMauro Carvalho Chehab } 1723ad85094bSMauro Carvalho Chehab 1724ad85094bSMauro Carvalho Chehab ret = ov5693_read_reg(client, OV5693_8BIT, 1725ad85094bSMauro Carvalho Chehab OV5693_SC_CMMN_SUB_ID, &high); 1726ad85094bSMauro Carvalho Chehab revision = (u8)high & 0x0f; 1727ad85094bSMauro Carvalho Chehab 1728ad85094bSMauro Carvalho Chehab dev_dbg(&client->dev, "sensor_revision = 0x%x\n", revision); 1729ad85094bSMauro Carvalho Chehab dev_dbg(&client->dev, "detect ov5693 success\n"); 1730ad85094bSMauro Carvalho Chehab return 0; 1731ad85094bSMauro Carvalho Chehab } 1732ad85094bSMauro Carvalho Chehab 1733ad85094bSMauro Carvalho Chehab static int ov5693_s_stream(struct v4l2_subdev *sd, int enable) 1734ad85094bSMauro Carvalho Chehab { 1735ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1736ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1737ad85094bSMauro Carvalho Chehab int ret; 1738ad85094bSMauro Carvalho Chehab 1739ad85094bSMauro Carvalho Chehab mutex_lock(&dev->input_lock); 1740ad85094bSMauro Carvalho Chehab 1741ad85094bSMauro Carvalho Chehab ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM, 1742ad85094bSMauro Carvalho Chehab enable ? OV5693_START_STREAMING : 1743ad85094bSMauro Carvalho Chehab OV5693_STOP_STREAMING); 1744ad85094bSMauro Carvalho Chehab 1745ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1746ad85094bSMauro Carvalho Chehab 1747ad85094bSMauro Carvalho Chehab return ret; 1748ad85094bSMauro Carvalho Chehab } 1749ad85094bSMauro Carvalho Chehab 1750ad85094bSMauro Carvalho Chehab static int ov5693_s_config(struct v4l2_subdev *sd, 1751ad85094bSMauro Carvalho Chehab int irq, void *platform_data) 1752ad85094bSMauro Carvalho Chehab { 1753ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1754ad85094bSMauro Carvalho Chehab struct i2c_client *client = v4l2_get_subdevdata(sd); 1755ad85094bSMauro Carvalho Chehab int ret = 0; 1756ad85094bSMauro Carvalho Chehab 1757bdfe0bebSMauro Carvalho Chehab if (!platform_data) 1758ad85094bSMauro Carvalho Chehab return -ENODEV; 1759ad85094bSMauro Carvalho Chehab 1760ad85094bSMauro Carvalho Chehab dev->platform_data = 1761ad85094bSMauro Carvalho Chehab (struct camera_sensor_platform_data *)platform_data; 1762ad85094bSMauro Carvalho Chehab 1763ad85094bSMauro Carvalho Chehab mutex_lock(&dev->input_lock); 1764ad85094bSMauro Carvalho Chehab /* power off the module, then power on it in future 1765ad85094bSMauro Carvalho Chehab * as first power on by board may not fulfill the 1766ad85094bSMauro Carvalho Chehab * power on sequqence needed by the module 1767ad85094bSMauro Carvalho Chehab */ 1768ad85094bSMauro Carvalho Chehab ret = power_down(sd); 1769ad85094bSMauro Carvalho Chehab if (ret) { 1770ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 power-off err.\n"); 1771ad85094bSMauro Carvalho Chehab goto fail_power_off; 1772ad85094bSMauro Carvalho Chehab } 1773ad85094bSMauro Carvalho Chehab 1774ad85094bSMauro Carvalho Chehab ret = power_up(sd); 1775ad85094bSMauro Carvalho Chehab if (ret) { 1776ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 power-up err.\n"); 1777ad85094bSMauro Carvalho Chehab goto fail_power_on; 1778ad85094bSMauro Carvalho Chehab } 1779ad85094bSMauro Carvalho Chehab 1780ad85094bSMauro Carvalho Chehab if (!dev->vcm) 1781ad85094bSMauro Carvalho Chehab dev->vcm = vcm_detect(client); 1782ad85094bSMauro Carvalho Chehab 1783ad85094bSMauro Carvalho Chehab ret = dev->platform_data->csi_cfg(sd, 1); 1784ad85094bSMauro Carvalho Chehab if (ret) 1785ad85094bSMauro Carvalho Chehab goto fail_csi_cfg; 1786ad85094bSMauro Carvalho Chehab 1787ad85094bSMauro Carvalho Chehab /* config & detect sensor */ 1788ad85094bSMauro Carvalho Chehab ret = ov5693_detect(client); 1789ad85094bSMauro Carvalho Chehab if (ret) { 1790ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693_detect err s_config.\n"); 1791ad85094bSMauro Carvalho Chehab goto fail_csi_cfg; 1792ad85094bSMauro Carvalho Chehab } 1793ad85094bSMauro Carvalho Chehab 1794ad85094bSMauro Carvalho Chehab dev->otp_data = ov5693_otp_read(sd); 1795ad85094bSMauro Carvalho Chehab 1796ad85094bSMauro Carvalho Chehab /* turn off sensor, after probed */ 1797ad85094bSMauro Carvalho Chehab ret = power_down(sd); 1798ad85094bSMauro Carvalho Chehab if (ret) { 1799ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "ov5693 power-off err.\n"); 1800ad85094bSMauro Carvalho Chehab goto fail_csi_cfg; 1801ad85094bSMauro Carvalho Chehab } 1802ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1803ad85094bSMauro Carvalho Chehab 1804ad85094bSMauro Carvalho Chehab return ret; 1805ad85094bSMauro Carvalho Chehab 1806ad85094bSMauro Carvalho Chehab fail_csi_cfg: 1807ad85094bSMauro Carvalho Chehab dev->platform_data->csi_cfg(sd, 0); 1808ad85094bSMauro Carvalho Chehab fail_power_on: 1809ad85094bSMauro Carvalho Chehab power_down(sd); 1810ad85094bSMauro Carvalho Chehab dev_err(&client->dev, "sensor power-gating failed\n"); 1811ad85094bSMauro Carvalho Chehab fail_power_off: 1812ad85094bSMauro Carvalho Chehab mutex_unlock(&dev->input_lock); 1813ad85094bSMauro Carvalho Chehab return ret; 1814ad85094bSMauro Carvalho Chehab } 1815ad85094bSMauro Carvalho Chehab 1816ad85094bSMauro Carvalho Chehab static int ov5693_g_frame_interval(struct v4l2_subdev *sd, 1817ad85094bSMauro Carvalho Chehab struct v4l2_subdev_frame_interval *interval) 1818ad85094bSMauro Carvalho Chehab { 1819ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1820ad85094bSMauro Carvalho Chehab 1821ad85094bSMauro Carvalho Chehab interval->interval.numerator = 1; 1822ad85094bSMauro Carvalho Chehab interval->interval.denominator = ov5693_res[dev->fmt_idx].fps; 1823ad85094bSMauro Carvalho Chehab 1824ad85094bSMauro Carvalho Chehab return 0; 1825ad85094bSMauro Carvalho Chehab } 1826ad85094bSMauro Carvalho Chehab 1827ad85094bSMauro Carvalho Chehab static int ov5693_enum_mbus_code(struct v4l2_subdev *sd, 1828ad85094bSMauro Carvalho Chehab struct v4l2_subdev_pad_config *cfg, 1829ad85094bSMauro Carvalho Chehab struct v4l2_subdev_mbus_code_enum *code) 1830ad85094bSMauro Carvalho Chehab { 1831ad85094bSMauro Carvalho Chehab if (code->index >= MAX_FMTS) 1832ad85094bSMauro Carvalho Chehab return -EINVAL; 1833ad85094bSMauro Carvalho Chehab 1834ad85094bSMauro Carvalho Chehab code->code = MEDIA_BUS_FMT_SBGGR10_1X10; 1835ad85094bSMauro Carvalho Chehab return 0; 1836ad85094bSMauro Carvalho Chehab } 1837ad85094bSMauro Carvalho Chehab 1838ad85094bSMauro Carvalho Chehab static int ov5693_enum_frame_size(struct v4l2_subdev *sd, 1839ad85094bSMauro Carvalho Chehab struct v4l2_subdev_pad_config *cfg, 1840ad85094bSMauro Carvalho Chehab struct v4l2_subdev_frame_size_enum *fse) 1841ad85094bSMauro Carvalho Chehab { 1842ad85094bSMauro Carvalho Chehab int index = fse->index; 1843ad85094bSMauro Carvalho Chehab 1844ad85094bSMauro Carvalho Chehab if (index >= N_RES) 1845ad85094bSMauro Carvalho Chehab return -EINVAL; 1846ad85094bSMauro Carvalho Chehab 1847ad85094bSMauro Carvalho Chehab fse->min_width = ov5693_res[index].width; 1848ad85094bSMauro Carvalho Chehab fse->min_height = ov5693_res[index].height; 1849ad85094bSMauro Carvalho Chehab fse->max_width = ov5693_res[index].width; 1850ad85094bSMauro Carvalho Chehab fse->max_height = ov5693_res[index].height; 1851ad85094bSMauro Carvalho Chehab 1852ad85094bSMauro Carvalho Chehab return 0; 1853ad85094bSMauro Carvalho Chehab } 1854ad85094bSMauro Carvalho Chehab 1855ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_video_ops ov5693_video_ops = { 1856ad85094bSMauro Carvalho Chehab .s_stream = ov5693_s_stream, 1857ad85094bSMauro Carvalho Chehab .g_frame_interval = ov5693_g_frame_interval, 1858ad85094bSMauro Carvalho Chehab }; 1859ad85094bSMauro Carvalho Chehab 1860ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_core_ops ov5693_core_ops = { 1861ad85094bSMauro Carvalho Chehab .s_power = ov5693_s_power, 1862ad85094bSMauro Carvalho Chehab .ioctl = ov5693_ioctl, 1863ad85094bSMauro Carvalho Chehab }; 1864ad85094bSMauro Carvalho Chehab 1865ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_pad_ops ov5693_pad_ops = { 1866ad85094bSMauro Carvalho Chehab .enum_mbus_code = ov5693_enum_mbus_code, 1867ad85094bSMauro Carvalho Chehab .enum_frame_size = ov5693_enum_frame_size, 1868ad85094bSMauro Carvalho Chehab .get_fmt = ov5693_get_fmt, 1869ad85094bSMauro Carvalho Chehab .set_fmt = ov5693_set_fmt, 1870ad85094bSMauro Carvalho Chehab }; 1871ad85094bSMauro Carvalho Chehab 1872ad85094bSMauro Carvalho Chehab static const struct v4l2_subdev_ops ov5693_ops = { 1873ad85094bSMauro Carvalho Chehab .core = &ov5693_core_ops, 1874ad85094bSMauro Carvalho Chehab .video = &ov5693_video_ops, 1875ad85094bSMauro Carvalho Chehab .pad = &ov5693_pad_ops, 1876ad85094bSMauro Carvalho Chehab }; 1877ad85094bSMauro Carvalho Chehab 1878ad85094bSMauro Carvalho Chehab static int ov5693_remove(struct i2c_client *client) 1879ad85094bSMauro Carvalho Chehab { 1880ad85094bSMauro Carvalho Chehab struct v4l2_subdev *sd = i2c_get_clientdata(client); 1881ad85094bSMauro Carvalho Chehab struct ov5693_device *dev = to_ov5693_sensor(sd); 1882ad85094bSMauro Carvalho Chehab 1883ad85094bSMauro Carvalho Chehab dev_dbg(&client->dev, "ov5693_remove...\n"); 1884ad85094bSMauro Carvalho Chehab 1885ad85094bSMauro Carvalho Chehab dev->platform_data->csi_cfg(sd, 0); 1886ad85094bSMauro Carvalho Chehab 1887ad85094bSMauro Carvalho Chehab v4l2_device_unregister_subdev(sd); 1888ad85094bSMauro Carvalho Chehab 1889ad85094bSMauro Carvalho Chehab atomisp_gmin_remove_subdev(sd); 1890ad85094bSMauro Carvalho Chehab 1891ad85094bSMauro Carvalho Chehab media_entity_cleanup(&dev->sd.entity); 1892ad85094bSMauro Carvalho Chehab v4l2_ctrl_handler_free(&dev->ctrl_handler); 1893ad85094bSMauro Carvalho Chehab kfree(dev); 1894ad85094bSMauro Carvalho Chehab 1895ad85094bSMauro Carvalho Chehab return 0; 1896ad85094bSMauro Carvalho Chehab } 1897ad85094bSMauro Carvalho Chehab 1898ad85094bSMauro Carvalho Chehab static int ov5693_probe(struct i2c_client *client) 1899ad85094bSMauro Carvalho Chehab { 1900ad85094bSMauro Carvalho Chehab struct ov5693_device *dev; 1901ad85094bSMauro Carvalho Chehab int i2c; 1902ac828456SDan Carpenter int ret; 1903ad85094bSMauro Carvalho Chehab void *pdata; 1904ad85094bSMauro Carvalho Chehab unsigned int i; 1905ad85094bSMauro Carvalho Chehab 1906ad85094bSMauro Carvalho Chehab /* 1907ad85094bSMauro Carvalho Chehab * Firmware workaround: Some modules use a "secondary default" 1908ad85094bSMauro Carvalho Chehab * address of 0x10 which doesn't appear on schematics, and 1909ad85094bSMauro Carvalho Chehab * some BIOS versions haven't gotten the memo. Work around 1910ad85094bSMauro Carvalho Chehab * via config. 1911ad85094bSMauro Carvalho Chehab */ 191285df8457SMauro Carvalho Chehab i2c = gmin_get_var_int(&client->dev, false, "I2CAddr", -1); 1913ad85094bSMauro Carvalho Chehab if (i2c != -1) { 1914ad85094bSMauro Carvalho Chehab dev_info(&client->dev, 1915ad85094bSMauro Carvalho Chehab "Overriding firmware-provided I2C address (0x%x) with 0x%x\n", 1916ad85094bSMauro Carvalho Chehab client->addr, i2c); 1917ad85094bSMauro Carvalho Chehab client->addr = i2c; 1918ad85094bSMauro Carvalho Chehab } 1919ad85094bSMauro Carvalho Chehab 1920ad85094bSMauro Carvalho Chehab dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1921ad85094bSMauro Carvalho Chehab if (!dev) 1922ad85094bSMauro Carvalho Chehab return -ENOMEM; 1923ad85094bSMauro Carvalho Chehab 1924ad85094bSMauro Carvalho Chehab mutex_init(&dev->input_lock); 1925ad85094bSMauro Carvalho Chehab 1926ad85094bSMauro Carvalho Chehab dev->fmt_idx = 0; 1927bdfe0bebSMauro Carvalho Chehab v4l2_i2c_subdev_init(&dev->sd, client, &ov5693_ops); 1928ad85094bSMauro Carvalho Chehab 1929ad85094bSMauro Carvalho Chehab pdata = gmin_camera_platform_data(&dev->sd, 1930ad85094bSMauro Carvalho Chehab ATOMISP_INPUT_FORMAT_RAW_10, 1931ad85094bSMauro Carvalho Chehab atomisp_bayer_order_bggr); 1932ac828456SDan Carpenter if (!pdata) { 1933ac828456SDan Carpenter ret = -EINVAL; 1934ad85094bSMauro Carvalho Chehab goto out_free; 1935ac828456SDan Carpenter } 1936ad85094bSMauro Carvalho Chehab 1937ad85094bSMauro Carvalho Chehab ret = ov5693_s_config(&dev->sd, client->irq, pdata); 1938ad85094bSMauro Carvalho Chehab if (ret) 1939ad85094bSMauro Carvalho Chehab goto out_free; 1940ad85094bSMauro Carvalho Chehab 1941ad85094bSMauro Carvalho Chehab ret = atomisp_register_i2c_module(&dev->sd, pdata, RAW_CAMERA); 1942ad85094bSMauro Carvalho Chehab if (ret) 1943ad85094bSMauro Carvalho Chehab goto out_free; 1944ad85094bSMauro Carvalho Chehab 1945ad85094bSMauro Carvalho Chehab dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1946ad85094bSMauro Carvalho Chehab dev->pad.flags = MEDIA_PAD_FL_SOURCE; 1947ad85094bSMauro Carvalho Chehab dev->format.code = MEDIA_BUS_FMT_SBGGR10_1X10; 1948ad85094bSMauro Carvalho Chehab dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 1949ad85094bSMauro Carvalho Chehab ret = 1950ad85094bSMauro Carvalho Chehab v4l2_ctrl_handler_init(&dev->ctrl_handler, 1951ad85094bSMauro Carvalho Chehab ARRAY_SIZE(ov5693_controls)); 1952ad85094bSMauro Carvalho Chehab if (ret) { 1953ad85094bSMauro Carvalho Chehab ov5693_remove(client); 1954ad85094bSMauro Carvalho Chehab return ret; 1955ad85094bSMauro Carvalho Chehab } 1956ad85094bSMauro Carvalho Chehab 1957ad85094bSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(ov5693_controls); i++) 1958ad85094bSMauro Carvalho Chehab v4l2_ctrl_new_custom(&dev->ctrl_handler, &ov5693_controls[i], 1959ad85094bSMauro Carvalho Chehab NULL); 1960ad85094bSMauro Carvalho Chehab 1961ad85094bSMauro Carvalho Chehab if (dev->ctrl_handler.error) { 1962ad85094bSMauro Carvalho Chehab ov5693_remove(client); 1963ad85094bSMauro Carvalho Chehab return dev->ctrl_handler.error; 1964ad85094bSMauro Carvalho Chehab } 1965ad85094bSMauro Carvalho Chehab 1966ad85094bSMauro Carvalho Chehab /* Use same lock for controls as for everything else. */ 1967ad85094bSMauro Carvalho Chehab dev->ctrl_handler.lock = &dev->input_lock; 1968ad85094bSMauro Carvalho Chehab dev->sd.ctrl_handler = &dev->ctrl_handler; 1969ad85094bSMauro Carvalho Chehab 1970ad85094bSMauro Carvalho Chehab ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad); 1971ad85094bSMauro Carvalho Chehab if (ret) 1972ad85094bSMauro Carvalho Chehab ov5693_remove(client); 1973ad85094bSMauro Carvalho Chehab 1974ad85094bSMauro Carvalho Chehab return ret; 1975ad85094bSMauro Carvalho Chehab out_free: 1976ad85094bSMauro Carvalho Chehab v4l2_device_unregister_subdev(&dev->sd); 1977ad85094bSMauro Carvalho Chehab kfree(dev); 1978ad85094bSMauro Carvalho Chehab return ret; 1979ad85094bSMauro Carvalho Chehab } 1980ad85094bSMauro Carvalho Chehab 1981ad85094bSMauro Carvalho Chehab static const struct acpi_device_id ov5693_acpi_match[] = { 1982ad85094bSMauro Carvalho Chehab {"INT33BE"}, 1983ad85094bSMauro Carvalho Chehab {}, 1984ad85094bSMauro Carvalho Chehab }; 1985ad85094bSMauro Carvalho Chehab MODULE_DEVICE_TABLE(acpi, ov5693_acpi_match); 1986ad85094bSMauro Carvalho Chehab 1987ad85094bSMauro Carvalho Chehab static struct i2c_driver ov5693_driver = { 1988ad85094bSMauro Carvalho Chehab .driver = { 1989ad85094bSMauro Carvalho Chehab .name = "ov5693", 1990ad85094bSMauro Carvalho Chehab .acpi_match_table = ov5693_acpi_match, 1991ad85094bSMauro Carvalho Chehab }, 1992ad85094bSMauro Carvalho Chehab .probe_new = ov5693_probe, 1993ad85094bSMauro Carvalho Chehab .remove = ov5693_remove, 1994ad85094bSMauro Carvalho Chehab }; 1995ad85094bSMauro Carvalho Chehab module_i2c_driver(ov5693_driver); 1996ad85094bSMauro Carvalho Chehab 1997ad85094bSMauro Carvalho Chehab MODULE_DESCRIPTION("A low-level driver for OmniVision 5693 sensors"); 1998ad85094bSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 1999