Commit 361f3803 authored by Akinobu Mita's avatar Akinobu Mita Committed by Mauro Carvalho Chehab

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: default avatarAkinobu Mita <akinobu.mita@gmail.com>
Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com> (I2C parts)
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 5bbf3221
...@@ -787,6 +787,7 @@ config VIDEO_OV7740 ...@@ -787,6 +787,7 @@ config VIDEO_OV7740
config VIDEO_OV9650 config VIDEO_OV9650
tristate "OmniVision OV9650/OV9652 sensor support" tristate "OmniVision OV9650/OV9652 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
select REGMAP_SCCB
---help--- ---help---
This is a V4L2 sensor driver for the Omnivision This is a V4L2 sensor driver for the Omnivision
OV9650 and OV9652 camera sensors. OV9650 and OV9652 camera sensors.
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/media.h> #include <linux/media.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
...@@ -259,7 +260,7 @@ struct ov965x { ...@@ -259,7 +260,7 @@ struct ov965x {
/* Protects the struct fields below */ /* Protects the struct fields below */
struct mutex lock; struct mutex lock;
struct i2c_client *client; struct regmap *regmap;
/* Exposure row interval in us */ /* Exposure row interval in us */
unsigned int exp_row_interval; unsigned int exp_row_interval;
...@@ -424,51 +425,40 @@ static inline struct ov965x *to_ov965x(struct v4l2_subdev *sd) ...@@ -424,51 +425,40 @@ static inline struct ov965x *to_ov965x(struct v4l2_subdev *sd)
return container_of(sd, struct ov965x, 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; int ret;
unsigned int buf;
ret = i2c_transfer(client->adapter, &msg, 1); ret = regmap_read(ov965x->regmap, addr, &buf);
if (ret == 1) { if (!ret)
msg.flags = I2C_M_RD; *val = buf;
ret = i2c_transfer(client->adapter, &msg, 1);
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); __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); __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) const struct i2c_rv *regs)
{ {
int i, ret = 0; int i, ret = 0;
for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) 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; return ret;
} }
...@@ -486,7 +476,7 @@ static int ov965x_set_default_gamma_curve(struct ov965x *ov965x) ...@@ -486,7 +476,7 @@ static int ov965x_set_default_gamma_curve(struct ov965x *ov965x)
unsigned int i; unsigned int i;
for (i = 0; i < ARRAY_SIZE(gamma_curve); 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) if (ret < 0)
return ret; return ret;
...@@ -506,7 +496,7 @@ static int ov965x_set_color_matrix(struct ov965x *ov965x) ...@@ -506,7 +496,7 @@ static int ov965x_set_color_matrix(struct ov965x *ov965x)
unsigned int i; unsigned int i;
for (i = 0; i < ARRAY_SIZE(mtx); 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) if (ret < 0)
return ret; return ret;
...@@ -542,16 +532,15 @@ static int __ov965x_set_power(struct ov965x *ov965x, int on) ...@@ -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) static int ov965x_s_power(struct v4l2_subdev *sd, int on)
{ {
struct ov965x *ov965x = to_ov965x(sd); struct ov965x *ov965x = to_ov965x(sd);
struct i2c_client *client = ov965x->client;
int ret = 0; 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); mutex_lock(&ov965x->lock);
if (ov965x->power == !on) { if (ov965x->power == !on) {
ret = __ov965x_set_power(ov965x, on); ret = __ov965x_set_power(ov965x, on);
if (!ret && on) { if (!ret && on) {
ret = ov965x_write_array(client, ret = ov965x_write_array(ov965x,
ov965x_init_regs); ov965x_init_regs);
ov965x->apply_frame_fmt = 1; ov965x->apply_frame_fmt = 1;
ov965x->ctrls.update = 1; ov965x->ctrls.update = 1;
...@@ -609,13 +598,13 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value) ...@@ -609,13 +598,13 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
int ret; int ret;
u8 reg; u8 reg;
ret = ov965x_read(ov965x->client, REG_COM8, &reg); ret = ov965x_read(ov965x, REG_COM8, &reg);
if (!ret) { if (!ret) {
if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED) if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
reg &= ~COM8_BFILT; reg &= ~COM8_BFILT;
else else
reg |= COM8_BFILT; 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) if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED)
return 0; return 0;
...@@ -631,7 +620,7 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value) ...@@ -631,7 +620,7 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value)
ov965x->fiv->interval.numerator; ov965x->fiv->interval.numerator;
mbd = ((mbd / (light_freq * 2)) + 500) / 1000UL; 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) 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) ...@@ -639,17 +628,17 @@ static int ov965x_set_white_balance(struct ov965x *ov965x, int awb)
int ret; int ret;
u8 reg; u8 reg;
ret = ov965x_read(ov965x->client, REG_COM8, &reg); ret = ov965x_read(ov965x, REG_COM8, &reg);
if (!ret) { if (!ret) {
reg = awb ? reg | REG_COM8 : reg & ~REG_COM8; 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) { if (!ret && !awb) {
ret = ov965x_write(ov965x->client, REG_BLUE, ret = ov965x_write(ov965x, REG_BLUE,
ov965x->ctrls.blue_balance->val); ov965x->ctrls.blue_balance->val);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_write(ov965x->client, REG_RED, ret = ov965x_write(ov965x, REG_RED,
ov965x->ctrls.red_balance->val); ov965x->ctrls.red_balance->val);
} }
return ret; return ret;
...@@ -677,14 +666,13 @@ static int ov965x_set_brightness(struct ov965x *ov965x, int val) ...@@ -677,14 +666,13 @@ static int ov965x_set_brightness(struct ov965x *ov965x, int val)
return -EINVAL; return -EINVAL;
for (i = 0; i < NUM_BR_REGS && !ret; i++) 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]); regs[val][i]);
return ret; return ret;
} }
static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain) static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
{ {
struct i2c_client *client = ov965x->client;
struct ov965x_ctrls *ctrls = &ov965x->ctrls; struct ov965x_ctrls *ctrls = &ov965x->ctrls;
int ret = 0; int ret = 0;
u8 reg; u8 reg;
...@@ -693,14 +681,14 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain) ...@@ -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. * gain value in REG_VREF, REG_GAIN is not overwritten.
*/ */
if (ctrls->auto_gain->is_new) { if (ctrls->auto_gain->is_new) {
ret = ov965x_read(client, REG_COM8, &reg); ret = ov965x_read(ov965x, REG_COM8, &reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ctrls->auto_gain->val) if (ctrls->auto_gain->val)
reg |= COM8_AGC; reg |= COM8_AGC;
else else
reg &= ~COM8_AGC; reg &= ~COM8_AGC;
ret = ov965x_write(client, REG_COM8, reg); ret = ov965x_write(ov965x, REG_COM8, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -719,15 +707,15 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain) ...@@ -719,15 +707,15 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain)
rgain = (gain - ((1 << m) * 16)) / (1 << m); rgain = (gain - ((1 << m) * 16)) / (1 << m);
rgain |= (((1 << m) - 1) << 4); rgain |= (((1 << m) - 1) << 4);
ret = ov965x_write(client, REG_GAIN, rgain & 0xff); ret = ov965x_write(ov965x, REG_GAIN, rgain & 0xff);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_read(client, REG_VREF, &reg); ret = ov965x_read(ov965x, REG_VREF, &reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
reg &= ~VREF_GAIN_MASK; reg &= ~VREF_GAIN_MASK;
reg |= (((rgain >> 8) & 0x3) << 6); reg |= (((rgain >> 8) & 0x3) << 6);
ret = ov965x_write(client, REG_VREF, reg); ret = ov965x_write(ov965x, REG_VREF, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Return updated control's value to userspace */ /* Return updated control's value to userspace */
...@@ -742,10 +730,10 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value) ...@@ -742,10 +730,10 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
u8 com14, edge; u8 com14, edge;
int ret; int ret;
ret = ov965x_read(ov965x->client, REG_COM14, &com14); ret = ov965x_read(ov965x, REG_COM14, &com14);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_read(ov965x->client, REG_EDGE, &edge); ret = ov965x_read(ov965x, REG_EDGE, &edge);
if (ret < 0) if (ret < 0)
return ret; return ret;
com14 = value ? com14 | COM14_EDGE_EN : com14 & ~COM14_EDGE_EN; 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) ...@@ -756,33 +744,32 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value)
} else { } else {
com14 &= ~COM14_EEF_X2; com14 &= ~COM14_EEF_X2;
} }
ret = ov965x_write(ov965x->client, REG_COM14, com14); ret = ov965x_write(ov965x, REG_COM14, com14);
if (ret < 0) if (ret < 0)
return ret; return ret;
edge &= ~EDGE_FACTOR_MASK; edge &= ~EDGE_FACTOR_MASK;
edge |= ((u8)value & 0x0f); 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) static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
{ {
struct i2c_client *client = ov965x->client;
struct ov965x_ctrls *ctrls = &ov965x->ctrls; struct ov965x_ctrls *ctrls = &ov965x->ctrls;
bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO); bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO);
int ret; int ret;
u8 reg; u8 reg;
if (ctrls->auto_exp->is_new) { if (ctrls->auto_exp->is_new) {
ret = ov965x_read(client, REG_COM8, &reg); ret = ov965x_read(ov965x, REG_COM8, &reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (auto_exposure) if (auto_exposure)
reg |= (COM8_AEC | COM8_AGC); reg |= (COM8_AEC | COM8_AGC);
else else
reg &= ~(COM8_AEC | COM8_AGC); reg &= ~(COM8_AEC | COM8_AGC);
ret = ov965x_write(client, REG_COM8, reg); ret = ov965x_write(ov965x, REG_COM8, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -794,12 +781,12 @@ static int ov965x_set_exposure(struct ov965x *ov965x, int exp) ...@@ -794,12 +781,12 @@ static int ov965x_set_exposure(struct ov965x *ov965x, int exp)
* Manual exposure value * Manual exposure value
* [b15:b0] - AECHM (b15:b10), AECH (b9:b2), COM1 (b1:b0) * [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) if (!ret)
ret = ov965x_write(client, REG_AECH, ret = ov965x_write(ov965x, REG_AECH,
(exposure >> 2) & 0xff); (exposure >> 2) & 0xff);
if (!ret) if (!ret)
ret = ov965x_write(client, REG_AECHM, ret = ov965x_write(ov965x, REG_AECHM,
(exposure >> 10) & 0x3f); (exposure >> 10) & 0x3f);
/* Update the value to minimize rounding errors */ /* Update the value to minimize rounding errors */
ctrls->exposure->val = ((exposure * ov965x->exp_row_interval) ctrls->exposure->val = ((exposure * ov965x->exp_row_interval)
...@@ -822,7 +809,7 @@ static int ov965x_set_flip(struct ov965x *ov965x) ...@@ -822,7 +809,7 @@ static int ov965x_set_flip(struct ov965x *ov965x)
if (ov965x->ctrls.vflip->val) if (ov965x->ctrls.vflip->val)
mvfp |= MVFP_FLIP; mvfp |= MVFP_FLIP;
return ov965x_write(ov965x->client, REG_MVFP, mvfp); return ov965x_write(ov965x, REG_MVFP, mvfp);
} }
#define NUM_SAT_LEVELS 5 #define NUM_SAT_LEVELS 5
...@@ -846,7 +833,7 @@ static int ov965x_set_saturation(struct ov965x *ov965x, int val) ...@@ -846,7 +833,7 @@ static int ov965x_set_saturation(struct ov965x *ov965x, int val)
return -EINVAL; return -EINVAL;
for (i = 0; i < NUM_SAT_REGS && !ret; i++) 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; return ret;
} }
...@@ -856,16 +843,15 @@ static int ov965x_set_test_pattern(struct ov965x *ov965x, int value) ...@@ -856,16 +843,15 @@ static int ov965x_set_test_pattern(struct ov965x *ov965x, int value)
int ret; int ret;
u8 reg; u8 reg;
ret = ov965x_read(ov965x->client, REG_COM23, &reg); ret = ov965x_read(ov965x, REG_COM23, &reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
reg = value ? reg | COM23_TEST_MODE : reg & ~COM23_TEST_MODE; 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) static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
{ {
struct i2c_client *client = ov965x->client;
unsigned int exposure, gain, m; unsigned int exposure, gain, m;
u8 reg0, reg1, reg2; u8 reg0, reg1, reg2;
int ret; int ret;
...@@ -877,10 +863,10 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl) ...@@ -877,10 +863,10 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTOGAIN:
if (!ctrl->val) if (!ctrl->val)
return 0; return 0;
ret = ov965x_read(client, REG_GAIN, &reg0); ret = ov965x_read(ov965x, REG_GAIN, &reg0);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_read(client, REG_VREF, &reg1); ret = ov965x_read(ov965x, REG_VREF, &reg1);
if (ret < 0) if (ret < 0)
return ret; return ret;
gain = ((reg1 >> 6) << 8) | reg0; gain = ((reg1 >> 6) << 8) | reg0;
...@@ -891,13 +877,13 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl) ...@@ -891,13 +877,13 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) if (ctrl->val == V4L2_EXPOSURE_MANUAL)
return 0; return 0;
ret = ov965x_read(client, REG_COM1, &reg0); ret = ov965x_read(ov965x, REG_COM1, &reg0);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_read(client, REG_AECH, &reg1); ret = ov965x_read(ov965x, REG_AECH, &reg1);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_read(client, REG_AECHM, &reg2); ret = ov965x_read(ov965x, REG_AECHM, &reg2);
if (ret < 0) if (ret < 0)
return ret; return ret;
exposure = ((reg2 & 0x3f) << 10) | (reg1 << 2) | exposure = ((reg2 & 0x3f) << 10) | (reg1 << 2) |
...@@ -1279,32 +1265,31 @@ static int ov965x_set_frame_size(struct ov965x *ov965x) ...@@ -1279,32 +1265,31 @@ static int ov965x_set_frame_size(struct ov965x *ov965x)
int i, ret = 0; int i, ret = 0;
for (i = 0; ret == 0 && i < NUM_FMT_REGS; i++) 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]); ov965x->frame_size->regs[i]);
return ret; return ret;
} }
static int __ov965x_set_params(struct ov965x *ov965x) static int __ov965x_set_params(struct ov965x *ov965x)
{ {
struct i2c_client *client = ov965x->client;
struct ov965x_ctrls *ctrls = &ov965x->ctrls; struct ov965x_ctrls *ctrls = &ov965x->ctrls;
int ret = 0; int ret = 0;
u8 reg; u8 reg;
if (ov965x->apply_frame_fmt) { if (ov965x->apply_frame_fmt) {
reg = DEF_CLKRC + ov965x->fiv->clkrc_div; reg = DEF_CLKRC + ov965x->fiv->clkrc_div;
ret = ov965x_write(client, REG_CLKRC, reg); ret = ov965x_write(ov965x, REG_CLKRC, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_set_frame_size(ov965x); ret = ov965x_set_frame_size(ov965x);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ov965x_read(client, REG_TSLB, &reg); ret = ov965x_read(ov965x, REG_TSLB, &reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
reg &= ~TSLB_YUYV_MASK; reg &= ~TSLB_YUYV_MASK;
reg |= ov965x->tslb_reg; reg |= ov965x->tslb_reg;
ret = ov965x_write(client, REG_TSLB, reg); ret = ov965x_write(ov965x, REG_TSLB, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -1318,10 +1303,10 @@ static int __ov965x_set_params(struct ov965x *ov965x) ...@@ -1318,10 +1303,10 @@ static int __ov965x_set_params(struct ov965x *ov965x)
* Select manual banding filter, the filter will * Select manual banding filter, the filter will
* be enabled further if required. * be enabled further if required.
*/ */
ret = ov965x_read(client, REG_COM11, &reg); ret = ov965x_read(ov965x, REG_COM11, &reg);
if (!ret) if (!ret)
reg |= COM11_BANDING; reg |= COM11_BANDING;
ret = ov965x_write(client, REG_COM11, reg); ret = ov965x_write(ov965x, REG_COM11, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* /*
...@@ -1333,12 +1318,11 @@ static int __ov965x_set_params(struct ov965x *ov965x) ...@@ -1333,12 +1318,11 @@ static int __ov965x_set_params(struct ov965x *ov965x)
static int ov965x_s_stream(struct v4l2_subdev *sd, int on) 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 *ov965x = to_ov965x(sd);
struct ov965x_ctrls *ctrls = &ov965x->ctrls; struct ov965x_ctrls *ctrls = &ov965x->ctrls;
int ret = 0; 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); mutex_lock(&ov965x->lock);
if (ov965x->streaming == !on) { if (ov965x->streaming == !on) {
...@@ -1358,7 +1342,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on) ...@@ -1358,7 +1342,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
ctrls->update = 0; ctrls->update = 0;
} }
if (!ret) if (!ret)
ret = ov965x_write(client, REG_COM2, ret = ov965x_write(ov965x, REG_COM2,
on ? 0x01 : 0x11); on ? 0x01 : 0x11);
} }
if (!ret) if (!ret)
...@@ -1421,6 +1405,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x, ...@@ -1421,6 +1405,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
{ {
int ret, i; int ret, i;
int gpios[NUM_GPIOS]; int gpios[NUM_GPIOS];
struct device *dev = regmap_get_device(ov965x->regmap);
gpios[GPIO_PWDN] = pdata->gpio_pwdn; gpios[GPIO_PWDN] = pdata->gpio_pwdn;
gpios[GPIO_RST] = pdata->gpio_reset; gpios[GPIO_RST] = pdata->gpio_reset;
...@@ -1430,7 +1415,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x, ...@@ -1430,7 +1415,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
if (!gpio_is_valid(gpio)) if (!gpio_is_valid(gpio))
continue; continue;
ret = devm_gpio_request_one(&ov965x->client->dev, gpio, ret = devm_gpio_request_one(dev, gpio,
GPIOF_OUT_INIT_HIGH, "OV965X"); GPIOF_OUT_INIT_HIGH, "OV965X");
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1446,7 +1431,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x, ...@@ -1446,7 +1431,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x,
static int ov965x_configure_gpios(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", ov965x->gpios[GPIO_PWDN] = devm_gpiod_get_optional(dev, "powerdown",
GPIOD_OUT_HIGH); GPIOD_OUT_HIGH);
...@@ -1467,7 +1452,6 @@ static int ov965x_configure_gpios(struct ov965x *ov965x) ...@@ -1467,7 +1452,6 @@ static int ov965x_configure_gpios(struct ov965x *ov965x)
static int ov965x_detect_sensor(struct v4l2_subdev *sd) static int ov965x_detect_sensor(struct v4l2_subdev *sd)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov965x *ov965x = to_ov965x(sd); struct ov965x *ov965x = to_ov965x(sd);
u8 pid, ver; u8 pid, ver;
int ret; int ret;
...@@ -1480,9 +1464,9 @@ static int ov965x_detect_sensor(struct v4l2_subdev *sd) ...@@ -1480,9 +1464,9 @@ static int ov965x_detect_sensor(struct v4l2_subdev *sd)
msleep(25); msleep(25);
/* Check sensor revision */ /* Check sensor revision */
ret = ov965x_read(client, REG_PID, &pid); ret = ov965x_read(ov965x, REG_PID, &pid);
if (!ret) if (!ret)
ret = ov965x_read(client, REG_VER, &ver); ret = ov965x_read(ov965x, REG_VER, &ver);
__ov965x_set_power(ov965x, 0); __ov965x_set_power(ov965x, 0);
...@@ -1509,12 +1493,21 @@ static int ov965x_probe(struct i2c_client *client, ...@@ -1509,12 +1493,21 @@ static int ov965x_probe(struct i2c_client *client,
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
struct ov965x *ov965x; struct ov965x *ov965x;
int ret; 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); ov965x = devm_kzalloc(&client->dev, sizeof(*ov965x), GFP_KERNEL);
if (!ov965x) if (!ov965x)
return -ENOMEM; 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) {
if (pdata->mclk_frequency == 0) { if (pdata->mclk_frequency == 0) {
...@@ -1527,7 +1520,7 @@ static int ov965x_probe(struct i2c_client *client, ...@@ -1527,7 +1520,7 @@ static int ov965x_probe(struct i2c_client *client,
if (ret < 0) if (ret < 0)
return ret; return ret;
} else if (dev_fwnode(&client->dev)) { } 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)) if (IS_ERR(ov965x->clk))
return PTR_ERR(ov965x->clk); return PTR_ERR(ov965x->clk);
ov965x->mclk_frequency = clk_get_rate(ov965x->clk); ov965x->mclk_frequency = clk_get_rate(ov965x->clk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment