1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
From fd31edb90963d91390b372153028fab79e7f060e Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Mon, 17 Oct 2022 12:44:27 +0200
Subject: [PATCH] media: i2c: imx290: Rename, extend and expand usage
of imx290_pixfmt
Upstream commit 10591fe63691
The imx290_pixfmt structure contains information about formats,
currently limited to the bpp value. Extend it with the register settings
for each format, and rename it to imx290_format_info to make its purpose
clearer. Add a function named imx290_format_info() to look up format
info for a media bus code, and use it through the code. This allows
dropping the imx290 bpp field as the value is now looked up dynamically.
The error handling in imx290_setup_format() can also be dropped, as the
format is guaranteed by imx290_set_fmt() to be valid.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
---
drivers/media/i2c/imx290.c | 99 ++++++++++++++++++++++----------------
1 file changed, 58 insertions(+), 41 deletions(-)
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -182,7 +182,6 @@ struct imx290 {
struct media_pad pad;
const struct imx290_mode *current_mode;
- u8 bpp;
struct regulator_bulk_data supplies[IMX290_NUM_SUPPLIES];
struct gpio_desc *rst_gpio;
@@ -414,16 +413,41 @@ static inline int imx290_modes_num(const
return ARRAY_SIZE(imx290_modes_4lanes);
}
-struct imx290_pixfmt {
+struct imx290_format_info {
u32 code;
u8 bpp;
+ const struct imx290_regval *regs;
+ unsigned int num_regs;
};
-static const struct imx290_pixfmt imx290_formats[] = {
- { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
- { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
+static const struct imx290_format_info imx290_formats[] = {
+ {
+ .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .bpp = 10,
+ .regs = imx290_10bit_settings,
+ .num_regs = ARRAY_SIZE(imx290_10bit_settings),
+ }, {
+ .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+ .bpp = 12,
+ .regs = imx290_12bit_settings,
+ .num_regs = ARRAY_SIZE(imx290_12bit_settings),
+ }
};
+static const struct imx290_format_info *imx290_format_info(u32 code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(imx290_formats); ++i) {
+ const struct imx290_format_info *info = &imx290_formats[i];
+
+ if (info->code == code)
+ return info;
+ }
+
+ return NULL;
+}
+
/* -----------------------------------------------------------------------------
* Register access
*/
@@ -516,40 +540,31 @@ static int imx290_set_data_lanes(struct
}
static int imx290_set_black_level(struct imx290 *imx290,
+ const struct v4l2_mbus_framefmt *format,
unsigned int black_level, int *err)
{
+ unsigned int bpp = imx290_format_info(format->code)->bpp;
+
return imx290_write(imx290, IMX290_BLKLEVEL,
- black_level >> (16 - imx290->bpp), err);
+ black_level >> (16 - bpp), err);
}
static int imx290_setup_format(struct imx290 *imx290,
const struct v4l2_mbus_framefmt *format)
{
- const struct imx290_regval *regs;
- unsigned int num_regs;
+ const struct imx290_format_info *info;
int ret;
- switch (format->code) {
- case MEDIA_BUS_FMT_SRGGB10_1X10:
- regs = imx290_10bit_settings;
- num_regs = ARRAY_SIZE(imx290_10bit_settings);
- break;
- case MEDIA_BUS_FMT_SRGGB12_1X12:
- regs = imx290_12bit_settings;
- num_regs = ARRAY_SIZE(imx290_12bit_settings);
- break;
- default:
- dev_err(imx290->dev, "Unknown pixel format\n");
- return -EINVAL;
- }
+ info = imx290_format_info(format->code);
- ret = imx290_set_register_array(imx290, regs, num_regs);
+ ret = imx290_set_register_array(imx290, info->regs, info->num_regs);
if (ret < 0) {
dev_err(imx290->dev, "Could not set format registers\n");
return ret;
}
- return imx290_set_black_level(imx290, IMX290_BLACK_LEVEL_DEFAULT, &ret);
+ return imx290_set_black_level(imx290, format,
+ IMX290_BLACK_LEVEL_DEFAULT, &ret);
}
/* ----------------------------------------------------------------------------
@@ -560,6 +575,8 @@ static int imx290_set_ctrl(struct v4l2_c
{
struct imx290 *imx290 = container_of(ctrl->handler,
struct imx290, ctrls);
+ const struct v4l2_mbus_framefmt *format;
+ struct v4l2_subdev_state *state;
int ret = 0;
/*
@@ -575,6 +592,9 @@ static int imx290_set_ctrl(struct v4l2_c
if (!pm_runtime_get_if_in_use(imx290->dev))
return 0;
+ state = v4l2_subdev_get_locked_active_state(&imx290->sd);
+ format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
+
switch (ctrl->id) {
case V4L2_CID_ANALOGUE_GAIN:
ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
@@ -587,7 +607,7 @@ static int imx290_set_ctrl(struct v4l2_c
case V4L2_CID_TEST_PATTERN:
if (ctrl->val) {
- imx290_set_black_level(imx290, 0, &ret);
+ imx290_set_black_level(imx290, format, 0, &ret);
usleep_range(10000, 11000);
imx290_write(imx290, IMX290_PGCTRL,
(u8)(IMX290_PGCTRL_REGEN |
@@ -596,8 +616,8 @@ static int imx290_set_ctrl(struct v4l2_c
} else {
imx290_write(imx290, IMX290_PGCTRL, 0x00, &ret);
usleep_range(10000, 11000);
- imx290_set_black_level(imx290, IMX290_BLACK_LEVEL_DEFAULT,
- &ret);
+ imx290_set_black_level(imx290, format,
+ IMX290_BLACK_LEVEL_DEFAULT, &ret);
}
break;
@@ -627,6 +647,7 @@ static const char * const imx290_test_pa
};
static void imx290_ctrl_update(struct imx290 *imx290,
+ const struct v4l2_mbus_framefmt *format,
const struct imx290_mode *mode)
{
unsigned int hblank = mode->hmax - mode->width;
@@ -636,7 +657,7 @@ static void imx290_ctrl_update(struct im
/* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
pixel_rate = link_freq * 2 * imx290->nlanes;
- do_div(pixel_rate, imx290->bpp);
+ do_div(pixel_rate, imx290_format_info(format->code)->bpp);
__v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
__v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, pixel_rate);
@@ -838,8 +859,7 @@ static int imx290_enum_frame_size(struct
const struct imx290 *imx290 = to_imx290(sd);
const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
- if ((fse->code != imx290_formats[0].code) &&
- (fse->code != imx290_formats[1].code))
+ if (!imx290_format_info(fse->code))
return -EINVAL;
if (fse->index >= imx290_modes_num(imx290))
@@ -860,7 +880,6 @@ static int imx290_set_fmt(struct v4l2_su
struct imx290 *imx290 = to_imx290(sd);
const struct imx290_mode *mode;
struct v4l2_mbus_framefmt *format;
- unsigned int i;
mode = v4l2_find_nearest_size(imx290_modes_ptr(imx290),
imx290_modes_num(imx290), width, height,
@@ -869,23 +888,17 @@ static int imx290_set_fmt(struct v4l2_su
fmt->format.width = mode->width;
fmt->format.height = mode->height;
- for (i = 0; i < ARRAY_SIZE(imx290_formats); i++)
- if (imx290_formats[i].code == fmt->format.code)
- break;
+ if (!imx290_format_info(fmt->format.code))
+ fmt->format.code = imx290_formats[0].code;
- if (i >= ARRAY_SIZE(imx290_formats))
- i = 0;
-
- fmt->format.code = imx290_formats[i].code;
fmt->format.field = V4L2_FIELD_NONE;
format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
imx290->current_mode = mode;
- imx290->bpp = imx290_formats[i].bpp;
- imx290_ctrl_update(imx290, mode);
+ imx290_ctrl_update(imx290, &fmt->format, mode);
}
*format = fmt->format;
@@ -976,10 +989,11 @@ static const struct media_entity_operati
static int imx290_subdev_init(struct imx290 *imx290)
{
struct i2c_client *client = to_i2c_client(imx290->dev);
+ const struct v4l2_mbus_framefmt *format;
+ struct v4l2_subdev_state *state;
int ret;
imx290->current_mode = &imx290_modes_ptr(imx290)[0];
- imx290->bpp = imx290_formats[0].bpp;
v4l2_i2c_subdev_init(&imx290->sd, client, &imx290_subdev_ops);
imx290->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -1008,7 +1022,10 @@ static int imx290_subdev_init(struct imx
goto err_ctrls;
}
- imx290_ctrl_update(imx290, imx290->current_mode);
+ state = v4l2_subdev_lock_and_get_active_state(&imx290->sd);
+ format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
+ imx290_ctrl_update(imx290, format, imx290->current_mode);
+ v4l2_subdev_unlock_state(state);
return 0;
|