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