bd36c22f6ec7bf2aa7ddf519a1c69176a036d121
[openwrt/staging/xback.git] /
1 From a04966a5f739570c32ac6bcc44c68643bf836780 Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Sun, 16 Oct 2022 09:15:13 +0300
4 Subject: [PATCH] media: i2c: imx290: Simplify error handling when
5 writing registers
6
7 Upstream commit e611f3dac54c.
8
9 Error handling for register writes requires checking the error status of
10 every single write. This makes the code complex, or incorrect when the
11 checks are omitted. Simplify this by passing a pointer to an error code
12 to the imx290_write_reg() function, which allows writing multiple
13 registers in a row and only checking for errors at the end.
14
15 While at it, rename imx290_write_reg() to imx290_write() as there's
16 nothing else than registers to write, and rename imx290_read_reg()
17 accordingly.
18
19 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
20 Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>
21 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
22 ---
23 drivers/media/i2c/imx290.c | 86 ++++++++++++++------------------------
24 1 file changed, 32 insertions(+), 54 deletions(-)
25
26 --- a/drivers/media/i2c/imx290.c
27 +++ b/drivers/media/i2c/imx290.c
28 @@ -367,7 +367,7 @@ static inline struct imx290 *to_imx290(s
29 return container_of(_sd, struct imx290, sd);
30 }
31
32 -static int __always_unused imx290_read_reg(struct imx290 *imx290, u32 addr, u32 *value)
33 +static int __always_unused imx290_read(struct imx290 *imx290, u32 addr, u32 *value)
34 {
35 u8 data[3] = { 0, 0, 0 };
36 int ret;
37 @@ -385,17 +385,23 @@ static int __always_unused imx290_read_r
38 return 0;
39 }
40
41 -static int imx290_write_reg(struct imx290 *imx290, u32 addr, u32 value)
42 +static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)
43 {
44 u8 data[3] = { value & 0xff, (value >> 8) & 0xff, value >> 16 };
45 int ret;
46
47 + if (err && *err)
48 + return *err;
49 +
50 ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
51 data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
52 - if (ret < 0)
53 + if (ret < 0) {
54 dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
55 ((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
56 addr & IMX290_REG_ADDR_MASK, ret);
57 + if (err)
58 + *err = ret;
59 + }
60
61 return ret;
62 }
63 @@ -408,7 +414,7 @@ static int imx290_set_register_array(str
64 int ret;
65
66 for (i = 0; i < num_settings; ++i, ++settings) {
67 - ret = imx290_write_reg(imx290, settings->reg, settings->val);
68 + ret = imx290_write(imx290, settings->reg, settings->val, NULL);
69 if (ret < 0)
70 return ret;
71 }
72 @@ -419,29 +425,16 @@ static int imx290_set_register_array(str
73 return 0;
74 }
75
76 -static int imx290_set_gain(struct imx290 *imx290, u32 value)
77 -{
78 - int ret;
79 -
80 - ret = imx290_write_reg(imx290, IMX290_GAIN, value);
81 - if (ret)
82 - dev_err(imx290->dev, "Unable to write gain\n");
83 -
84 - return ret;
85 -}
86 -
87 /* Stop streaming */
88 static int imx290_stop_streaming(struct imx290 *imx290)
89 {
90 - int ret;
91 + int ret = 0;
92
93 - ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x01);
94 - if (ret < 0)
95 - return ret;
96 + imx290_write(imx290, IMX290_STANDBY, 0x01, &ret);
97
98 msleep(30);
99
100 - return imx290_write_reg(imx290, IMX290_XMSTA, 0x01);
101 + return imx290_write(imx290, IMX290_XMSTA, 0x01, &ret);
102 }
103
104 static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
105 @@ -456,25 +449,25 @@ static int imx290_set_ctrl(struct v4l2_c
106
107 switch (ctrl->id) {
108 case V4L2_CID_GAIN:
109 - ret = imx290_set_gain(imx290, ctrl->val);
110 + ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
111 break;
112 case V4L2_CID_TEST_PATTERN:
113 if (ctrl->val) {
114 - imx290_write_reg(imx290, IMX290_BLKLEVEL, 0);
115 + imx290_write(imx290, IMX290_BLKLEVEL, 0, &ret);
116 usleep_range(10000, 11000);
117 - imx290_write_reg(imx290, IMX290_PGCTRL,
118 - (u8)(IMX290_PGCTRL_REGEN |
119 - IMX290_PGCTRL_THRU |
120 - IMX290_PGCTRL_MODE(ctrl->val)));
121 + imx290_write(imx290, IMX290_PGCTRL,
122 + (u8)(IMX290_PGCTRL_REGEN |
123 + IMX290_PGCTRL_THRU |
124 + IMX290_PGCTRL_MODE(ctrl->val)), &ret);
125 } else {
126 - imx290_write_reg(imx290, IMX290_PGCTRL, 0x00);
127 + imx290_write(imx290, IMX290_PGCTRL, 0x00, &ret);
128 usleep_range(10000, 11000);
129 if (imx290->bpp == 10)
130 - imx290_write_reg(imx290, IMX290_BLKLEVEL,
131 - 0x3c);
132 + imx290_write(imx290, IMX290_BLKLEVEL, 0x3c,
133 + &ret);
134 else /* 12 bits per pixel */
135 - imx290_write_reg(imx290, IMX290_BLKLEVEL,
136 - 0xf0);
137 + imx290_write(imx290, IMX290_BLKLEVEL, 0xf0,
138 + &ret);
139 }
140 break;
141 default:
142 @@ -695,7 +688,8 @@ static int imx290_start_streaming(struct
143 return ret;
144 }
145
146 - ret = imx290_write_reg(imx290, IMX290_HMAX, imx290->current_mode->hmax);
147 + ret = imx290_write(imx290, IMX290_HMAX, imx290->current_mode->hmax,
148 + NULL);
149 if (ret)
150 return ret;
151
152 @@ -706,14 +700,12 @@ static int imx290_start_streaming(struct
153 return ret;
154 }
155
156 - ret = imx290_write_reg(imx290, IMX290_STANDBY, 0x00);
157 - if (ret < 0)
158 - return ret;
159 + imx290_write(imx290, IMX290_STANDBY, 0x00, &ret);
160
161 msleep(30);
162
163 /* Start streaming */
164 - return imx290_write_reg(imx290, IMX290_XMSTA, 0x00);
165 + return imx290_write(imx290, IMX290_XMSTA, 0x00, &ret);
166 }
167
168 static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
169 @@ -772,27 +764,13 @@ static int imx290_set_data_lanes(struct
170 * validated in probe itself
171 */
172 dev_err(imx290->dev, "Lane configuration not supported\n");
173 - ret = -EINVAL;
174 - goto exit;
175 - }
176 -
177 - ret = imx290_write_reg(imx290, IMX290_PHY_LANE_NUM, laneval);
178 - if (ret) {
179 - dev_err(imx290->dev, "Error setting Physical Lane number register\n");
180 - goto exit;
181 - }
182 -
183 - ret = imx290_write_reg(imx290, IMX290_CSI_LANE_MODE, laneval);
184 - if (ret) {
185 - dev_err(imx290->dev, "Error setting CSI Lane mode register\n");
186 - goto exit;
187 + return -EINVAL;
188 }
189
190 - ret = imx290_write_reg(imx290, IMX290_FR_FDG_SEL, frsel);
191 - if (ret)
192 - dev_err(imx290->dev, "Error setting FR/FDG SEL register\n");
193 + imx290_write(imx290, IMX290_PHY_LANE_NUM, laneval, &ret);
194 + imx290_write(imx290, IMX290_CSI_LANE_MODE, laneval, &ret);
195 + imx290_write(imx290, IMX290_FR_FDG_SEL, frsel, &ret);
196
197 -exit:
198 return ret;
199 }
200