mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 10:39:04 +00:00
201 lines
5.9 KiB
Diff
201 lines
5.9 KiB
Diff
|
From a04966a5f739570c32ac6bcc44c68643bf836780 Mon Sep 17 00:00:00 2001
|
||
|
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||
|
Date: Sun, 16 Oct 2022 09:15:13 +0300
|
||
|
Subject: [PATCH] media: i2c: imx290: Simplify error handling when
|
||
|
writing registers
|
||
|
|
||
|
Upstream commit e611f3dac54c.
|
||
|
|
||
|
Error handling for register writes requires checking the error status of
|
||
|
every single write. This makes the code complex, or incorrect when the
|
||
|
checks are omitted. Simplify this by passing a pointer to an error code
|
||
|
to the imx290_write_reg() function, which allows writing multiple
|
||
|
registers in a row and only checking for errors at the end.
|
||
|
|
||
|
While at it, rename imx290_write_reg() to imx290_write() as there's
|
||
|
nothing else than registers to write, and rename imx290_read_reg()
|
||
|
accordingly.
|
||
|
|
||
|
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||
|
Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>
|
||
|
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||
|
---
|
||
|
drivers/media/i2c/imx290.c | 86 ++++++++++++++------------------------
|
||
|
1 file changed, 32 insertions(+), 54 deletions(-)
|
||
|
|
||
|
--- a/drivers/media/i2c/imx290.c
|
||
|
+++ b/drivers/media/i2c/imx290.c
|
||
|
@@ -367,7 +367,7 @@ static inline struct imx290 *to_imx290(s
|
||
|
return container_of(_sd, struct imx290, sd);
|
||
|
}
|
||
|
|
||
|
-static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value)
|
||
|
+static int __always_unused imx290_read(struct imx290 *imx290, u32 addr, u32 *value)
|
||
|
{
|
||
|
u8 data[3] = { 0, 0, 0 };
|
||
|
int ret;
|
||
|
@@ -385,17 +385,23 @@ static int __always_unused imx290_read_r
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
|
||
|
+static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)
|
||
|
{
|
||
|
u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
|
||
|
int ret;
|
||
|
|
||
|
+ if (err && *err)
|
||
|
+ return *err;
|
||
|
+
|
||
|
ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
|
||
|
data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
|
||
|
- if (ret < 0)
|
||
|
+ if (ret < 0) {
|
||
|
dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
|
||
|
((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
|
||
|
addr & IMX290_REG_ADDR_MASK, ret);
|
||
|
+ if (err)
|
||
|
+ *err = ret;
|
||
|
+ }
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
@@ -408,7 +414,7 @@ static int imx290_set_register_array(str
|
||
|
int ret;
|
||
|
|
||
|
for (i = 0; i < num_settings; ++i, ++settings) {
|
||
|
- ret = imx290_write_reg(imx290, settings->reg, settings->val);
|
||
|
+ ret = imx290_write(imx290, settings->reg, settings->val, NULL);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
}
|
||
|
@@ -419,29 +425,16 @@ static int imx290_set_register_array(str
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-static int imx290_set_gain(struct imx290 *imx290, u32 value)
|
||
|
-{
|
||
|
- int ret;
|
||
|
-
|
||
|
- ret = imx290_write_reg(imx290, IMX290_GAIN, value);
|
||
|
- if (ret)
|
||
|
- dev_err(imx290->dev, "Unable to write gain\n");
|
||
|
-
|
||
|
- return ret;
|
||
|
-}
|
||
|
-
|
||
|
/* Stop streaming */
|
||
|
static int imx290_stop_streaming(struct imx290 *imx290)
|
||
|
{
|
||
|
- int ret;
|
||
|
+ int ret = 0;
|
||
|
|
||
|
- ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x01);
|
||
|
- if (ret < 0)
|
||
|
- return ret;
|
||
|
+ imx290_write(imx290, IMX290_STANDBY, 0x01, &ret);
|
||
|
|
||
|
msleep(30);
|
||
|
|
||
|
- return imx290_write_reg(imx290, IMX290_XMSTA, 0x01);
|
||
|
+ return imx290_write(imx290, IMX290_XMSTA, 0x01, &ret);
|
||
|
}
|
||
|
|
||
|
static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
|
||
|
@@ -456,25 +449,25 @@ static int imx290_set_ctrl(struct v4l2_c
|
||
|
|
||
|
switch (ctrl->id) {
|
||
|
case V4L2_CID_GAIN:
|
||
|
- ret = imx290_set_gain(imx290, ctrl->val);
|
||
|
+ ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
|
||
|
break;
|
||
|
case V4L2_CID_TEST_PATTERN:
|
||
|
if (ctrl->val) {
|
||
|
- imx290_write_reg(imx290, IMX290_BLKLEVEL, 0);
|
||
|
+ imx290_write(imx290, IMX290_BLKLEVEL, 0, &ret);
|
||
|
usleep_range(10000, 11000);
|
||
|
- imx290_write_reg(imx290, IMX290_PGCTRL,
|
||
|
- (u8)(IMX290_PGCTRL_REGEN |
|
||
|
- IMX290_PGCTRL_THRU |
|
||
|
- IMX290_PGCTRL_MODE(ctrl->val)));
|
||
|
+ imx290_write(imx290, IMX290_PGCTRL,
|
||
|
+ (u8)(IMX290_PGCTRL_REGEN |
|
||
|
+ IMX290_PGCTRL_THRU |
|
||
|
+ IMX290_PGCTRL_MODE(ctrl->val)), &ret);
|
||
|
} else {
|
||
|
- imx290_write_reg(imx290, IMX290_PGCTRL, 0x00);
|
||
|
+ imx290_write(imx290, IMX290_PGCTRL, 0x00, &ret);
|
||
|
usleep_range(10000, 11000);
|
||
|
if (imx290->bpp == 10)
|
||
|
- imx290_write_reg(imx290, IMX290_BLKLEVEL,
|
||
|
- 0x3c);
|
||
|
+ imx290_write(imx290, IMX290_BLKLEVEL, 0x3c,
|
||
|
+ &ret);
|
||
|
else /* 12 bits per pixel */
|
||
|
- imx290_write_reg(imx290, IMX290_BLKLEVEL,
|
||
|
- 0xf0);
|
||
|
+ imx290_write(imx290, IMX290_BLKLEVEL, 0xf0,
|
||
|
+ &ret);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
@@ -695,7 +688,8 @@ static int imx290_start_streaming(struct
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
- ret = imx290_write_reg(imx290, IMX290_HMAX, imx290->current_mode->hmax);
|
||
|
+ ret = imx290_write(imx290, IMX290_HMAX, imx290->current_mode->hmax,
|
||
|
+ NULL);
|
||
|
if (ret)
|
||
|
return ret;
|
||
|
|
||
|
@@ -706,14 +700,12 @@ static int imx290_start_streaming(struct
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
- ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x00);
|
||
|
- if (ret < 0)
|
||
|
- return ret;
|
||
|
+ imx290_write(imx290, IMX290_STANDBY, 0x00, &ret);
|
||
|
|
||
|
msleep(30);
|
||
|
|
||
|
/* Start streaming */
|
||
|
- return imx290_write_reg(imx290, IMX290_XMSTA, 0x00);
|
||
|
+ return imx290_write(imx290, IMX290_XMSTA, 0x00, &ret);
|
||
|
}
|
||
|
|
||
|
static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
|
||
|
@@ -772,27 +764,13 @@ static int imx290_set_data_lanes(struct
|
||
|
* validated in probe itself
|
||
|
*/
|
||
|
dev_err(imx290->dev, "Lane configuration not supported\n");
|
||
|
- ret = -EINVAL;
|
||
|
- goto exit;
|
||
|
- }
|
||
|
-
|
||
|
- ret = imx290_write_reg(imx290, IMX290_PHY_LANE_NUM, laneval);
|
||
|
- if (ret) {
|
||
|
- dev_err(imx290->dev, "Error setting Physical Lane number register\n");
|
||
|
- goto exit;
|
||
|
- }
|
||
|
-
|
||
|
- ret = imx290_write_reg(imx290, IMX290_CSI_LANE_MODE, laneval);
|
||
|
- if (ret) {
|
||
|
- dev_err(imx290->dev, "Error setting CSI Lane mode register\n");
|
||
|
- goto exit;
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
|
||
|
- ret = imx290_write_reg(imx290, IMX290_FR_FDG_SEL, frsel);
|
||
|
- if (ret)
|
||
|
- dev_err(imx290->dev, "Error setting FR/FDG SEL register\n");
|
||
|
+ imx290_write(imx290, IMX290_PHY_LANE_NUM, laneval, &ret);
|
||
|
+ imx290_write(imx290, IMX290_CSI_LANE_MODE, laneval, &ret);
|
||
|
+ imx290_write(imx290, IMX290_FR_FDG_SEL, frsel, &ret);
|
||
|
|
||
|
-exit:
|
||
|
return ret;
|
||
|
}
|
||
|
|