@@ -46,27 +46,12 @@ 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-
49+ /* Wrapper over the struct video_imager_data that extends it with other fields */
6350struct 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 )];
7055};
7156
7257/* All the I2C registers sent on various scenario */
@@ -108,47 +93,50 @@ static const struct video_reg emul_imager_60fps[] = {
10893};
10994
11095/* 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 [] = {
11297 {.fps = 15 , .regs = {emul_imager_320x240 , emul_imager_rgb565 , emul_imager_15fps }},
11398 {.fps = 30 , .regs = {emul_imager_320x240 , emul_imager_rgb565 , emul_imager_30fps }},
11499 {.fps = 60 , .regs = {emul_imager_320x240 , emul_imager_rgb565 , emul_imager_60fps }},
115100 {0 },
116101};
117- struct emul_imager_mode emul_imager_yuyv_320x240_modes [] = {
102+ static struct video_imager_mode emul_imager_yuyv_320x240_modes [] = {
118103 {.fps = 15 , .regs = {emul_imager_320x240 , emul_imager_yuyv , emul_imager_15fps }},
119104 {.fps = 30 , .regs = {emul_imager_320x240 , emul_imager_yuyv , emul_imager_30fps }},
120105 {0 },
121106};
122107
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 [] = {
125109 [RGB565_320x240 ] = emul_imager_rgb565_320x240_modes ,
126110 [YUYV_320x240 ] = emul_imager_yuyv_320x240_modes ,
127111};
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 ),
146115 {0 },
147116};
148117
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+
149137static int emul_imager_set_ctrl (const struct device * dev , unsigned int cid , void * value )
150138{
151- const struct emul_imager_config * cfg = dev -> config ;
139+ const struct video_imager_config * cfg = dev -> config ;
152140
153141 switch (cid ) {
154142 case EMUL_IMAGER_CID_CUSTOM :
@@ -160,7 +148,7 @@ static int emul_imager_set_ctrl(const struct device *dev, unsigned int cid, void
160148
161149static int emul_imager_get_ctrl (const struct device * dev , unsigned int cid , void * value )
162150{
163- const struct emul_imager_config * cfg = dev -> config ;
151+ const struct video_imager_config * cfg = dev -> config ;
164152 uint32_t reg = 0 ;
165153 int ret ;
166154
@@ -176,178 +164,30 @@ static int emul_imager_get_ctrl(const struct device *dev, unsigned int cid, void
176164 return ret ;
177165}
178166
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-
328167static int emul_imager_set_stream (const struct device * dev , bool enable )
329168{
330- const struct emul_imager_config * cfg = dev -> config ;
169+ const struct video_imager_config * cfg = dev -> config ;
331170
332171 return video_write_cci_reg (& cfg -> i2c , EMUL_IMAGER_REG_CTRL , enable ? 1 : 0 );
333172}
334173
335174static DEVICE_API (video , emul_imager_driver_api ) = {
175+ /* Local implementation */
336176 .set_ctrl = emul_imager_set_ctrl ,
337177 .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 ,
344178 .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 ,
345186};
346187
347188int emul_imager_init (const struct device * dev )
348189{
349- const struct emul_imager_config * cfg = dev -> config ;
350- struct video_format fmt ;
190+ const struct video_imager_config * cfg = dev -> config ;
351191 uint32_t sensor_id ;
352192 int ret ;
353193
@@ -358,43 +198,42 @@ int emul_imager_init(const struct device *dev)
358198
359199 ret = video_read_cci_reg (& cfg -> i2c , EMUL_IMAGER_REG_SENSOR_ID , & sensor_id );
360200 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 );
368202 return ret ;
369203 }
370204
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 );
383206}
384207
385208#define EMUL_IMAGER_DEFINE (inst ) \
386209 static struct emul_imager_data emul_imager_data_##inst; \
387210 \
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 = { \
389214 .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, \
390219 }; \
391220 \
392221 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, \
394223 &emul_imager_driver_api);
395224
396225DT_INST_FOREACH_STATUS_OKAY (EMUL_IMAGER_DEFINE )
397226
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+
398237/* Simulated I2C bus */
399238
400239static int emul_imager_transfer_i2c (const struct emul * target , struct i2c_msg msgs [], int num_msgs ,
0 commit comments