@@ -41,6 +41,7 @@ struct video_stm32_dcmi_data {
41
41
const struct device * dev ;
42
42
DCMI_HandleTypeDef hdcmi ;
43
43
struct video_format fmt ;
44
+ int capture_rate ;
44
45
struct k_fifo fifo_in ;
45
46
struct k_fifo fifo_out ;
46
47
struct video_buffer * vbuf ;
@@ -251,6 +252,12 @@ static int video_stm32_dcmi_get_fmt(const struct device *dev,
251
252
return 0 ;
252
253
}
253
254
255
+ #define STM32_DCMI_GET_CAPTURE_RATE (capture_rate ) \
256
+ ((capture_rate) == 1 ? DCMI_CR_ALL_FRAME : \
257
+ (capture_rate) == 2 ? DCMI_CR_ALTERNATE_2_FRAME : \
258
+ (capture_rate) == 4 ? DCMI_CR_ALTERNATE_4_FRAME : \
259
+ DCMI_CR_ALL_FRAME)
260
+
254
261
static int video_stm32_dcmi_set_stream (const struct device * dev , bool enable )
255
262
{
256
263
struct video_stm32_dcmi_data * data = dev -> data ;
@@ -282,6 +289,10 @@ static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable)
282
289
return - ENOMEM ;
283
290
}
284
291
292
+ /* Set the frame control */
293
+ data -> hdcmi .Instance -> CR &= ~(DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 );
294
+ data -> hdcmi .Instance -> CR |= STM32_DCMI_GET_CAPTURE_RATE (data -> capture_rate );
295
+
285
296
err = HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
286
297
(uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused / 4 );
287
298
if (err != HAL_OK ) {
@@ -351,13 +362,129 @@ static int video_stm32_dcmi_get_caps(const struct device *dev,
351
362
return video_get_caps (config -> sensor_dev , ep , caps );
352
363
}
353
364
365
+ static int video_stm32_dcmi_enum_frmival (const struct device * dev , enum video_endpoint_id ep ,
366
+ struct video_frmival_enum * fie )
367
+ {
368
+ const struct video_stm32_dcmi_config * config = dev -> config ;
369
+ int ret ;
370
+
371
+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
372
+ return - EINVAL ;
373
+ }
374
+
375
+ ret = video_stm32_dcmi_is_fmt_valid (fie -> format -> pixelformat , fie -> format -> pitch ,
376
+ fie -> format -> height );
377
+ if (ret < 0 ) {
378
+ return ret ;
379
+ }
380
+
381
+ ret = video_enum_frmival (config -> sensor_dev , ep , fie );
382
+ if (ret < 0 ) {
383
+ return ret ;
384
+ }
385
+
386
+ /* Adapt the interval in order to report the frame drop capabilities */
387
+ if (fie -> type == VIDEO_FRMIVAL_TYPE_DISCRETE ) {
388
+ struct video_frmival discrete = fie -> discrete ;
389
+
390
+ fie -> type = VIDEO_FRMIVAL_TYPE_STEPWISE ;
391
+ fie -> stepwise .max = discrete ;
392
+ fie -> stepwise .min .denominator = discrete .denominator ;
393
+ fie -> stepwise .min .numerator = discrete .numerator * 4 ;
394
+ fie -> stepwise .step .denominator = discrete .denominator ;
395
+ fie -> stepwise .step .numerator = discrete .numerator * 2 ;
396
+ } else {
397
+ fie -> stepwise .min .numerator *= 4 ;
398
+ fie -> stepwise .step .numerator *= 2 ;
399
+ }
400
+
401
+ return 0 ;
402
+ }
403
+
404
+ #define STM32_DCMI_MAX_FRAME_DROP 4
405
+ static int video_stm32_dcmi_set_frmival (const struct device * dev , enum video_endpoint_id ep ,
406
+ struct video_frmival * frmival )
407
+ {
408
+ const struct video_stm32_dcmi_config * config = dev -> config ;
409
+ struct video_stm32_dcmi_data * data = dev -> data ;
410
+ struct video_frmival_enum fie = {
411
+ .format = & data -> fmt ,
412
+ };
413
+ struct video_frmival best_sensor_frmival ;
414
+ uint64_t best_diff_nsec = INT32_MAX ;
415
+ uint64_t diff_nsec = 0 , a , b ;
416
+ int best_capture_rate = 1 ;
417
+
418
+ if (ep != VIDEO_EP_OUT && ep != VIDEO_EP_ALL ) {
419
+ return - EINVAL ;
420
+ }
421
+
422
+ /*
423
+ * Try to figure out a frameinterval setting allow to reach as close as
424
+ * possible to the request. At first without relying on DCMI frame control,
425
+ * then enabling it
426
+ */
427
+ for (int capture_rate = 1 ; capture_rate <= STM32_DCMI_MAX_FRAME_DROP ; capture_rate *= 2 ) {
428
+ /*
429
+ * Take into consideration the drop done by the DCMI hence multiply
430
+ * denominator by the rate introduced by the DCMI
431
+ */
432
+ fie .discrete .numerator = frmival -> numerator ;
433
+ fie .discrete .denominator = frmival -> denominator * capture_rate ;
434
+
435
+ a = video_frmival_nsec (& fie .discrete );
436
+ video_closest_frmival (config -> sensor_dev , ep , & fie );
437
+ b = video_frmival_nsec (& fie .discrete );
438
+ diff_nsec = a > b ? a - b : b - a ;
439
+ if (diff_nsec < best_diff_nsec ) {
440
+ best_diff_nsec = diff_nsec ;
441
+ best_sensor_frmival = fie .discrete ;
442
+ best_capture_rate = capture_rate ;
443
+ }
444
+ if (diff_nsec == 0 ) {
445
+ break ;
446
+ }
447
+ }
448
+
449
+ /*
450
+ * Give back the achieved frame interval achieved, ensuring to take into
451
+ * consideration the DCMI frame control
452
+ */
453
+ frmival -> numerator = best_sensor_frmival .numerator * best_capture_rate ;
454
+ frmival -> denominator = best_sensor_frmival .denominator ;
455
+
456
+ data -> capture_rate = best_capture_rate ;
457
+
458
+ return video_set_frmival (config -> sensor_dev , ep , & best_sensor_frmival );
459
+ }
460
+
461
+ static int video_stm32_dcmi_get_frmival (const struct device * dev , enum video_endpoint_id ep ,
462
+ struct video_frmival * frmival )
463
+ {
464
+ const struct video_stm32_dcmi_config * config = dev -> config ;
465
+ struct video_stm32_dcmi_data * data = dev -> data ;
466
+ int ret ;
467
+
468
+ ret = video_get_frmival (config -> sensor_dev , ep , frmival );
469
+ if (ret < 0 ) {
470
+ return ret ;
471
+ }
472
+
473
+ frmival -> numerator *= data -> capture_rate ;
474
+
475
+ return 0 ;
476
+ }
477
+
354
478
static DEVICE_API (video , video_stm32_dcmi_driver_api ) = {
355
479
.set_format = video_stm32_dcmi_set_fmt ,
356
480
.get_format = video_stm32_dcmi_get_fmt ,
357
481
.set_stream = video_stm32_dcmi_set_stream ,
358
482
.enqueue = video_stm32_dcmi_enqueue ,
359
483
.dequeue = video_stm32_dcmi_dequeue ,
360
484
.get_caps = video_stm32_dcmi_get_caps ,
485
+ .enum_frmival = video_stm32_dcmi_enum_frmival ,
486
+ .set_frmival = video_stm32_dcmi_set_frmival ,
487
+ .get_frmival = video_stm32_dcmi_get_frmival ,
361
488
};
362
489
363
490
static void video_stm32_dcmi_irq_config_func (const struct device * dev )
@@ -389,12 +516,6 @@ static void video_stm32_dcmi_irq_config_func(const struct device *dev)
389
516
390
517
PINCTRL_DT_INST_DEFINE (0 );
391
518
392
- #define STM32_DCMI_GET_CAPTURE_RATE (capture_rate ) \
393
- ((capture_rate) == 1 ? DCMI_CR_ALL_FRAME : \
394
- (capture_rate) == 2 ? DCMI_CR_ALTERNATE_2_FRAME : \
395
- (capture_rate) == 4 ? DCMI_CR_ALTERNATE_4_FRAME : \
396
- DCMI_CR_ALL_FRAME)
397
-
398
519
#define STM32_DCMI_GET_BUS_WIDTH (bus_width ) \
399
520
((bus_width) == 8 ? DCMI_EXTEND_DATA_8B : \
400
521
(bus_width) == 10 ? DCMI_EXTEND_DATA_10B : \
@@ -424,9 +545,6 @@ static struct video_stm32_dcmi_data video_stm32_dcmi_data_0 = {
424
545
.VSPolarity = DT_PROP_OR (DT_INST_ENDPOINT_BY_ID (n , 0 , 0 ),
425
546
vsync_active , 0 ) ?
426
547
DCMI_VSPOLARITY_HIGH : DCMI_VSPOLARITY_LOW ,
427
- .CaptureRate = STM32_DCMI_GET_CAPTURE_RATE (
428
- DT_PROP_OR (DT_DRV_INST (inst ), capture_rate ,
429
- 1 )),
430
548
.ExtendedDataMode = STM32_DCMI_GET_BUS_WIDTH (
431
549
DT_PROP_OR (DT_INST_ENDPOINT_BY_ID (n , 0 , 0 ),
432
550
bus_width , 8 )),
@@ -482,6 +600,7 @@ static int video_stm32_dcmi_init(const struct device *dev)
482
600
data -> dev = dev ;
483
601
k_fifo_init (& data -> fifo_in );
484
602
k_fifo_init (& data -> fifo_out );
603
+ data -> capture_rate = 1 ;
485
604
486
605
/* Run IRQ init */
487
606
config -> irq_config (dev );
0 commit comments