mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
media: i2c: st-vgxy61: Convert to CCI register access helpers
Use the new common CCI register access helpers to replace the private register access helpers in the st-vgxy61 driver. This simplifies the driver by reducing the amount of code. st-vgxy61 devices use little endianness arrangement, therefore the driver uses the CCI_REGx_LE registers definition. Signed-off-by: Julien Massot <julien.massot@collabora.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
parent
24b41af1f1
commit
9a6d7f2ba2
@ -658,6 +658,7 @@ config VIDEO_S5K6A3
|
||||
|
||||
config VIDEO_ST_VGXY61
|
||||
tristate "ST VGXY61 sensor support"
|
||||
select V4L2_CCI_I2C
|
||||
depends on OF && GPIOLIB
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the ST VGXY61
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
@ -19,79 +20,74 @@
|
||||
|
||||
#include <media/mipi-csi2.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-cci.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
#define VGXY61_REG_8BIT(n) ((1 << 16) | (n))
|
||||
#define VGXY61_REG_16BIT(n) ((2 << 16) | (n))
|
||||
#define VGXY61_REG_32BIT(n) ((4 << 16) | (n))
|
||||
#define VGXY61_REG_SIZE_SHIFT 16
|
||||
#define VGXY61_REG_ADDR_MASK 0xffff
|
||||
|
||||
#define VGXY61_REG_MODEL_ID VGXY61_REG_16BIT(0x0000)
|
||||
#define VGXY61_REG_MODEL_ID CCI_REG16_LE(0x0000)
|
||||
#define VG5661_MODEL_ID 0x5661
|
||||
#define VG5761_MODEL_ID 0x5761
|
||||
#define VGXY61_REG_REVISION VGXY61_REG_16BIT(0x0002)
|
||||
#define VGXY61_REG_FWPATCH_REVISION VGXY61_REG_16BIT(0x0014)
|
||||
#define VGXY61_REG_FWPATCH_START_ADDR VGXY61_REG_8BIT(0x2000)
|
||||
#define VGXY61_REG_SYSTEM_FSM VGXY61_REG_8BIT(0x0020)
|
||||
#define VGXY61_REG_REVISION CCI_REG16_LE(0x0002)
|
||||
#define VGXY61_REG_FWPATCH_REVISION CCI_REG16_LE(0x0014)
|
||||
#define VGXY61_REG_FWPATCH_START_ADDR CCI_REG8(0x2000)
|
||||
#define VGXY61_REG_SYSTEM_FSM CCI_REG8(0x0020)
|
||||
#define VGXY61_SYSTEM_FSM_SW_STBY 0x03
|
||||
#define VGXY61_SYSTEM_FSM_STREAMING 0x04
|
||||
#define VGXY61_REG_NVM VGXY61_REG_8BIT(0x0023)
|
||||
#define VGXY61_REG_NVM CCI_REG8(0x0023)
|
||||
#define VGXY61_NVM_OK 0x04
|
||||
#define VGXY61_REG_STBY VGXY61_REG_8BIT(0x0201)
|
||||
#define VGXY61_REG_STBY CCI_REG8(0x0201)
|
||||
#define VGXY61_STBY_NO_REQ 0
|
||||
#define VGXY61_STBY_REQ_TMP_READ BIT(2)
|
||||
#define VGXY61_REG_STREAMING VGXY61_REG_8BIT(0x0202)
|
||||
#define VGXY61_REG_STREAMING CCI_REG8(0x0202)
|
||||
#define VGXY61_STREAMING_NO_REQ 0
|
||||
#define VGXY61_STREAMING_REQ_STOP BIT(0)
|
||||
#define VGXY61_STREAMING_REQ_START BIT(1)
|
||||
#define VGXY61_REG_EXT_CLOCK VGXY61_REG_32BIT(0x0220)
|
||||
#define VGXY61_REG_CLK_PLL_PREDIV VGXY61_REG_8BIT(0x0224)
|
||||
#define VGXY61_REG_CLK_SYS_PLL_MULT VGXY61_REG_8BIT(0x0225)
|
||||
#define VGXY61_REG_GPIO_0_CTRL VGXY61_REG_8BIT(0x0236)
|
||||
#define VGXY61_REG_GPIO_1_CTRL VGXY61_REG_8BIT(0x0237)
|
||||
#define VGXY61_REG_GPIO_2_CTRL VGXY61_REG_8BIT(0x0238)
|
||||
#define VGXY61_REG_GPIO_3_CTRL VGXY61_REG_8BIT(0x0239)
|
||||
#define VGXY61_REG_SIGNALS_POLARITY_CTRL VGXY61_REG_8BIT(0x023b)
|
||||
#define VGXY61_REG_LINE_LENGTH VGXY61_REG_16BIT(0x0300)
|
||||
#define VGXY61_REG_ORIENTATION VGXY61_REG_8BIT(0x0302)
|
||||
#define VGXY61_REG_VT_CTRL VGXY61_REG_8BIT(0x0304)
|
||||
#define VGXY61_REG_FORMAT_CTRL VGXY61_REG_8BIT(0x0305)
|
||||
#define VGXY61_REG_OIF_CTRL VGXY61_REG_16BIT(0x0306)
|
||||
#define VGXY61_REG_OIF_ROI0_CTRL VGXY61_REG_8BIT(0x030a)
|
||||
#define VGXY61_REG_ROI0_START_H VGXY61_REG_16BIT(0x0400)
|
||||
#define VGXY61_REG_ROI0_START_V VGXY61_REG_16BIT(0x0402)
|
||||
#define VGXY61_REG_ROI0_END_H VGXY61_REG_16BIT(0x0404)
|
||||
#define VGXY61_REG_ROI0_END_V VGXY61_REG_16BIT(0x0406)
|
||||
#define VGXY61_REG_PATGEN_CTRL VGXY61_REG_32BIT(0x0440)
|
||||
#define VGXY61_REG_EXT_CLOCK CCI_REG32_LE(0x0220)
|
||||
#define VGXY61_REG_CLK_PLL_PREDIV CCI_REG8(0x0224)
|
||||
#define VGXY61_REG_CLK_SYS_PLL_MULT CCI_REG8(0x0225)
|
||||
#define VGXY61_REG_GPIO_0_CTRL CCI_REG8(0x0236)
|
||||
#define VGXY61_REG_GPIO_1_CTRL CCI_REG8(0x0237)
|
||||
#define VGXY61_REG_GPIO_2_CTRL CCI_REG8(0x0238)
|
||||
#define VGXY61_REG_GPIO_3_CTRL CCI_REG8(0x0239)
|
||||
#define VGXY61_REG_SIGNALS_POLARITY_CTRL CCI_REG8(0x023b)
|
||||
#define VGXY61_REG_LINE_LENGTH CCI_REG16_LE(0x0300)
|
||||
#define VGXY61_REG_ORIENTATION CCI_REG8(0x0302)
|
||||
#define VGXY61_REG_VT_CTRL CCI_REG8(0x0304)
|
||||
#define VGXY61_REG_FORMAT_CTRL CCI_REG8(0x0305)
|
||||
#define VGXY61_REG_OIF_CTRL CCI_REG16_LE(0x0306)
|
||||
#define VGXY61_REG_OIF_ROI0_CTRL CCI_REG8(0x030a)
|
||||
#define VGXY61_REG_ROI0_START_H CCI_REG16_LE(0x0400)
|
||||
#define VGXY61_REG_ROI0_START_V CCI_REG16_LE(0x0402)
|
||||
#define VGXY61_REG_ROI0_END_H CCI_REG16_LE(0x0404)
|
||||
#define VGXY61_REG_ROI0_END_V CCI_REG16_LE(0x0406)
|
||||
#define VGXY61_REG_PATGEN_CTRL CCI_REG32_LE(0x0440)
|
||||
#define VGXY61_PATGEN_LONG_ENABLE BIT(16)
|
||||
#define VGXY61_PATGEN_SHORT_ENABLE BIT(0)
|
||||
#define VGXY61_PATGEN_LONG_TYPE_SHIFT 18
|
||||
#define VGXY61_PATGEN_SHORT_TYPE_SHIFT 4
|
||||
#define VGXY61_REG_FRAME_CONTENT_CTRL VGXY61_REG_8BIT(0x0478)
|
||||
#define VGXY61_REG_COARSE_EXPOSURE_LONG VGXY61_REG_16BIT(0x0500)
|
||||
#define VGXY61_REG_COARSE_EXPOSURE_SHORT VGXY61_REG_16BIT(0x0504)
|
||||
#define VGXY61_REG_ANALOG_GAIN VGXY61_REG_8BIT(0x0508)
|
||||
#define VGXY61_REG_DIGITAL_GAIN_LONG VGXY61_REG_16BIT(0x050a)
|
||||
#define VGXY61_REG_DIGITAL_GAIN_SHORT VGXY61_REG_16BIT(0x0512)
|
||||
#define VGXY61_REG_FRAME_LENGTH VGXY61_REG_16BIT(0x051a)
|
||||
#define VGXY61_REG_SIGNALS_CTRL VGXY61_REG_16BIT(0x0522)
|
||||
#define VGXY61_REG_FRAME_CONTENT_CTRL CCI_REG8(0x0478)
|
||||
#define VGXY61_REG_COARSE_EXPOSURE_LONG CCI_REG16_LE(0x0500)
|
||||
#define VGXY61_REG_COARSE_EXPOSURE_SHORT CCI_REG16_LE(0x0504)
|
||||
#define VGXY61_REG_ANALOG_GAIN CCI_REG8(0x0508)
|
||||
#define VGXY61_REG_DIGITAL_GAIN_LONG CCI_REG16_LE(0x050a)
|
||||
#define VGXY61_REG_DIGITAL_GAIN_SHORT CCI_REG16_LE(0x0512)
|
||||
#define VGXY61_REG_FRAME_LENGTH CCI_REG16_LE(0x051a)
|
||||
#define VGXY61_REG_SIGNALS_CTRL CCI_REG16_LE(0x0522)
|
||||
#define VGXY61_SIGNALS_GPIO_ID_SHIFT 4
|
||||
#define VGXY61_REG_READOUT_CTRL VGXY61_REG_8BIT(0x0530)
|
||||
#define VGXY61_REG_HDR_CTRL VGXY61_REG_8BIT(0x0532)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_GR VGXY61_REG_16BIT(0x092c)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_R VGXY61_REG_16BIT(0x092e)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_B VGXY61_REG_16BIT(0x0930)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_GB VGXY61_REG_16BIT(0x0932)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_GR VGXY61_REG_16BIT(0x0950)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_R VGXY61_REG_16BIT(0x0952)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_B VGXY61_REG_16BIT(0x0954)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_GB VGXY61_REG_16BIT(0x0956)
|
||||
#define VGXY61_REG_BYPASS_CTRL VGXY61_REG_8BIT(0x0a60)
|
||||
#define VGXY61_REG_READOUT_CTRL CCI_REG8(0x0530)
|
||||
#define VGXY61_REG_HDR_CTRL CCI_REG8(0x0532)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_GR CCI_REG16_LE(0x092c)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_R CCI_REG16_LE(0x092e)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_B CCI_REG16_LE(0x0930)
|
||||
#define VGXY61_REG_PATGEN_LONG_DATA_GB CCI_REG16_LE(0x0932)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_GR CCI_REG16_LE(0x0950)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_R CCI_REG16_LE(0x0952)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_B CCI_REG16_LE(0x0954)
|
||||
#define VGXY61_REG_PATGEN_SHORT_DATA_GB CCI_REG16_LE(0x0956)
|
||||
#define VGXY61_REG_BYPASS_CTRL CCI_REG8(0x0a60)
|
||||
|
||||
#define VGX661_WIDTH 1464
|
||||
#define VGX661_HEIGHT 1104
|
||||
@ -384,6 +380,7 @@ static const struct vgxy61_mode_info vgx761_mode_data[] = {
|
||||
|
||||
struct vgxy61_dev {
|
||||
struct i2c_client *i2c_client;
|
||||
struct regmap *regmap;
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pad;
|
||||
struct regulator_bulk_data supplies[ARRAY_SIZE(vgxy61_supply_name)];
|
||||
@ -510,82 +507,6 @@ static unsigned int get_chunk_size(struct vgxy61_dev *sensor)
|
||||
return max(max_write_len, 1);
|
||||
}
|
||||
|
||||
static int vgxy61_read_multiple(struct vgxy61_dev *sensor, u32 reg,
|
||||
unsigned int len)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
struct i2c_msg msg[2];
|
||||
u8 buf[2];
|
||||
u8 val[sizeof(u32)] = {0};
|
||||
int ret;
|
||||
|
||||
if (len > sizeof(u32))
|
||||
return -EINVAL;
|
||||
buf[0] = reg >> 8;
|
||||
buf[1] = reg & 0xff;
|
||||
|
||||
msg[0].addr = client->addr;
|
||||
msg[0].flags = client->flags;
|
||||
msg[0].buf = buf;
|
||||
msg[0].len = sizeof(buf);
|
||||
|
||||
msg[1].addr = client->addr;
|
||||
msg[1].flags = client->flags | I2C_M_RD;
|
||||
msg[1].buf = val;
|
||||
msg[1].len = len;
|
||||
|
||||
ret = i2c_transfer(client->adapter, msg, 2);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n",
|
||||
__func__, client->addr, reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return get_unaligned_le32(val);
|
||||
}
|
||||
|
||||
static inline int vgxy61_read_reg(struct vgxy61_dev *sensor, u32 reg)
|
||||
{
|
||||
return vgxy61_read_multiple(sensor, reg & VGXY61_REG_ADDR_MASK,
|
||||
(reg >> VGXY61_REG_SIZE_SHIFT) & 7);
|
||||
}
|
||||
|
||||
static int vgxy61_write_multiple(struct vgxy61_dev *sensor, u32 reg,
|
||||
const u8 *data, unsigned int len, int *err)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
struct i2c_msg msg;
|
||||
u8 buf[VGXY61_WRITE_MULTIPLE_CHUNK_MAX + 2];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (err && *err)
|
||||
return *err;
|
||||
|
||||
if (len > VGXY61_WRITE_MULTIPLE_CHUNK_MAX)
|
||||
return -EINVAL;
|
||||
buf[0] = reg >> 8;
|
||||
buf[1] = reg & 0xff;
|
||||
for (i = 0; i < len; i++)
|
||||
buf[i + 2] = data[i];
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = client->flags;
|
||||
msg.buf = buf;
|
||||
msg.len = len + 2;
|
||||
|
||||
ret = i2c_transfer(client->adapter, &msg, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n",
|
||||
__func__, reg, ret);
|
||||
if (err)
|
||||
*err = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
|
||||
unsigned int nb, const u8 *array)
|
||||
{
|
||||
@ -595,7 +516,8 @@ static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
|
||||
|
||||
while (nb) {
|
||||
sz = min(nb, chunk_size);
|
||||
ret = vgxy61_write_multiple(sensor, reg, array, sz, NULL);
|
||||
ret = regmap_bulk_write(sensor->regmap, CCI_REG_ADDR(reg),
|
||||
array, sz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
nb -= sz;
|
||||
@ -606,24 +528,17 @@ static int vgxy61_write_array(struct vgxy61_dev *sensor, u32 reg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int vgxy61_write_reg(struct vgxy61_dev *sensor, u32 reg, u32 val,
|
||||
int *err)
|
||||
{
|
||||
return vgxy61_write_multiple(sensor, reg & VGXY61_REG_ADDR_MASK,
|
||||
(u8 *)&val,
|
||||
(reg >> VGXY61_REG_SIZE_SHIFT) & 7, err);
|
||||
}
|
||||
|
||||
static int vgxy61_poll_reg(struct vgxy61_dev *sensor, u32 reg, u8 poll_val,
|
||||
unsigned int timeout_ms)
|
||||
{
|
||||
const unsigned int loop_delay_ms = 10;
|
||||
u64 val;
|
||||
int ret;
|
||||
|
||||
return read_poll_timeout(vgxy61_read_reg, ret,
|
||||
((ret < 0) || (ret == poll_val)),
|
||||
return read_poll_timeout(cci_read, ret,
|
||||
((ret < 0) || (val == poll_val)),
|
||||
loop_delay_ms * 1000, timeout_ms * 1000,
|
||||
false, sensor, reg);
|
||||
false, sensor->regmap, reg, &val, NULL);
|
||||
}
|
||||
|
||||
static int vgxy61_wait_state(struct vgxy61_dev *sensor, int state,
|
||||
@ -662,11 +577,11 @@ static int vgxy61_apply_exposure(struct vgxy61_dev *sensor)
|
||||
int ret = 0;
|
||||
|
||||
/* We first set expo to zero to avoid forbidden parameters couple */
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_LONG,
|
||||
sensor->expo_long, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_COARSE_EXPOSURE_SHORT,
|
||||
sensor->expo_short, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT, 0, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_LONG,
|
||||
sensor->expo_long, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_COARSE_EXPOSURE_SHORT,
|
||||
sensor->expo_short, &ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -827,8 +742,8 @@ static int vgxy61_update_analog_gain(struct vgxy61_dev *sensor, u32 target)
|
||||
sensor->analog_gain = target;
|
||||
|
||||
if (sensor->streaming)
|
||||
return vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN, target,
|
||||
NULL);
|
||||
return cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN, target,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -842,10 +757,10 @@ static int vgxy61_apply_digital_gain(struct vgxy61_dev *sensor,
|
||||
* DIGITAL_GAIN_SHORT_CH0 is enough to configure the gain of all
|
||||
* four sub pixels.
|
||||
*/
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain,
|
||||
&ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain,
|
||||
&ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_LONG, digital_gain,
|
||||
&ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_DIGITAL_GAIN_SHORT, digital_gain,
|
||||
&ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -870,7 +785,7 @@ static int vgxy61_apply_patgen(struct vgxy61_dev *sensor, u32 index)
|
||||
|
||||
if (pattern)
|
||||
reg |= VGXY61_PATGEN_LONG_ENABLE | VGXY61_PATGEN_SHORT_ENABLE;
|
||||
return vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_CTRL, reg, NULL);
|
||||
return cci_write(sensor->regmap, VGXY61_REG_PATGEN_CTRL, reg, NULL);
|
||||
}
|
||||
|
||||
static int vgxy61_update_patgen(struct vgxy61_dev *sensor, u32 pattern)
|
||||
@ -887,15 +802,13 @@ static int vgxy61_apply_gpiox_strobe_mode(struct vgxy61_dev *sensor,
|
||||
unsigned int idx)
|
||||
{
|
||||
static const u8 index2val[] = {0x0, 0x1, 0x3};
|
||||
int reg;
|
||||
u16 mask, val;
|
||||
|
||||
reg = vgxy61_read_reg(sensor, VGXY61_REG_SIGNALS_CTRL);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
reg &= ~(0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT));
|
||||
reg |= index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
|
||||
mask = 0xf << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
|
||||
val = index2val[mode] << (idx * VGXY61_SIGNALS_GPIO_ID_SHIFT);
|
||||
|
||||
return vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_CTRL, reg, NULL);
|
||||
return cci_update_bits(sensor->regmap, VGXY61_REG_SIGNALS_CTRL,
|
||||
mask, val, NULL);
|
||||
}
|
||||
|
||||
static int vgxy61_update_gpios_strobe_mode(struct vgxy61_dev *sensor,
|
||||
@ -940,12 +853,12 @@ static int vgxy61_update_gpios_strobe_polarity(struct vgxy61_dev *sensor,
|
||||
if (sensor->streaming)
|
||||
return -EBUSY;
|
||||
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity,
|
||||
&ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_GPIO_0_CTRL, polarity << 1, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_GPIO_1_CTRL, polarity << 1, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_GPIO_2_CTRL, polarity << 1, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_GPIO_3_CTRL, polarity << 1, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_SIGNALS_POLARITY_CTRL, polarity,
|
||||
&ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1057,8 +970,8 @@ static int vgxy61_update_exposure(struct vgxy61_dev *sensor, u16 new_expo_long,
|
||||
|
||||
static int vgxy61_apply_framelength(struct vgxy61_dev *sensor)
|
||||
{
|
||||
return vgxy61_write_reg(sensor, VGXY61_REG_FRAME_LENGTH,
|
||||
sensor->frame_length, NULL);
|
||||
return cci_write(sensor->regmap, VGXY61_REG_FRAME_LENGTH,
|
||||
sensor->frame_length, NULL);
|
||||
}
|
||||
|
||||
static int vgxy61_update_vblank(struct vgxy61_dev *sensor, u16 vblank,
|
||||
@ -1086,8 +999,8 @@ static int vgxy61_apply_hdr(struct vgxy61_dev *sensor,
|
||||
{
|
||||
static const u8 index2val[] = {0x1, 0x4, 0xa};
|
||||
|
||||
return vgxy61_write_reg(sensor, VGXY61_REG_HDR_CTRL, index2val[index],
|
||||
NULL);
|
||||
return cci_write(sensor->regmap, VGXY61_REG_HDR_CTRL, index2val[index],
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int vgxy61_update_hdr(struct vgxy61_dev *sensor,
|
||||
@ -1133,16 +1046,16 @@ static int vgxy61_apply_settings(struct vgxy61_dev *sensor)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vgxy61_write_reg(sensor, VGXY61_REG_ANALOG_GAIN,
|
||||
sensor->analog_gain, NULL);
|
||||
ret = cci_write(sensor->regmap, VGXY61_REG_ANALOG_GAIN,
|
||||
sensor->analog_gain, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = vgxy61_apply_digital_gain(sensor, sensor->digital_gain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vgxy61_write_reg(sensor, VGXY61_REG_ORIENTATION,
|
||||
sensor->hflip | (sensor->vflip << 1), NULL);
|
||||
ret = cci_write(sensor->regmap, VGXY61_REG_ORIENTATION,
|
||||
sensor->hflip | (sensor->vflip << 1), NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1174,19 +1087,19 @@ static int vgxy61_stream_enable(struct vgxy61_dev *sensor)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_FORMAT_CTRL,
|
||||
get_bpp_by_code(sensor->fmt.code), &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_OIF_ROI0_CTRL,
|
||||
get_data_type_by_code(sensor->fmt.code), &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_FORMAT_CTRL,
|
||||
get_bpp_by_code(sensor->fmt.code), &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_OIF_ROI0_CTRL,
|
||||
get_data_type_by_code(sensor->fmt.code), &ret);
|
||||
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_READOUT_CTRL,
|
||||
sensor->current_mode->bin_mode, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_H, crop->left, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_H,
|
||||
crop->left + crop->width - 1, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_ROI0_START_V, crop->top, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_ROI0_END_V,
|
||||
crop->top + crop->height - 1, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_READOUT_CTRL,
|
||||
sensor->current_mode->bin_mode, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_ROI0_START_H, crop->left, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_ROI0_END_H,
|
||||
crop->left + crop->width - 1, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_ROI0_START_V, crop->top, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_ROI0_END_V,
|
||||
crop->top + crop->height - 1, &ret);
|
||||
if (ret)
|
||||
goto err_rpm_put;
|
||||
|
||||
@ -1194,8 +1107,8 @@ static int vgxy61_stream_enable(struct vgxy61_dev *sensor)
|
||||
if (ret)
|
||||
goto err_rpm_put;
|
||||
|
||||
ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING,
|
||||
VGXY61_STREAMING_REQ_START, NULL);
|
||||
ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING,
|
||||
VGXY61_STREAMING_REQ_START, NULL);
|
||||
if (ret)
|
||||
goto err_rpm_put;
|
||||
|
||||
@ -1225,8 +1138,8 @@ static int vgxy61_stream_disable(struct vgxy61_dev *sensor)
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
|
||||
int ret;
|
||||
|
||||
ret = vgxy61_write_reg(sensor, VGXY61_REG_STREAMING,
|
||||
VGXY61_STREAMING_REQ_STOP, NULL);
|
||||
ret = cci_write(sensor->regmap, VGXY61_REG_STREAMING,
|
||||
VGXY61_STREAMING_REQ_STOP, NULL);
|
||||
if (ret)
|
||||
goto err_str_dis;
|
||||
|
||||
@ -1582,7 +1495,7 @@ static int vgxy61_configure(struct vgxy61_dev *sensor)
|
||||
{
|
||||
u32 sensor_freq;
|
||||
u8 prediv, mult;
|
||||
int line_length;
|
||||
u64 line_length;
|
||||
int ret = 0;
|
||||
|
||||
compute_pll_parameters_by_freq(sensor->clk_freq, &prediv, &mult);
|
||||
@ -1592,28 +1505,28 @@ static int vgxy61_configure(struct vgxy61_dev *sensor)
|
||||
/* Video timing ISP path (pixel clock) requires 804/5 mhz = 160 mhz */
|
||||
sensor->pclk = sensor_freq / 5;
|
||||
|
||||
line_length = vgxy61_read_reg(sensor, VGXY61_REG_LINE_LENGTH);
|
||||
if (line_length < 0)
|
||||
return line_length;
|
||||
sensor->line_length = line_length;
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_BYPASS_CTRL, 4, &ret);
|
||||
cci_read(sensor->regmap, VGXY61_REG_LINE_LENGTH, &line_length, &ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
sensor->line_length = (u16)line_length;
|
||||
cci_write(sensor->regmap, VGXY61_REG_EXT_CLOCK, sensor->clk_freq, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_CLK_PLL_PREDIV, prediv, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_CLK_SYS_PLL_MULT, mult, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_OIF_CTRL, sensor->oif_ctrl, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_FRAME_CONTENT_CTRL, 0, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_BYPASS_CTRL, 4, &ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
vgxy61_update_gpios_strobe_polarity(sensor, sensor->gpios_polarity);
|
||||
/* Set pattern generator solid to middle value */
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret);
|
||||
vgxy61_write_reg(sensor, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GR, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_R, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_B, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_LONG_DATA_GB, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GR, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_R, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_B, 0x800, &ret);
|
||||
cci_write(sensor->regmap, VGXY61_REG_PATGEN_SHORT_DATA_GB, 0x800, &ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1623,37 +1536,33 @@ static int vgxy61_configure(struct vgxy61_dev *sensor)
|
||||
static int vgxy61_patch(struct vgxy61_dev *sensor)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
int patch, ret;
|
||||
u64 patch;
|
||||
int ret;
|
||||
|
||||
ret = vgxy61_write_array(sensor, VGXY61_REG_FWPATCH_START_ADDR,
|
||||
sizeof(patch_array), patch_array);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vgxy61_write_reg(sensor, VGXY61_REG_STBY, 0x10, NULL);
|
||||
cci_write(sensor->regmap, VGXY61_REG_STBY, 0x10, &ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vgxy61_poll_reg(sensor, VGXY61_REG_STBY, 0, VGXY61_TIMEOUT_MS);
|
||||
if (ret)
|
||||
cci_read(sensor->regmap, VGXY61_REG_FWPATCH_REVISION, &patch, &ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
patch = vgxy61_read_reg(sensor, VGXY61_REG_FWPATCH_REVISION);
|
||||
if (patch < 0)
|
||||
return patch;
|
||||
|
||||
if (patch != (VGXY61_FWPATCH_REVISION_MAJOR << 12) +
|
||||
(VGXY61_FWPATCH_REVISION_MINOR << 8) +
|
||||
VGXY61_FWPATCH_REVISION_MICRO) {
|
||||
dev_err(&client->dev, "bad patch version expected %d.%d.%d got %d.%d.%d\n",
|
||||
dev_err(&client->dev,
|
||||
"bad patch version expected %d.%d.%d got %u.%u.%u\n",
|
||||
VGXY61_FWPATCH_REVISION_MAJOR,
|
||||
VGXY61_FWPATCH_REVISION_MINOR,
|
||||
VGXY61_FWPATCH_REVISION_MICRO,
|
||||
patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
|
||||
(u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff);
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_dbg(&client->dev, "patch %d.%d.%d applied\n",
|
||||
patch >> 12, (patch >> 8) & 0x0f, patch & 0xff);
|
||||
dev_dbg(&client->dev, "patch %u.%u.%u applied\n",
|
||||
(u16)patch >> 12, ((u16)patch >> 8) & 0x0f, (u16)patch & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1661,11 +1570,12 @@ static int vgxy61_patch(struct vgxy61_dev *sensor)
|
||||
static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
int device_rev;
|
||||
u64 device_rev;
|
||||
int ret;
|
||||
|
||||
device_rev = vgxy61_read_reg(sensor, VGXY61_REG_REVISION);
|
||||
if (device_rev < 0)
|
||||
return device_rev;
|
||||
ret = cci_read(sensor->regmap, VGXY61_REG_REVISION, &device_rev, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (device_rev >> 8) {
|
||||
case 0xA:
|
||||
@ -1687,17 +1597,17 @@ static int vgxy61_detect_cut_version(struct vgxy61_dev *sensor)
|
||||
static int vgxy61_detect(struct vgxy61_dev *sensor)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
int id = 0;
|
||||
int ret, st;
|
||||
u64 st, id = 0;
|
||||
int ret;
|
||||
|
||||
id = vgxy61_read_reg(sensor, VGXY61_REG_MODEL_ID);
|
||||
if (id < 0)
|
||||
return id;
|
||||
ret = cci_read(sensor->regmap, VGXY61_REG_MODEL_ID, &id, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (id != VG5661_MODEL_ID && id != VG5761_MODEL_ID) {
|
||||
dev_warn(&client->dev, "Unsupported sensor id %x\n", id);
|
||||
dev_warn(&client->dev, "Unsupported sensor id %x\n", (u16)id);
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", id);
|
||||
dev_dbg(&client->dev, "detected sensor id = 0x%04x\n", (u16)id);
|
||||
sensor->id = id;
|
||||
|
||||
ret = vgxy61_wait_state(sensor, VGXY61_SYSTEM_FSM_SW_STBY,
|
||||
@ -1705,11 +1615,11 @@ static int vgxy61_detect(struct vgxy61_dev *sensor)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st = vgxy61_read_reg(sensor, VGXY61_REG_NVM);
|
||||
if (st < 0)
|
||||
ret = cci_read(sensor->regmap, VGXY61_REG_NVM, &st, NULL);
|
||||
if (ret < 0)
|
||||
return st;
|
||||
if (st != VGXY61_NVM_OK)
|
||||
dev_warn(&client->dev, "Bad nvm state got %d\n", st);
|
||||
dev_warn(&client->dev, "Bad nvm state got %u\n", (u8)st);
|
||||
|
||||
ret = vgxy61_detect_cut_version(sensor);
|
||||
if (ret)
|
||||
@ -1832,6 +1742,12 @@ static int vgxy61_probe(struct i2c_client *client)
|
||||
sensor->analog_gain = 0;
|
||||
sensor->digital_gain = 256;
|
||||
|
||||
sensor->regmap = devm_cci_regmap_init_i2c(client, 16);
|
||||
if (IS_ERR(sensor->regmap)) {
|
||||
ret = PTR_ERR(sensor->regmap);
|
||||
return dev_err_probe(dev, ret, "Failed to init regmap\n");
|
||||
}
|
||||
|
||||
handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
|
||||
if (!handle) {
|
||||
dev_err(dev, "handle node not found\n");
|
||||
|
Loading…
Reference in New Issue
Block a user