Skip to content

Commit e52c4c5

Browse files
committed
drivers: video: emul_imager: use the shared imager implementation
Make the emulated imager use the shared implementation of all imagers, making shared implementation of the image sensor drivers be tested by CI. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent 4000eb6 commit e52c4c5

File tree

1 file changed

+27
-220
lines changed

1 file changed

+27
-220
lines changed

drivers/video/video_emul_imager.c

Lines changed: 27 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,9 @@ enum emul_imager_fmt_id {
4646
YUYV_320x240,
4747
};
4848

49-
struct emul_imager_mode {
50-
uint8_t fps;
51-
/* List of registers lists to configure the various properties of the sensor.
52-
* This permits to deduplicate the list of registers in case some lare sections
53-
* are repeated across modes, such as the resolution for different FPS.
54-
*/
55-
const struct video_reg *regs[3];
56-
/* More fields can be added according to the needs of the sensor driver */
57-
};
58-
59-
struct emul_imager_config {
60-
struct i2c_dt_spec i2c;
61-
};
62-
6349
struct emul_imager_data {
6450
/* First field is a line buffer for I/O emulation purpose */
6551
uint8_t framebuffer[320 * sizeof(uint16_t)];
66-
/* Other fields are shared with real hardware drivers */
67-
const struct emul_imager_mode *mode;
68-
enum emul_imager_fmt_id fmt_id;
69-
struct video_format fmt;
7052
};
7153

7254
/* All the I2C registers sent on various scenario */
@@ -108,47 +90,31 @@ static const struct video_reg emul_imager_60fps[] = {
10890
};
10991

