@@ -343,3 +343,197 @@ int video_write_cci_multi(const struct i2c_dt_spec *i2c, const struct video_reg
343
343
344
344
return 0 ;
345
345
}
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