@@ -343,3 +343,197 @@ int video_write_cci_multi(const struct i2c_dt_spec *i2c, const struct video_reg
343343
344344 return 0 ;
345345}
346+ /* Common implementation for imagers (a.k.a. image sensor) drivers */
347+
348+ int video_imager_set_mode (const struct device * dev , const struct video_imager_mode * mode )
349+ {
350+ const struct video_imager_config * cfg = dev -> config ;
351+ struct video_imager_data * data = cfg -> data ;
352+ int ret ;
353+
354+ if (data -> mode == mode ) {
355+ LOG_DBG ("%s is arlready in the mode requested" , dev -> name );
356+ return 0 ;
357+ }
358+
359+ /* Write each register table to the device */
360+ for (int i = 0 ; i < ARRAY_SIZE (mode -> regs ) && mode -> regs [i ] != NULL ; i ++ ) {
361+ ret = cfg -> write_multi (& cfg -> i2c , mode -> regs [i ]);
362+ if (ret != 0 ) {
363+ LOG_ERR ("Could not set %s to mode %p, %u FPS" , dev -> name , mode , mode -> fps );
364+ return ret ;
365+ }
366+ }
367+
368+ data -> mode = mode ;
369+
370+ return 0 ;
371+ }
372+
373+ int video_imager_set_frmival (const struct device * dev , enum video_endpoint_id ep ,
374+ struct video_frmival * frmival )
375+ {
376+ const struct video_imager_config * cfg = dev -> config ;
377+ struct video_imager_data * data = cfg -> data ;
378+ struct video_frmival_enum fie = {.format = & data -> fmt , .discrete = * frmival };
379+
380+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
381+ return - EINVAL ;
382+ }
383+
384+ video_closest_frmival (dev , ep , & fie );
385+
386+ return video_imager_set_mode (dev , & cfg -> modes [data -> fmt_id ][fie .index ]);
387+ }
388+
389+ int video_imager_get_frmival (const struct device * dev , enum video_endpoint_id ep ,
390+ struct video_frmival * frmival )
391+ {
392+ const struct video_imager_config * cfg = dev -> config ;
393+ struct video_imager_data * data = cfg -> data ;
394+
395+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
396+ return - EINVAL ;
397+ }
398+
399+ frmival -> numerator = 1 ;
400+ frmival -> denominator = data -> mode -> fps ;
401+
402+ return 0 ;
403+ }
404+
405+ int video_imager_enum_frmival (const struct device * dev , enum video_endpoint_id ep ,
406+ struct video_frmival_enum * fie )
407+ {
408+ const struct video_imager_config * cfg = dev -> config ;
409+ const struct video_imager_mode * modes ;
410+ size_t fmt_id = 0 ;
411+ int ret ;
412+
413+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
414+ return - EINVAL ;
415+ }
416+
417+ ret = video_format_caps_index (cfg -> fmts , fie -> format , & fmt_id );
418+ if (ret != 0 ) {
419+ LOG_ERR ("Format '%s' %ux%u not found for %s" ,
420+ VIDEO_FOURCC_TO_STR (fie -> format -> pixelformat ),
421+ fie -> format -> width , fie -> format -> height , dev -> name );
422+ return ret ;
423+ }
424+
425+ modes = cfg -> modes [fmt_id ];
426+
427+ for (int i = 0 ;; i ++ ) {
428+ if (modes [i ].fps == 0 ) {
429+ return - EINVAL ;
430+ }
431+
432+ if (i == fie -> index ) {
433+ fie -> type = VIDEO_FRMIVAL_TYPE_DISCRETE ;
434+ fie -> discrete .numerator = 1 ;
435+ fie -> discrete .denominator = modes [i ].fps ;
436+ break ;
437+ }
438+ }
439+
440+ return 0 ;
441+ }
442+
443+ int video_imager_set_fmt (const struct device * const dev , enum video_endpoint_id ep ,
444+ struct video_format * fmt )
445+ {
446+ const struct video_imager_config * cfg = dev -> config ;
447+ struct video_imager_data * data = cfg -> data ;
448+ size_t fmt_id ;
449+ int ret ;
450+
451+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
452+ LOG_ERR ("Only the output endpoint is supported for %s" , dev -> name );
453+ return - EINVAL ;
454+ }
455+
456+ ret = video_format_caps_index (cfg -> fmts , fmt , & fmt_id );
457+ if (ret != 0 ) {
458+ LOG_ERR ("Format '%s' %ux%u not found for device %s" ,
459+ VIDEO_FOURCC_TO_STR (fmt -> pixelformat ), fmt -> width , fmt -> height , dev -> name );
460+ return ret ;
461+ }
462+
463+ ret = video_imager_set_mode (dev , & cfg -> modes [fmt_id ][0 ]);
464+ if (ret != 0 ) {
465+ return ret ;
466+ }
467+
468+ data -> fmt_id = fmt_id ;
469+ data -> fmt = * fmt ;
470+
471+ return 0 ;
472+ }
473+
474+ int video_imager_get_fmt (const struct device * dev , enum video_endpoint_id ep ,
475+ struct video_format * fmt )
476+ {
477+ const struct video_imager_config * cfg = dev -> config ;
478+ struct video_imager_data * data = cfg -> data ;
479+
480+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
481+ return - EINVAL ;
482+ }
483+
484+ * fmt = data -> fmt ;
485+
486+ return 0 ;
487+ }
488+
489+ int video_imager_get_caps (const struct device * dev , enum video_endpoint_id ep ,
490+ struct video_caps * caps )
491+ {
492+ const struct video_imager_config * cfg = dev -> config ;
493+
494+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
495+ return - EINVAL ;
496+ }
497+
498+ caps -> format_caps = cfg -> fmts ;
499+
500+ return 0 ;
501+ }
502+
503+ int video_imager_init (const struct device * dev , const struct video_reg * init_regs ,
504+ int default_fmt_idx )
505+ {
506+ const struct video_imager_config * cfg = dev -> config ;
507+ struct video_format fmt ;
508+ int ret ;
509+
510+ __ASSERT_NO_MSG (cfg -> modes != NULL );
511+ __ASSERT_NO_MSG (cfg -> fmts != NULL );
512+
513+ if (!device_is_ready (cfg -> i2c .bus )) {
514+ LOG_ERR ("I2C bus device %s is not ready" , cfg -> i2c .bus -> name );
515+ return - ENODEV ;
516+ }
517+
518+ if (init_regs != NULL ) {
519+ ret = cfg -> write_multi (& cfg -> i2c , init_regs );
520+ if (ret != 0 ) {
521+ LOG_ERR ("Could not set %s initial registers" , dev -> name );
522+ return ret ;
523+ }
524+ }
525+
526+ fmt .pixelformat = cfg -> fmts [default_fmt_idx ].pixelformat ;
527+ fmt .width = cfg -> fmts [default_fmt_idx ].width_max ;
528+ fmt .height = cfg -> fmts [default_fmt_idx ].height_max ;
529+ fmt .pitch = fmt .width * video_bits_per_pixel (fmt .pixelformat ) / BITS_PER_BYTE ;
530+
531+ ret = video_set_format (dev , VIDEO_EP_OUT , & fmt );
532+ if (ret != 0 ) {
533+ LOG_ERR ("Failed to set %s to default format '%s' %ux%u" ,
534+ dev -> name , VIDEO_FOURCC_TO_STR (fmt .pixelformat ), fmt .width , fmt .height );
535+ return ret ;
536+ }
537+
538+ return 0 ;
539+ }
0 commit comments