@@ -301,3 +301,197 @@ int video_write_cci_multi(const struct i2c_dt_spec *i2c, const struct video_reg
301301
302302 return 0 ;
303303}
304+ /* Common implementation for imagers (a.k.a. image sensor) drivers */
305+
306+ int video_imager_set_mode (const struct device * dev , const struct video_imager_mode * mode )
307+ {
308+ const struct video_imager_config * cfg = dev -> config ;
309+ struct video_imager_data * data = cfg -> data ;
310+ int ret ;
311+
312+ if (data -> mode == mode ) {
313+ LOG_DBG ("%s is arlready in the mode requested" , dev -> name );
314+ return 0 ;
315+ }
316+
317+ /* Write each register table to the device */
318+ for (int i = 0 ; i < ARRAY_SIZE (mode -> regs ) && mode -> regs [i ] != NULL ; i ++ ) {
319+ ret = cfg -> write_multi (& cfg -> i2c , mode -> regs [i ]);
320+ if (ret != 0 ) {
321+ LOG_ERR ("Could not set %s to mode %p, %u FPS" , dev -> name , mode , mode -> fps );
322+ return ret ;
323+ }
324+ }
325+
326+ data -> mode = mode ;
327+
328+ return 0 ;
329+ }
330+
331+ int video_imager_set_frmival (const struct device * dev , enum video_endpoint_id ep ,
332+ struct video_frmival * frmival )
333+ {
334+ const struct video_imager_config * cfg = dev -> config ;
335+ struct video_imager_data * data = cfg -> data ;
336+ struct video_frmival_enum fie = {.format = & data -> fmt , .discrete = * frmival };
337+
338+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
339+ return - EINVAL ;
340+ }
341+
342+ video_closest_frmival (dev , ep , & fie );
343+
344+ return video_imager_set_mode (dev , & cfg -> modes [data -> fmt_id ][fie .index ]);
345+ }
346+
347+ int video_imager_get_frmival (const struct device * dev , enum video_endpoint_id ep ,
348+ struct video_frmival * frmival )
349+ {
350+ const struct video_imager_config * cfg = dev -> config ;
351+ struct video_imager_data * data = cfg -> data ;
352+
353+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
354+ return - EINVAL ;
355+ }
356+
357+ frmival -> numerator = 1 ;
358+ frmival -> denominator = data -> mode -> fps ;
359+
360+ return 0 ;
361+ }
362+
363+ int video_imager_enum_frmival (const struct device * dev , enum video_endpoint_id ep ,
364+ struct video_frmival_enum * fie )
365+ {
366+ const struct video_imager_config * cfg = dev -> config ;
367+ const struct video_imager_mode * modes ;
368+ size_t fmt_id = 0 ;
369+ int ret ;
370+
371+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
372+ return - EINVAL ;
373+ }
374+
375+ ret = video_format_caps_index (cfg -> fmts , fie -> format , & fmt_id );
376+ if (ret != 0 ) {
377+ LOG_ERR ("Format '%s' %ux%u not found for %s" ,
378+ VIDEO_FOURCC_TO_STR (fie -> format -> pixelformat ),
379+ fie -> format -> width , fie -> format -> height , dev -> name );
380+ return ret ;
381+ }
382+
383+ modes = cfg -> modes [fmt_id ];
384+
385+ for (int i = 0 ;; i ++ ) {
386+ if (modes [i ].fps == 0 ) {
387+ return - EINVAL ;
388+ }
389+
390+ if (i == fie -> index ) {
391+ fie -> type = VIDEO_FRMIVAL_TYPE_DISCRETE ;
392+ fie -> discrete .numerator = 1 ;
393+ fie -> discrete .denominator = modes [i ].fps ;
394+ break ;
395+ }
396+ }
397+
398+ return 0 ;
399+ }
400+
401+ int video_imager_set_fmt (const struct device * const dev , enum video_endpoint_id ep ,
402+ struct video_format * fmt )
403+ {
404+ const struct video_imager_config * cfg = dev -> config ;
405+ struct video_imager_data * data = cfg -> data ;
406+ size_t fmt_id ;
407+ int ret ;
408+
409+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
410+ LOG_ERR ("Only the output endpoint is supported for %s" , dev -> name );
411+ return - EINVAL ;
412+ }
413+
414+ ret = video_format_caps_index (cfg -> fmts , fmt , & fmt_id );
415+ if (ret != 0 ) {
416+ LOG_ERR ("Format '%s' %ux%u not found for device %s" ,
417+ VIDEO_FOURCC_TO_STR (fmt -> pixelformat ), fmt -> width , fmt -> height , dev -> name );
418+ return ret ;
419+ }
420+
421+ ret = video_imager_set_mode (dev , & cfg -> modes [fmt_id ][0 ]);
422+ if (ret != 0 ) {
423+ return ret ;
424+ }
425+
426+ data -> fmt_id = fmt_id ;
427+ data -> fmt = * fmt ;
428+
429+ return 0 ;
430+ }
431+
432+ int video_imager_get_fmt (const struct device * dev , enum video_endpoint_id ep ,
433+ struct video_format * fmt )
434+ {
435+ const struct video_imager_config * cfg = dev -> config ;
436+ struct video_imager_data * data = cfg -> data ;
437+
438+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
439+ return - EINVAL ;
440+ }
441+
442+ * fmt = data -> fmt ;
443+
444+ return 0 ;
445+ }
446+
447+ int video_imager_get_caps (const struct device * dev , enum video_endpoint_id ep ,
448+ struct video_caps * caps )
449+ {
450+ const struct video_imager_config * cfg = dev -> config ;
451+
452+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
453+ return - EINVAL ;
454+ }
455+
456+ caps -> format_caps = cfg -> fmts ;
457+
458+ return 0 ;
459+ }
460+
461+ int video_imager_init (const struct device * dev , const struct video_reg * init_regs ,
462+ int default_fmt_idx )
463+ {
464+ const struct video_imager_config * cfg = dev -> config ;
465+ struct video_format fmt ;
466+ int ret ;
467+
468+ __ASSERT_NO_MSG (cfg -> modes != NULL );
469+ __ASSERT_NO_MSG (cfg -> fmts != NULL );
470+
471+ if (!device_is_ready (cfg -> i2c .bus )) {
472+ LOG_ERR ("I2C bus device %s is not ready" , cfg -> i2c .bus -> name );
473+ return - ENODEV ;
474+ }
475+
476+ if (init_regs != NULL ) {
477+ ret = cfg -> write_multi (& cfg -> i2c , init_regs );
478+ if (ret != 0 ) {
479+ LOG_ERR ("Could not set %s initial registers" , dev -> name );
480+ return ret ;
481+ }
482+ }
483+
484+ fmt .pixelformat = cfg -> fmts [default_fmt_idx ].pixelformat ;
485+ fmt .width = cfg -> fmts [default_fmt_idx ].width_max ;
486+ fmt .height = cfg -> fmts [default_fmt_idx ].height_max ;
487+ fmt .pitch = fmt .width * video_bits_per_pixel (fmt .pixelformat ) / BITS_PER_BYTE ;
488+
489+ ret = video_set_format (dev , VIDEO_EP_OUT , & fmt );
490+ if (ret != 0 ) {
491+ LOG_ERR ("Failed to set %s to default format '%s' %ux%u" ,
492+ dev -> name , VIDEO_FOURCC_TO_STR (fmt .pixelformat ), fmt .width , fmt .height );
493+ return ret ;
494+ }
495+
496+ return 0 ;
497+ }
0 commit comments