media: ov9650: use SCCB regmap
Convert ov965x register access to use SCCB regmap. Cc: Mark Brown <broonie@kernel.org> Cc: Peter Rosin <peda@axentia.se> Cc: Sebastian Reichel <sebastian.reichel@collabora.co.uk> Cc: Wolfram Sang <wsa@the-dreams.de> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com> Cc: Jacopo Mondi <jacopo+renesas@jmondi.org> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com> (I2C parts) Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
Родитель
5bbf32217b
Коммит
361f3803ad
|
@ -787,6 +787,7 @@ config VIDEO_OV7740
|
|||
config VIDEO_OV9650
|
||||
tristate "OmniVision OV9650/OV9652 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
select REGMAP_SCCB
|
||||
---help---
|
||||
This is a V4L2 sensor driver for the Omnivision
|
||||
OV9650 and OV9652 camera sensors.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/media.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
@ -259,7 +260,7 @@ struct ov965x {
|
|||
/* Protects the struct fields below */
|
||||
struct mutex lock;
|
||||
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
|
||||
/* Exposure row interval in us */
|
||||
unsigned int exp_row_interval;
|
||||
|
@ -424,51 +425,40 @@ static inline struct ov965x *to_ov965x(struct v4l2_subdev *sd)
|
|||
return container_of(sd, struct ov965x, sd);
|
||||
}
|
||||
|
||||
static int ov965x_read(struct i2c_client *client, u8 addr, u8 *val)
|
||||
static int ov965x_read(struct ov965x *ov965x, u8 addr, u8 *val)
|
||||
{
|
||||
u8 buf = addr;
|
||||
struct i2c_msg msg = {
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &buf
|
||||
};
|
||||
int ret;
|
||||
unsigned int buf;
|
||||
|
||||
ret = i2c_transfer(client->adapter, &msg, 1);
|
||||
if (ret == 1) {
|
||||
msg.flags = I2C_M_RD;
|
||||
ret = i2c_transfer(client->adapter, &msg, 1);
|
||||
ret = regmap_read(ov965x->regmap, addr, &buf);
|
||||
if (!ret)
|
||||
*val = buf;
|
||||
|
||||
if (ret == 1)
|
||||
*val = buf;
|
||||
}
|
||||
|
||||
v4l2_dbg(2, debug, client, "%s: 0x%02x @ 0x%02x. (%d)\n",
|
||||
v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02x. (%d)\n",
|
||||
__func__, *val, addr, ret);
|
||||
|
||||
return ret == 1 ? 0 : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov965x_write(struct i2c_client *client, u8 addr, u8 val)
|
||||
static int ov965x_write(struct ov965x *ov965x, u8 addr, u8 val)
|
||||
{
|
||||
u8 buf[2] = { addr, val };
|
||||
int ret;
|
||||
|
||||
int ret = i2c_master_send(client, buf, 2);
|
||||
ret = regmap_write(ov965x->regmap, addr, val);
|
||||
|
||||
v4l2_dbg(2, debug, client, "%s: 0x%02x @ 0x%02X (%d)\n",
|
||||
v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02X (%d)\n",
|
||||
__func__, val, addr, ret);
|
||||
|
||||
return ret == 2 ? 0 : ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov965x_write_array(struct i2c_client *client,
|
||||
static int ov965x_write_array(struct ov965x *ov965x,
|
||||
const struct i2c_rv *regs)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++)
|
||||
ret = ov965x_write(client, regs[i].addr, regs[i].value);
|
||||
ret = ov965x_write(ov965x, regs[i].addr, regs[i].value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -486,7 +476,7 @@ static int ov965x_set_default_gamma_curve(struct ov965x *ov965x)
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gamma_curve); i++) {
|
||||
int ret = ov965x_write(ov965x->client, addr, gamma_curve[i]);
|
||||
int ret = ov965x_write(ov965x, addr, gamma_curve[i]);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -506,7 +496,7 @@ static int ov965x_set_color_matrix(struct ov965x *ov965x)
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mtx); i++) {
|
||||
int ret = ov965x_write(ov965x->client, addr, mtx[i]);
|
||||
int ret = ov965x_write(ov965x, addr, mtx[i]);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -542,16 +532,15 @@ static int __ov965x_set_power(struct ov965x *ov965x, int on)
|
|||
static int ov965x_s_power(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
struct ov965x *ov965x = to_ov965x(sd);
|
||||
struct i2c_client *client = ov965x->client;
|
||||
int ret = 0;
|
||||
|
||||
v4l2_dbg(1, debug, client, "%s: on: %d\n", __func__, on);
|
||||
v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
|
||||
|
||||
mutex_lock(&ov965x->lock);
|
||||
if (ov965x->power == !on) {
|
||||
ret = __ov965x_set_power(ov965x, on);
|
||||
if (!ret && on) {
|
||||
ret = ov965x_write_array(client,
|
||||
ret = ov965x_write_array(ov965x,
|
||||
ov965x_init_regs);
|
||||
ov965x->apply_frame_fmt = 1;
|
||||
ov965x->ctrls.update = 1;
|
||||
|
@ -609,13 +598,13 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
|
|||
int ret;
|
||||
u8 reg;
|
||||
|
||||
ret = ov965x_read(ov965x->client, REG_COM8, ®);
|
||||
ret = ov965x_read(ov965x, REG_COM8, ®);
|
||||
if (!ret) {
|
||||
if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
|
||||
reg &= ~COM8_BFILT;
|
||||
else
|
||||
reg |= COM8_BFILT;
|
||||
ret = ov965x_write(ov965x->client, REG_COM8, reg);
|
||||
ret = ov965x_write(ov965x, REG_COM8, reg);
|
||||
}
|
||||
if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
|
||||
return 0;
|
||||
|
@ -631,7 +620,7 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
|
|||
ov965x->fiv->interval.numerator;
|
||||
mbd = ((mbd / (light_freq * 2)) + 500) / 1000UL;
|
||||
|
||||
return ov965x_write(ov965x->client, REG_MBD, mbd);
|
||||
return ov965x_write(ov965x, REG_MBD, mbd);
|
||||
}
|
||||
|
||||
static int ov965x_set_white_balance(struct ov965x *ov965x, int awb)
|
||||
|
@ -639,17 +628,17 @@ static int ov965x_set_white_balance(struct ov965x *ov965x, int awb)
|
|||
int ret;
|
||||
u8 reg;
|
||||
|
||||
ret = ov965x_read(ov965x->client, REG_COM8, ®);
|
||||
ret = ov965x_read(ov965x, REG_COM8, ®);
|
||||
if (!ret) {
|
||||
reg = awb ? reg | REG_COM8 : reg & ~REG_COM8;
|
||||
ret = ov965x_write(ov965x->client, REG_COM8, reg);
|
||||
ret = ov965x_write(ov965x, REG_COM8, reg);
|
||||
}
|
||||
if (!ret && !awb) {
|
||||
ret = ov965x_write(ov965x->client, REG_BLUE,
|
||||
ret = ov965x_write(ov965x, REG_BLUE,
|
||||
ov965x->ctrls.blue_balance->val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_write(ov965x->client, REG_RED,
|
||||
ret = ov965x_write(ov965x, REG_RED,
|
||||
ov965x->ctrls.red_balance->val);
|
||||
}
|
||||
return ret;
|
||||
|
@ -677,14 +666,13 @@ static int ov965x_set_brightness(struct ov965x *ov965x, int val)
|
|||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < NUM_BR_REGS && !ret; i++)
|
||||
ret = ov965x_write(ov965x->client, regs[0][i],
|
||||
ret = ov965x_write(ov965x, regs[0][i],
|
||||
regs[val][i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
|
||||
{
|
||||
struct i2c_client *client = ov965x->client;
|
||||
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
|
||||
int ret = 0;
|
||||
u8 reg;
|
||||
|
@ -693,14 +681,14 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
|
|||
* gain value in REG_VREF, REG_GAIN is not overwritten.
|
||||
*/
|
||||
if (ctrls->auto_gain->is_new) {
|
||||
ret = ov965x_read(client, REG_COM8, ®);
|
||||
ret = ov965x_read(ov965x, REG_COM8, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ctrls->auto_gain->val)
|
||||
reg |= COM8_AGC;
|
||||
else
|
||||
reg &= ~COM8_AGC;
|
||||
ret = ov965x_write(client, REG_COM8, reg);
|
||||
ret = ov965x_write(ov965x, REG_COM8, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
@ -719,15 +707,15 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
|
|||
rgain = (gain - ((1 << m) * 16)) / (1 << m);
|
||||
rgain |= (((1 << m) - 1) << 4);
|
||||
|
||||
ret = ov965x_write(client, REG_GAIN, rgain & 0xff);
|
||||
ret = ov965x_write(ov965x, REG_GAIN, rgain & 0xff);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_read(client, REG_VREF, ®);
|
||||
ret = ov965x_read(ov965x, REG_VREF, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg &= ~VREF_GAIN_MASK;
|
||||
reg |= (((rgain >> 8) & 0x3) << 6);
|
||||
ret = ov965x_write(client, REG_VREF, reg);
|
||||
ret = ov965x_write(ov965x, REG_VREF, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Return updated control's value to userspace */
|
||||
|
@ -742,10 +730,10 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
|
|||
u8 com14, edge;
|
||||
int ret;
|
||||
|
||||
ret = ov965x_read(ov965x->client, REG_COM14, &com14);
|
||||
ret = ov965x_read(ov965x, REG_COM14, &com14);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_read(ov965x->client, REG_EDGE, &edge);
|
||||
ret = ov965x_read(ov965x, REG_EDGE, &edge);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
com14 = value ? com14 | COM14_EDGE_EN : com14 & ~COM14_EDGE_EN;
|
||||
|
@ -756,33 +744,32 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
|
|||
} else {
|
||||
com14 &= ~COM14_EEF_X2;
|
||||
}
|
||||
ret = ov965x_write(ov965x->client, REG_COM14, com14);
|
||||
ret = ov965x_write(ov965x, REG_COM14, com14);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
edge &= ~EDGE_FACTOR_MASK;
|
||||
edge |= ((u8)value & 0x0f);
|
||||
|
||||
return ov965x_write(ov965x->client, REG_EDGE, edge);
|
||||
return ov965x_write(ov965x, REG_EDGE, edge);
|
||||
}
|
||||
|
||||
static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
|
||||
{
|
||||
struct i2c_client *client = ov965x->client;
|
||||
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
|
||||
bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO);
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
if (ctrls->auto_exp->is_new) {
|
||||
ret = ov965x_read(client, REG_COM8, ®);
|
||||
ret = ov965x_read(ov965x, REG_COM8, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (auto_exposure)
|
||||
reg |= (COM8_AEC | COM8_AGC);
|
||||
else
|
||||
reg &= ~(COM8_AEC | COM8_AGC);
|
||||
ret = ov965x_write(client, REG_COM8, reg);
|
||||
ret = ov965x_write(ov965x, REG_COM8, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
@ -794,12 +781,12 @@ static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
|
|||
* Manual exposure value
|
||||
* [b15:b0] - AECHM (b15:b10), AECH (b9:b2), COM1 (b1:b0)
|
||||
*/
|
||||
ret = ov965x_write(client, REG_COM1, exposure & 0x3);
|
||||
ret = ov965x_write(ov965x, REG_COM1, exposure & 0x3);
|
||||
if (!ret)
|
||||
ret = ov965x_write(client, REG_AECH,
|
||||
ret = ov965x_write(ov965x, REG_AECH,
|
||||
(exposure >> 2) & 0xff);
|
||||
if (!ret)
|
||||
ret = ov965x_write(client, REG_AECHM,
|
||||
ret = ov965x_write(ov965x, REG_AECHM,
|
||||
(exposure >> 10) & 0x3f);
|
||||
/* Update the value to minimize rounding errors */
|
||||
ctrls->exposure->val = ((exposure * ov965x->exp_row_interval)
|
||||
|
@ -822,7 +809,7 @@ static int ov965x_set_flip(struct ov965x *ov965x)
|
|||
if (ov965x->ctrls.vflip->val)
|
||||
mvfp |= MVFP_FLIP;
|
||||
|
||||
return ov965x_write(ov965x->client, REG_MVFP, mvfp);
|
||||
return ov965x_write(ov965x, REG_MVFP, mvfp);
|
||||
}
|
||||
|
||||
#define NUM_SAT_LEVELS 5
|
||||
|
@ -846,7 +833,7 @@ static int ov965x_set_saturation(struct ov965x *ov965x, int val)
|
|||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < NUM_SAT_REGS && !ret; i++)
|
||||
ret = ov965x_write(ov965x->client, addr + i, regs[val][i]);
|
||||
ret = ov965x_write(ov965x, addr + i, regs[val][i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -856,16 +843,15 @@ static int ov965x_set_test_pattern(struct ov965x *ov965x, int value)
|
|||
int ret;
|
||||
u8 reg;
|
||||
|
||||
ret = ov965x_read(ov965x->client, REG_COM23, ®);
|
||||
ret = ov965x_read(ov965x, REG_COM23, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg = value ? reg | COM23_TEST_MODE : reg & ~COM23_TEST_MODE;
|
||||
return ov965x_write(ov965x->client, REG_COM23, reg);
|
||||
return ov965x_write(ov965x, REG_COM23, reg);
|
||||
}
|
||||
|
||||
static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct i2c_client *client = ov965x->client;
|
||||
unsigned int exposure, gain, m;
|
||||
u8 reg0, reg1, reg2;
|
||||
int ret;
|
||||
|
@ -877,10 +863,10 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
|
|||
case V4L2_CID_AUTOGAIN:
|
||||
if (!ctrl->val)
|
||||
return 0;
|
||||
ret = ov965x_read(client, REG_GAIN, ®0);
|
||||
ret = ov965x_read(ov965x, REG_GAIN, ®0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_read(client, REG_VREF, ®1);
|
||||
ret = ov965x_read(ov965x, REG_VREF, ®1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
gain = ((reg1 >> 6) << 8) | reg0;
|
||||
|
@ -891,13 +877,13 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
|
|||
case V4L2_CID_EXPOSURE_AUTO:
|
||||
if (ctrl->val == V4L2_EXPOSURE_MANUAL)
|
||||
return 0;
|
||||
ret = ov965x_read(client, REG_COM1, ®0);
|
||||
ret = ov965x_read(ov965x, REG_COM1, ®0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_read(client, REG_AECH, ®1);
|
||||
ret = ov965x_read(ov965x, REG_AECH, ®1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_read(client, REG_AECHM, ®2);
|
||||
ret = ov965x_read(ov965x, REG_AECHM, ®2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
exposure = ((reg2 & 0x3f) << 10) | (reg1 << 2) |
|
||||
|
@ -1279,32 +1265,31 @@ static int ov965x_set_frame_size(struct ov965x *ov965x)
|
|||
int i, ret = 0;
|
||||
|
||||
for (i = 0; ret == 0 && i < NUM_FMT_REGS; i++)
|
||||
ret = ov965x_write(ov965x->client, frame_size_reg_addr[i],
|
||||
ret = ov965x_write(ov965x, frame_size_reg_addr[i],
|
||||
ov965x->frame_size->regs[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __ov965x_set_params(struct ov965x *ov965x)
|
||||
{
|
||||
struct i2c_client *client = ov965x->client;
|
||||
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
|
||||
int ret = 0;
|
||||
u8 reg;
|
||||
|
||||
if (ov965x->apply_frame_fmt) {
|
||||
reg = DEF_CLKRC + ov965x->fiv->clkrc_div;
|
||||
ret = ov965x_write(client, REG_CLKRC, reg);
|
||||
ret = ov965x_write(ov965x, REG_CLKRC, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_set_frame_size(ov965x);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ov965x_read(client, REG_TSLB, ®);
|
||||
ret = ov965x_read(ov965x, REG_TSLB, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
reg &= ~TSLB_YUYV_MASK;
|
||||
reg |= ov965x->tslb_reg;
|
||||
ret = ov965x_write(client, REG_TSLB, reg);
|
||||
ret = ov965x_write(ov965x, REG_TSLB, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
@ -1318,10 +1303,10 @@ static int __ov965x_set_params(struct ov965x *ov965x)
|
|||
* Select manual banding filter, the filter will
|
||||
* be enabled further if required.
|
||||
*/
|
||||
ret = ov965x_read(client, REG_COM11, ®);
|
||||
ret = ov965x_read(ov965x, REG_COM11, ®);
|
||||
if (!ret)
|
||||
reg |= COM11_BANDING;
|
||||
ret = ov965x_write(client, REG_COM11, reg);
|
||||
ret = ov965x_write(ov965x, REG_COM11, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/*
|
||||
|
@ -1333,12 +1318,11 @@ static int __ov965x_set_params(struct ov965x *ov965x)
|
|||
|
||||
static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov965x *ov965x = to_ov965x(sd);
|
||||
struct ov965x_ctrls *ctrls = &ov965x->ctrls;
|
||||
int ret = 0;
|
||||
|
||||
v4l2_dbg(1, debug, client, "%s: on: %d\n", __func__, on);
|
||||
v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on);
|
||||
|
||||
mutex_lock(&ov965x->lock);
|
||||
if (ov965x->streaming == !on) {
|
||||
|
@ -1358,7 +1342,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
|
|||
ctrls->update = 0;
|
||||
}
|
||||
if (!ret)
|
||||
ret = ov965x_write(client, REG_COM2,
|
||||
ret = ov965x_write(ov965x, REG_COM2,
|
||||
on ? 0x01 : 0x11);
|
||||
}
|
||||
if (!ret)
|
||||
|
@ -1421,6 +1405,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
|
|||
{
|
||||
int ret, i;
|
||||
int gpios[NUM_GPIOS];
|
||||
struct device *dev = regmap_get_device(ov965x->regmap);
|
||||
|
||||
gpios[GPIO_PWDN] = pdata->gpio_pwdn;
|
||||
gpios[GPIO_RST] = pdata->gpio_reset;
|
||||
|
@ -1430,7 +1415,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
|
|||
|
||||
if (!gpio_is_valid(gpio))
|
||||
continue;
|
||||
ret = devm_gpio_request_one(&ov965x->client->dev, gpio,
|
||||
ret = devm_gpio_request_one(dev, gpio,
|
||||
GPIOF_OUT_INIT_HIGH, "OV965X");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -1446,7 +1431,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
|
|||
|
||||
static int ov965x_configure_gpios(struct ov965x *ov965x)
|
||||
{
|
||||
struct device *dev = &ov965x->client->dev;
|
||||
struct device *dev = regmap_get_device(ov965x->regmap);
|
||||
|
||||
ov965x->gpios[GPIO_PWDN] = devm_gpiod_get_optional(dev, "powerdown",
|
||||
GPIOD_OUT_HIGH);
|
||||
|
@ -1467,7 +1452,6 @@ static int ov965x_configure_gpios(struct ov965x *ov965x)
|
|||
|
||||
static int ov965x_detect_sensor(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct ov965x *ov965x = to_ov965x(sd);
|
||||
u8 pid, ver;
|
||||
int ret;
|
||||
|
@ -1480,9 +1464,9 @@ static int ov965x_detect_sensor(struct v4l2_subdev *sd)
|
|||
msleep(25);
|
||||
|
||||
/* Check sensor revision */
|
||||
ret = ov965x_read(client, REG_PID, &pid);
|
||||
ret = ov965x_read(ov965x, REG_PID, &pid);
|
||||
if (!ret)
|
||||
ret = ov965x_read(client, REG_VER, &ver);
|
||||
ret = ov965x_read(ov965x, REG_VER, &ver);
|
||||
|
||||
__ov965x_set_power(ov965x, 0);
|
||||
|
||||
|
@ -1509,12 +1493,21 @@ static int ov965x_probe(struct i2c_client *client,
|
|||
struct v4l2_subdev *sd;
|
||||
struct ov965x *ov965x;
|
||||
int ret;
|
||||
static const struct regmap_config ov965x_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0xab,
|
||||
};
|
||||
|
||||
ov965x = devm_kzalloc(&client->dev, sizeof(*ov965x), GFP_KERNEL);
|
||||
if (!ov965x)
|
||||
return -ENOMEM;
|
||||
|
||||
ov965x->client = client;
|
||||
ov965x->regmap = devm_regmap_init_sccb(client, &ov965x_regmap_config);
|
||||
if (IS_ERR(ov965x->regmap)) {
|
||||
dev_err(&client->dev, "Failed to allocate register map\n");
|
||||
return PTR_ERR(ov965x->regmap);
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
if (pdata->mclk_frequency == 0) {
|
||||
|
@ -1527,7 +1520,7 @@ static int ov965x_probe(struct i2c_client *client,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (dev_fwnode(&client->dev)) {
|
||||
ov965x->clk = devm_clk_get(&ov965x->client->dev, NULL);
|
||||
ov965x->clk = devm_clk_get(&client->dev, NULL);
|
||||
if (IS_ERR(ov965x->clk))
|
||||
return PTR_ERR(ov965x->clk);
|
||||
ov965x->mclk_frequency = clk_get_rate(ov965x->clk);
|
||||
|
|
Загрузка…
Ссылка в новой задаче