@@ -41,6 +41,7 @@ struct video_stm32_dcmi_data {
4141 const struct device * dev ;
4242 DCMI_HandleTypeDef hdcmi ;
4343 struct video_format fmt ;
44+ int capture_rate ;
4445 struct k_fifo fifo_in ;
4546 struct k_fifo fifo_out ;
4647 struct video_buffer * vbuf ;
@@ -251,6 +252,12 @@ static int video_stm32_dcmi_get_fmt(const struct device *dev,
251252 return 0 ;
252253}
253254
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+
254261static int video_stm32_dcmi_set_stream (const struct device * dev , bool enable )
255262{
256263 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)
282289 return - ENOMEM ;
283290 }
284291
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+
285296 err = HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
286297 (uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused / 4 );
287298 if (err != HAL_OK ) {
@@ -351,13 +362,129 @@ static int video_stm32_dcmi_get_caps(const struct device *dev,
351362 return video_get_caps (config -> sensor_dev , ep , caps );
352363}
353364
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+
354478static DEVICE_API (video , video_stm32_dcmi_driver_api ) = {
355479 .set_format = video_stm32_dcmi_set_fmt ,
356480 .get_format = video_stm32_dcmi_get_fmt ,
357481 .set_stream = video_stm32_dcmi_set_stream ,
358482 .enqueue = video_stm32_dcmi_enqueue ,
359483 .dequeue = video_stm32_dcmi_dequeue ,
360484 .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 ,
361488};
362489
363490static 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)
389516
390517PINCTRL_DT_INST_DEFINE (0 );
391518
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-
398519#define STM32_DCMI_GET_BUS_WIDTH (bus_width ) \
399520 ((bus_width) == 8 ? DCMI_EXTEND_DATA_8B : \
400521 (bus_width) == 10 ? DCMI_EXTEND_DATA_10B : \
@@ -424,9 +545,6 @@ static struct video_stm32_dcmi_data video_stm32_dcmi_data_0 = {
424545 .VSPolarity = DT_PROP_OR (DT_INST_ENDPOINT_BY_ID (n , 0 , 0 ),
425546 vsync_active , 0 ) ?
426547 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 )),
430548 .ExtendedDataMode = STM32_DCMI_GET_BUS_WIDTH (
431549 DT_PROP_OR (DT_INST_ENDPOINT_BY_ID (n , 0 , 0 ),
432550 bus_width , 8 )),
@@ -482,6 +600,7 @@ static int video_stm32_dcmi_init(const struct device *dev)
482600 data -> dev = dev ;
483601 k_fifo_init (& data -> fifo_in );
484602 k_fifo_init (& data -> fifo_out );
603+ data -> capture_rate = 1 ;
485604
486605 /* Run IRQ init */
487606 config -> irq_config (dev );
0 commit comments