summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/ov5647.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/ov5647.c')
-rw-r--r--drivers/media/i2c/ov5647.c98
1 files changed, 59 insertions, 39 deletions
diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c
index 847a7bbb69c5..e193fef4fced 100644
--- a/drivers/media/i2c/ov5647.c
+++ b/drivers/media/i2c/ov5647.c
@@ -58,6 +58,7 @@
#define OV5647_REG_MIPI_CTRL00 0x4800
#define OV5647_REG_MIPI_CTRL14 0x4814
#define OV5647_REG_AWB 0x5001
+#define OV5647_REG_ISPCTRL3D 0x503d
#define REG_TERM 0xfffe
#define VAL_TERM 0xfe
@@ -108,7 +109,6 @@ struct ov5647 {
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *exposure;
- bool streaming;
};
static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd)
@@ -116,6 +116,20 @@ static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd)
return container_of(sd, struct ov5647, sd);
}
+static const char * const ov5647_test_pattern_menu[] = {
+ "Disabled",
+ "Color Bars",
+ "Color Squares",
+ "Random Data",
+};
+
+static const u8 ov5647_test_pattern_val[] = {
+ 0x00, /* Disabled */
+ 0x80, /* Color Bars */
+ 0x82, /* Color Squares */
+ 0x81, /* Random Data */
+};
+
static const struct regval_list sensor_oe_disable_regs[] = {
{0x3000, 0x00},
{0x3001, 0x00},
@@ -614,23 +628,29 @@ static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val)
static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val)
{
- unsigned char data_w[2] = { reg >> 8, reg & 0xff };
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ u8 buf[2] = { reg >> 8, reg & 0xff };
+ struct i2c_msg msg[2];
int ret;
- ret = i2c_master_send(client, data_w, 2);
- if (ret < 0) {
- dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
- __func__, reg);
- return ret;
+ 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 = buf;
+ msg[1].len = 1;
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+ if (ret != 2) {
+ dev_err(&client->dev, "%s: i2c read error, reg: %x = %d\n",
+ __func__, reg, ret);
+ return ret >= 0 ? -EINVAL : ret;
}
- ret = i2c_master_recv(client, val, 1);
- if (ret < 0) {
- dev_dbg(&client->dev, "%s: i2c read error, reg: %x\n",
- __func__, reg);
- return ret;
- }
+ *val = buf[0];
return 0;
}
@@ -862,7 +882,7 @@ __ov5647_get_pad_crop(struct ov5647 *ov5647,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov5647->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov5647->mode->crop;
}
@@ -877,10 +897,6 @@ static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
int ret;
mutex_lock(&sensor->lock);
- if (sensor->streaming == enable) {
- mutex_unlock(&sensor->lock);
- return 0;
- }
if (enable) {
ret = pm_runtime_resume_and_get(&client->dev);
@@ -901,7 +917,6 @@ static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
pm_runtime_put(&client->dev);
}
- sensor->streaming = enable;
mutex_unlock(&sensor->lock);
return 0;
@@ -960,8 +975,8 @@ static int ov5647_get_pad_fmt(struct v4l2_subdev *sd,
mutex_lock(&sensor->lock);
switch (format->which) {
case V4L2_SUBDEV_FORMAT_TRY:
- sensor_format = v4l2_subdev_get_try_format(sd, sd_state,
- format->pad);
+ sensor_format = v4l2_subdev_state_get_format(sd_state,
+ format->pad);
break;
default:
sensor_format = &sensor->mode->format;
@@ -989,7 +1004,7 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd,
/* Update the sensor mode and apply at it at streamon time. */
mutex_lock(&sensor->lock);
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = mode->format;
+ *v4l2_subdev_state_get_format(sd_state, format->pad) = mode->format;
} else {
int exposure_max, exposure_def;
int hblank, vblank;
@@ -1106,8 +1121,8 @@ static int ov5647_detect(struct v4l2_subdev *sd)
static int ov5647_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *format =
- v4l2_subdev_get_try_format(sd, fh->state, 0);
- struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
+ v4l2_subdev_state_get_format(fh->state, 0);
+ struct v4l2_rect *crop = v4l2_subdev_state_get_crop(fh->state, 0);
crop->left = OV5647_PIXEL_ARRAY_LEFT;
crop->top = OV5647_PIXEL_ARRAY_TOP;
@@ -1242,6 +1257,10 @@ static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl)
ret = ov5647_write16(sd, OV5647_REG_VTS_HI,
sensor->mode->format.height + ctrl->val);
break;
+ case V4L2_CID_TEST_PATTERN:
+ ret = ov5647_write(sd, OV5647_REG_ISPCTRL3D,
+ ov5647_test_pattern_val[ctrl->val]);
+ break;
/* Read-only, but we adjust it based on mode. */
case V4L2_CID_PIXEL_RATE:
@@ -1270,7 +1289,7 @@ static int ov5647_init_controls(struct ov5647 *sensor)
struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
int hblank, exposure_max, exposure_def;
- v4l2_ctrl_handler_init(&sensor->ctrls, 8);
+ v4l2_ctrl_handler_init(&sensor->ctrls, 9);
v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
V4L2_CID_AUTOGAIN, 0, 1, 1, 0);
@@ -1314,6 +1333,11 @@ static int ov5647_init_controls(struct ov5647 *sensor)
sensor->mode->vts -
sensor->mode->format.height);
+ v4l2_ctrl_new_std_menu_items(&sensor->ctrls, &ov5647_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(ov5647_test_pattern_menu) - 1,
+ 0, 0, ov5647_test_pattern_menu);
+
if (sensor->ctrls.error)
goto handler_free;
@@ -1336,24 +1360,21 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np)
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY,
};
- struct device_node *ep;
+ struct device_node *ep __free(device_node) =
+ of_graph_get_endpoint_by_regs(np, 0, -1);
int ret;
- ep = of_graph_get_next_endpoint(np, NULL);
if (!ep)
return -EINVAL;
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &bus_cfg);
if (ret)
- goto out;
+ return ret;
sensor->clock_ncont = bus_cfg.bus.mipi_csi2.flags &
V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
-out:
- of_node_put(ep);
-
- return ret;
+ return 0;
}
static int ov5647_probe(struct i2c_client *client)
@@ -1377,11 +1398,10 @@ static int ov5647_probe(struct i2c_client *client)
}
}
- sensor->xclk = devm_clk_get(dev, NULL);
- if (IS_ERR(sensor->xclk)) {
- dev_err(dev, "could not get xclk");
- return PTR_ERR(sensor->xclk);
- }
+ sensor->xclk = devm_v4l2_sensor_clk_get(dev, NULL);
+ if (IS_ERR(sensor->xclk))
+ return dev_err_probe(dev, PTR_ERR(sensor->xclk),
+ "could not get xclk\n");
xclk_freq = clk_get_rate(sensor->xclk);
if (xclk_freq != 25000000) {
@@ -1466,7 +1486,7 @@ static const struct dev_pm_ops ov5647_pm_ops = {
};
static const struct i2c_device_id ov5647_id[] = {
- { "ov5647", 0 },
+ { "ov5647" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, ov5647_id);
@@ -1485,7 +1505,7 @@ static struct i2c_driver ov5647_driver = {
.name = "ov5647",
.pm = &ov5647_pm_ops,
},
- .probe_new = ov5647_probe,
+ .probe = ov5647_probe,
.remove = ov5647_remove,
.id_table = ov5647_id,
};