@@ -46,27 +46,12 @@ enum emul_imager_fmt_id {
46
46
YUYV_320x240 ,
47
47
};
48
48
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
-
49
+ /* Wrapper over the struct video_imager_data that extends it with other fields */
63
50
struct emul_imager_data {
64
- /* First field is a line buffer for I/O emulation purpose */
65
- 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 ;
51
+ /* The first field is the default data used by all image sensors */
52
+ struct video_imager_data imager ;
53
+ /* A line buffer for I/O emulation purpose */
54
+ uint8_t linebuffer [320 * sizeof (uint16_t )];
70
55
};
71
56
72
57
/* All the I2C registers sent on various scenario */
@@ -108,47 +93,50 @@ static const struct video_reg emul_imager_60fps[] = {
108
93
};
109
94
110
95
/* 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 [] = {
96
+ static struct video_imager_mode emul_imager_rgb565_320x240_modes [] = {
112
97
{.fps = 15 , .regs = {emul_imager_320x240 , emul_imager_rgb565 , emul_imager_15fps }},
113
98
{.fps = 30 , .regs = {emul_imager_320x240 , emul_imager_rgb565 , emul_imager_30fps }},
114
99
{.fps = 60 , .regs = {emul_imager_320x240 , emul_imager_rgb565 , emul_imager_60fps }},
115
100
{0 },
116
101
};
117
- struct emul_imager_mode emul_imager_yuyv_320x240_modes [] = {
102
+ static struct video_imager_mode emul_imager_yuyv_320x240_modes [] = {
118
103
{.fps = 15 , .regs = {emul_imager_320x240 , emul_imager_yuyv , emul_imager_15fps }},
119
104
{.fps = 30 , .regs = {emul_imager_320x240 , emul_imager_yuyv , emul_imager_30fps }},
120
105
{0 },
121
106
};
122
107
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 [] = {
108
+ static const struct video_imager_mode * emul_imager_modes [] = {
125
109
[RGB565_320x240 ] = emul_imager_rgb565_320x240_modes ,
126
110
[YUYV_320x240 ] = emul_imager_yuyv_320x240_modes ,
127
111
};
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 ),
112
+ static const struct video_format_cap emul_imager_fmts [] = {
113
+ [RGB565_320x240 ] = VIDEO_IMAGER_FORMAT_CAP (VIDEO_PIX_FMT_RGB565 , 320 , 240 ),
114
+ [YUYV_320x240 ] = VIDEO_IMAGER_FORMAT_CAP (VIDEO_PIX_FMT_YUYV , 320 , 240 ),
146
115
{0 },
147
116
};
148
117
118
+ static int emul_imager_set_fmt (const struct device * const dev , enum video_endpoint_id ep ,
119
+ struct video_format * fmt )
120
+ {
121
+ struct emul_imager_data * data = dev -> data ;
122
+
123
+ /* For the purpose of simulation, fill the image line buffer with 50% gray, this data
124
+ * will be collected by the video_emul_rx driver.
125
+ */
126
+ if (fmt -> pixelformat == VIDEO_PIX_FMT_RGB565 ) {
127
+ for (int i = 0 ; i < sizeof (data -> linebuffer ) / sizeof (uint16_t ); i ++ ) {
128
+ ((uint16_t * )data -> linebuffer )[i ] = sys_cpu_to_le16 (0x7bef );
129
+ }
130
+ } else {
131
+ memset (data -> linebuffer , 0x7f , sizeof (data -> linebuffer ));
132
+ }
133
+
134
+ return video_imager_set_fmt (dev , ep , fmt );
135
+ }
136
+
149
137
static int emul_imager_set_ctrl (const struct device * dev , unsigned int cid , void * value )
150
138
{
151
- const struct emul_imager_config * cfg = dev -> config ;
139
+ const struct video_imager_config * cfg = dev -> config ;
152
140
153
141
switch (cid ) {
154
142
case EMUL_IMAGER_CID_CUSTOM :
@@ -160,7 +148,7 @@ static int emul_imager_set_ctrl(const struct device *dev, unsigned int cid, void
160
148
161
149
static int emul_imager_get_ctrl (const struct device * dev , unsigned int cid , void * value )
162
150
{
163
- const struct emul_imager_config * cfg = dev -> config ;
151
+ const struct video_imager_config * cfg = dev -> config ;
164
152
uint32_t reg = 0 ;
165
153
int ret ;
166
154
@@ -176,178 +164,30 @@ static int emul_imager_get_ctrl(const struct device *dev, unsigned int cid, void
176
164
return ret ;
177
165
}
178
166
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
-
328
167
static int emul_imager_set_stream (const struct device * dev , bool enable )
329
168
{
330
- const struct emul_imager_config * cfg = dev -> config ;
169
+ const struct video_imager_config * cfg = dev -> config ;
331
170
332
171
return video_write_cci_reg (& cfg -> i2c , EMUL_IMAGER_REG_CTRL , enable ? 1 : 0 );
333
172
}
334
173
335
174
static DEVICE_API (video , emul_imager_driver_api ) = {
175
+ /* Local implementation */
336
176
.set_ctrl = emul_imager_set_ctrl ,
337
177
.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 ,
344
178
.set_stream = emul_imager_set_stream ,
179
+ .set_format = emul_imager_set_fmt ,
180
+ /* Default implementation */
181
+ .set_frmival = video_imager_set_frmival ,
182
+ .get_frmival = video_imager_get_frmival ,
183
+ .enum_frmival = video_imager_enum_frmival ,
184
+ .get_format = video_imager_get_fmt ,
185
+ .get_caps = video_imager_get_caps ,
345
186
};
346
187
347
188
int emul_imager_init (const struct device * dev )
348
189
{
349
- const struct emul_imager_config * cfg = dev -> config ;
350
- struct video_format fmt ;
190
+ const struct video_imager_config * cfg = dev -> config ;
351
191
uint32_t sensor_id ;
352
192
int ret ;
353
193
@@ -358,43 +198,42 @@ int emul_imager_init(const struct device *dev)
358
198
359
199
ret = video_read_cci_reg (& cfg -> i2c , EMUL_IMAGER_REG_SENSOR_ID , & sensor_id );
360
200
if (ret < 0 || sensor_id != EMUL_IMAGER_SENSOR_ID ) {
361
- LOG_ERR ("Failed to get a correct sensor ID 0x%x" , sensor_id );
362
- return ret ;
363
- }
364
-
365
- ret = video_write_cci_multi (& cfg -> i2c , emul_imager_init_regs );
366
- if (ret < 0 ) {
367
- LOG_ERR ("Could not set initial registers" );
201
+ LOG_ERR ("Failed to get a correct sensor ID 0x%x" , sensor_id );
368
202
return ret ;
369
203
}
370
204
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 ;
205
+ return video_imager_init (dev , emul_imager_init_regs , 0 );
383
206
}
384
207
385
208
#define EMUL_IMAGER_DEFINE (inst ) \
386
209
static struct emul_imager_data emul_imager_data_##inst; \
387
210
\
388
- static const struct emul_imager_config emul_imager_cfg_##inst = { \
211
+ static struct video_imager_data video_imager_data_##inst; \
212
+ \
213
+ static const struct video_imager_config video_imager_cfg_##inst = { \
389
214
.i2c = I2C_DT_SPEC_INST_GET(inst), \
215
+ .modes = emul_imager_modes, \
216
+ .fmts = emul_imager_fmts, \
217
+ .data = &video_imager_data_##inst, \
218
+ .write_multi = video_write_cci_multi, \
390
219
}; \
391
220
\
392
221
DEVICE_DT_INST_DEFINE(inst, &emul_imager_init, NULL, &emul_imager_data_##inst, \
393
- &emul_imager_cfg_ ##inst, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
222
+ &video_imager_cfg_ ##inst, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
394
223
&emul_imager_driver_api);
395
224
396
225
DT_INST_FOREACH_STATUS_OKAY (EMUL_IMAGER_DEFINE )
397
226
227
+ /* Simulated MIPI bus */
228
+
229
+ const uint8_t * video_emul_imager_get_linebuffer (const struct device * dev , size_t * pitch )
230
+ {
231
+ struct emul_imager_data * data = dev -> data ;
232
+
233
+ * pitch = sizeof (data -> linebuffer );
234
+ return data -> linebuffer ;
235
+ }
236
+
398
237
/* Simulated I2C bus */
399
238
400
239
static int emul_imager_transfer_i2c (const struct emul * target , struct i2c_msg msgs [], int num_msgs ,
0 commit comments