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