11092
/* Description of "modes", that pick lists of registesr that will be all sentto the imager */
111-
struct emul_imager_mode emul_imager_rgb565_320x240_modes[] = {
93+
static struct video_imager_mode emul_imager_rgb565_320x240_modes[] = {
11294
{.fps = 15, .regs = {emul_imager_320x240, emul_imager_rgb565, emul_imager_15fps}},
11395
{.fps = 30, .regs = {emul_imager_320x240, emul_imager_rgb565, emul_imager_30fps}},
11496
{.fps = 60, .regs = {emul_imager_320x240, emul_imager_rgb565, emul_imager_60fps}},
11597
{0},
11698
};
117-
struct emul_imager_mode emul_imager_yuyv_320x240_modes[] = {
99+
static struct video_imager_mode emul_imager_yuyv_320x240_modes[] = {
118100
{.fps = 15, .regs = {emul_imager_320x240, emul_imager_yuyv, emul_imager_15fps}},
119101
{.fps = 30, .regs = {emul_imager_320x240, emul_imager_yuyv, emul_imager_30fps}},
120102
{0},
121103
};
122104

123-
/* Summary of all the modes of all the frame formats, with indexes matching those of fmts[]. */
124-
static const struct emul_imager_mode *emul_imager_modes[] = {
105+
static const struct video_imager_mode *emul_imager_modes[] = {
125106
[RGB565_320x240] = emul_imager_rgb565_320x240_modes,
126107
[YUYV_320x240] = emul_imager_yuyv_320x240_modes,
127108
};
128-
129-
/* Video device capabilities where the supported resolutions and pixel formats are listed.
130-
* The format ID is used as index to fetch the matching mode from the list above.
131-
*/
132-
#define EMUL_IMAGER_VIDEO_FORMAT_CAP(format, width, height) \
133-
{ \
134-
/* For a real imager, the width and height would be macro parameters */ \
135-
.pixelformat = (format), \
136-
.width_min = (width), \
137-
.width_max = (width), \
138-
.width_step = 0, \
139-
.height_min = (height), \
140-
.height_max = (height), \
141-
.height_step = 0, \
142-
}
143-
static const struct video_format_cap fmts[] = {
144-
[RGB565_320x240] = EMUL_IMAGER_VIDEO_FORMAT_CAP(VIDEO_PIX_FMT_RGB565, 320, 240),
145-
[YUYV_320x240] = EMUL_IMAGER_VIDEO_FORMAT_CAP(VIDEO_PIX_FMT_YUYV, 320, 240),
109+
static const struct video_format_cap emul_imager_fmts[] = {
110+
[RGB565_320x240] = VIDEO_IMAGER_FORMAT_CAP(VIDEO_PIX_FMT_RGB565, 320, 240),
111+
[YUYV_320x240] = VIDEO_IMAGER_FORMAT_CAP(VIDEO_PIX_FMT_YUYV, 320, 240),
146112
{0},
147113
};
148114

149115
static int emul_imager_set_ctrl(const struct device *dev, unsigned int cid, void *value)
150116
{
151-
const struct emul_imager_config *cfg = dev->config;
117+
const struct video_imager_config *cfg = dev->config;
152118

153119
switch (cid) {
154120
case EMUL_IMAGER_CID_CUSTOM:
@@ -160,7 +126,7 @@ static int emul_imager_set_ctrl(const struct device *dev, unsigned int cid, void
160126

161127
static int emul_imager_get_ctrl(const struct device *dev, unsigned int cid, void *value)
162128
{
163-
const struct emul_imager_config *cfg = dev->config;
129+
const struct video_imager_config *cfg = dev->config;
164130
uint32_t reg = 0;
165131
int ret;
166132

@@ -176,178 +142,30 @@ static int emul_imager_get_ctrl(const struct device *dev, unsigned int cid, void
176142
return ret;
177143
}
178144

179-
/* Customize this function according to your "struct emul_imager_mode". */
180-
static int emul_imager_set_mode(const struct device *dev, const struct emul_imager_mode *mode)
181-
{
182-
const struct emul_imager_config *cfg = dev->config;
183-
struct emul_imager_data *data = dev->data;
184-
int ret;
185-
186-
if (data->mode == mode) {
187-
return 0;
188-
}
189-
190-
LOG_DBG("Applying mode %p at %d FPS", mode, mode->fps);
191-
192-
/* Apply all the configuration registers for that mode */
193-
for (int i = 0; i < 2; i++) {
194-
ret = video_write_cci_multi(&cfg->i2c, mode->regs[i]);
195-
if (ret < 0) {
196-
goto err;
197-
}
198-
}
199-
200-
data->mode = mode;
201-
return 0;
202-
err:
203-
LOG_ERR("Could not apply mode %p (%u FPS)", mode, mode->fps);
204-
return ret;
205-
}
206-
207-
static int emul_imager_set_frmival(const struct device *dev, enum video_endpoint_id ep,
208-
struct video_frmival *frmival)
209-
{
210-
struct emul_imager_data *data = dev->data;
211-
struct video_frmival_enum fie = {.format = &data->fmt, .discrete = *frmival};
212-
213-
if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
214-
return -EINVAL;
215-
}
216-
217-
video_closest_frmival(dev, ep, &fie);
218-
LOG_DBG("Applying frame interval number %u", fie.index);
219-
return emul_imager_set_mode(dev, &emul_imager_modes[data->fmt_id][fie.index]);
220-
}
221-
222-
static int emul_imager_get_frmival(const struct device *dev, enum video_endpoint_id ep,
223-
struct video_frmival *frmival)
224-
{
225-
struct emul_imager_data *data = dev->data;
226-
227-
if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
228-
return -EINVAL;
229-
}
230-
231-
frmival->numerator = 1;
232-
frmival->denominator = data->mode->fps;
233-
return 0;
234-
}
235-
236-
static int emul_imager_enum_frmival(const struct device *dev, enum video_endpoint_id ep,
237-
struct video_frmival_enum *fie)
238-
{
239-
const struct emul_imager_mode *mode;
240-
size_t fmt_id;
241-
int ret;
242-
243-
if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
244-
return -EINVAL;
245-
}
246-
247-
ret = video_format_caps_index(fmts, fie->format, &fmt_id);
248-
if (ret < 0) {
249-
return ret;
250-
}
251-
252-
mode = &emul_imager_modes[fmt_id][fie->index];
253-
254-
fie->type = VIDEO_FRMIVAL_TYPE_DISCRETE;
255-
fie->discrete.numerator = 1;
256-
fie->discrete.denominator = mode->fps;
257-
fie->index++;
258-
259-
return mode->fps == 0;
260-
}
261-
262-
static int emul_imager_set_fmt(const struct device *const dev, enum video_endpoint_id ep,
263-
struct video_format *fmt)
264-
{
265-
struct emul_imager_data *data = dev->data;
266-
size_t fmt_id;
267-
int ret;
268-
269-
if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
270-
return -EINVAL;
271-
}
272-
273-
if (memcmp(&data->fmt, fmt, sizeof(data->fmt)) == 0) {
274-
return 0;
275-
}
276-
277-
ret = video_format_caps_index(fmts, fmt, &fmt_id);
278-
if (ret < 0) {
279-
LOG_ERR("Format %x %ux%u not found", fmt->pixelformat, fmt->width, fmt->height);
280-
return ret;
281-
}
282-
283-
ret = emul_imager_set_mode(dev, &emul_imager_modes[fmt_id][0]);
284-
if (ret < 0) {
285-
return ret;
286-
}
287-
288-
/* For the purpose of simulation, fill the image line buffer with 50% gray, this data
289-
* will be collected by the video_emul_rx driver.
290-
*/
291-
if (fmt->pixelformat == VIDEO_PIX_FMT_RGB565) {
292-
for (int i = 0; i < fmt->width; i++) {
293-
((uint16_t *)data->framebuffer)[i] = sys_cpu_to_le16(0x7bef);
294-
}
295-
} else {
296-
memset(data->framebuffer, 0x7f, fmt->pitch);
297-
}
298-
299-
data->fmt_id = fmt_id;
300-
data->fmt = *fmt;
301-
return 0;
302-
}
303-
304-
static int emul_imager_get_fmt(const struct device *dev, enum video_endpoint_id ep,
305-
struct video_format *fmt)
306-
{
307-
struct emul_imager_data *data = dev->data;
308-
309-
if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
310-
return -EINVAL;
311-
}
312-
313-
*fmt = data->fmt;
314-
return 0;
315-
}
316-
317-
static int emul_imager_get_caps(const struct device *dev, enum video_endpoint_id ep,
318-
struct video_caps *caps)
319-
{
320-
if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL) {
321-
return -EINVAL;
322-
}
323-
324-
caps->format_caps = fmts;
325-
return 0;
326-
}
327-
328145
static int emul_imager_set_stream(const struct device *dev, bool enable)
329146
{
330-
const struct emul_imager_config *cfg = dev->config;
147+
const struct video_imager_config *cfg = dev->config;
331148

332149
return video_write_cci_reg(&cfg->i2c, EMUL_IMAGER_REG_CTRL, enable ? 1 : 0);
333150
}
334151

335152
static DEVICE_API(video, emul_imager_driver_api) = {
153+
/* Local implementation */
336154
.set_ctrl = emul_imager_set_ctrl,
337155
.get_ctrl = emul_imager_get_ctrl,
338-
.set_frmival = emul_imager_set_frmival,
339-
.get_frmival = emul_imager_get_frmival,
340-
.enum_frmival = emul_imager_enum_frmival,
341-
.set_format = emul_imager_set_fmt,
342-
.get_format = emul_imager_get_fmt,
343-
.get_caps = emul_imager_get_caps,
344156
.set_stream = emul_imager_set_stream,
157+
/* Default implementation */
158+
.set_frmival = video_imager_set_frmival,
159+
.get_frmival = video_imager_get_frmival,
160+
.enum_frmival = video_imager_enum_frmival,
161+
.set_format = video_imager_set_fmt,
162+
.get_format = video_imager_get_fmt,
163+
.get_caps = video_imager_get_caps,
345164
};
346165

347166
int emul_imager_init(const struct device *dev)
348167
{
349-
const struct emul_imager_config *cfg = dev->config;
350-
struct video_format fmt;
168+
const struct video_imager_config *cfg = dev->config;
351169
uint32_t sensor_id;
352170
int ret;
353171

@@ -362,35 +180,24 @@ int emul_imager_init(const struct device *dev)
362180
return ret;
363181
}
364182

365-
ret = video_write_cci_multi(&cfg->i2c, emul_imager_init_regs);
366-
if (ret < 0) {
367-
LOG_ERR("Could not set initial registers");
368-
return ret;
369-
}
370-
371-
fmt.pixelformat = fmts[0].pixelformat;
372-
fmt.width = fmts[0].width_min;
373-
fmt.height = fmts[0].height_min;
374-
fmt.pitch = fmt.width * 2;
375-
376-
ret = emul_imager_set_fmt(dev, VIDEO_EP_OUT, &fmt);
377-
if (ret < 0) {
378-
LOG_ERR("Failed to set to default format %x %ux%u",
379-
fmt.pixelformat, fmt.width, fmt.height);
380-
}
381-
382-
return 0;
183+
return video_imager_init(dev, emul_imager_init_regs, 0);
383184
}
384185

385186
#define EMUL_IMAGER_DEFINE(inst) \
386187
static struct emul_imager_data emul_imager_data_##inst; \
387188
\
388-
static const struct emul_imager_config emul_imager_cfg_##inst = { \
189+
static struct video_imager_data video_imager_data_##inst; \
190+
\
191+
static const struct video_imager_config video_imager_cfg_##inst = { \
389192
.i2c = I2C_DT_SPEC_INST_GET(inst), \
193+
.modes = emul_imager_modes, \
194+
.fmts = emul_imager_fmts, \
195+
.data = &video_imager_data_##inst, \
196+
.write_multi = video_write_cci_multi, \
390197
}; \
391198
\
392199
DEVICE_DT_INST_DEFINE(inst, &emul_imager_init, NULL, &emul_imager_data_##inst, \
393-
&emul_imager_cfg_##inst, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
200+
&video_imager_cfg_##inst, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
394201
&emul_imager_driver_api);
395202

396203
DT_INST_FOREACH_STATUS_OKAY(EMUL_IMAGER_DEFINE)

0 commit comments

Comments
 (0)