1212#include  <zephyr/irq.h> 
1313#include  <zephyr/logging/log.h> 
1414#include  <zephyr/drivers/video.h> 
15+ #include  <zephyr/drivers/video-controls.h> 
1516#include  <zephyr/drivers/pinctrl.h> 
1617#include  <zephyr/drivers/clock_control/stm32_clock_control.h> 
1718#include  <zephyr/drivers/clock_control.h> 
2021
2122#include  <stm32_ll_dma.h> 
2223
24+ #include  "video_ctrls.h" 
2325#include  "video_device.h" 
2426
2527LOG_MODULE_REGISTER (video_stm32_dcmi , CONFIG_VIDEO_LOG_LEVEL );
2628
27- #if  CONFIG_VIDEO_BUFFER_POOL_NUM_MAX  <  2 
28- #error  "The minimum required number of buffers for video_stm32 is 2 "
29+ #if  CONFIG_VIDEO_BUFFER_POOL_NUM_MAX  <  1 
30+ #error  "The minimum required number of buffers for video_stm32 is 1 "
2931#endif 
3032
3133typedef  void  (* irq_config_func_t )(const  struct  device  * dev );
@@ -37,14 +39,22 @@ struct stream {
3739	struct  dma_config  cfg ;
3840};
3941
42+ 
43+ struct  video_stm32_dcmi_ctrls  {
44+ 	struct  video_ctrl  snapshot ;
45+ };
46+ 
4047struct  video_stm32_dcmi_data  {
4148	const  struct  device  * dev ;
4249	DCMI_HandleTypeDef  hdcmi ;
4350	struct  video_format  fmt ;
51+ 	struct  video_stm32_dcmi_ctrls  ctrls ;
4452	int  capture_rate ;
4553	struct  k_fifo  fifo_in ;
4654	struct  k_fifo  fifo_out ;
4755	struct  video_buffer  * vbuf ;
56+ 	uint32_t  snapshot_start_time ;
57+ 	bool  snapshot_mode ;
4858};
4959
5060struct  video_stm32_dcmi_config  {
@@ -53,6 +63,8 @@ struct video_stm32_dcmi_config {
5363	const  struct  pinctrl_dev_config  * pctrl ;
5464	const  struct  device  * sensor_dev ;
5565	const  struct  stream  dma ;
66+ 	bool  snapshot_mode ;
67+ 	int  snapshot_timeout ;
5668};
5769
5870static  void  stm32_dcmi_process_dma_error (DCMI_HandleTypeDef  * hdcmi )
@@ -69,7 +81,7 @@ static void stm32_dcmi_process_dma_error(DCMI_HandleTypeDef *hdcmi)
6981	}
7082
7183	if  (HAL_DCMI_Start_DMA (& dev_data -> hdcmi ,
72- 			       DCMI_MODE_CONTINUOUS ,
84+ 			       dev_data -> snapshot_mode  ?  DCMI_MODE_SNAPSHOT  :  DCMI_MODE_CONTINUOUS ,
7385			       (uint32_t )dev_data -> vbuf -> buffer ,
7486			       dev_data -> vbuf -> size  / 4 ) !=  HAL_OK ) {
7587		LOG_WRN ("Continuous: HAL_DCMI_Start_DMA FAILED!" );
@@ -89,6 +101,17 @@ void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
89101	struct  video_buffer  * vbuf ;
90102	HAL_StatusTypeDef  __maybe_unused  hal_ret ;
91103
104+ 	if  (dev_data -> snapshot_mode ) {
105+ 		/* we remove the buffer from the camera and add it to fifo_out */ 
106+ 		vbuf  =  dev_data -> vbuf ;
107+ 		dev_data -> vbuf  =  NULL ;
108+ 		vbuf -> timestamp  =  k_uptime_get_32 ();
109+ 		k_fifo_put (& dev_data -> fifo_out , vbuf );
110+ 		LOG_DBG ("event SH put: %p" , vbuf );
111+ 		return ;
112+ 	}
113+ 
114+ 	/* Not in snapshot_mode */ 
92115	hal_ret  =  HAL_DCMI_Suspend (hdcmi );
93116	__ASSERT_NO_MSG (hal_ret  ==  HAL_OK );
94117
@@ -276,22 +299,30 @@ static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable,
276299		return  0 ;
277300	}
278301
279- 	data -> vbuf  =  k_fifo_get (& data -> fifo_in , K_NO_WAIT );
302+ 	if  (!data -> snapshot_mode  &&  (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX  !=  1 )) {
303+ 		data -> vbuf  =  k_fifo_get (& data -> fifo_in , K_NO_WAIT );
280304
281- 	if  (data -> vbuf  ==  NULL ) {
282- 		LOG_ERR ("Failed to dequeue a DCMI buffer." );
283- 		return  - ENOMEM ;
305+ 		if  (data -> vbuf  ==  NULL ) {
306+ 			data -> snapshot_mode  =  true;
307+ 			LOG_WRN ("No buffers, assume snapshot mode." );
308+ 		}
284309	}
285310
286311	/* Set the frame control */ 
287312	data -> hdcmi .Instance -> CR  &= ~(DCMI_CR_FCRC_0  | DCMI_CR_FCRC_1 );
288313	data -> hdcmi .Instance -> CR  |= STM32_DCMI_GET_CAPTURE_RATE (data -> capture_rate );
289314
290- 	hal_ret  =  HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
291- 				     (uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused  / 4 );
292- 	if  (hal_ret  !=  HAL_OK ) {
293- 		LOG_ERR ("Failed to start DCMI DMA" );
294- 		return  - EIO ;
315+ 	/* don't start the DCMI DMA if we are in Snapshot mode */ 
316+ 	if  (!data -> snapshot_mode ) {
317+ 		hal_ret  =  HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
318+ 					     (uint32_t )data -> vbuf -> buffer ,
319+ 					     data -> vbuf -> bytesused  / 4 );
320+ 		if  (hal_ret  !=  HAL_OK ) {
321+ 			LOG_ERR ("Failed to start DCMI DMA" );
322+ 			return  - EIO ;
323+ 		}
324+ 	} else  {
325+ 		LOG_DBG ("Snapshot mode active" );
295326	}
296327
297328	return  video_stream_start (config -> sensor_dev , type );
@@ -314,19 +345,88 @@ static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffe
314345	return  0 ;
315346}
316347
317- static  int  video_stm32_dcmi_dequeue (const  struct  device  * dev , struct  video_buffer  * * vbuf ,
318- 				    k_timeout_t  timeout )
348+ static  int  video_stm32_dcmi_snapshot (const  struct  device  * dev , struct  video_buffer  * * vbuf ,
349+ 				      k_timeout_t  timeout )
319350{
320351	struct  video_stm32_dcmi_data  * data  =  dev -> data ;
352+ 	const  struct  video_stm32_dcmi_config  * config  =  dev -> config ;
353+ 
354+ 	LOG_DBG ("dequeue snapshot: %p %llu\n" , data -> vbuf , timeout .ticks );
355+ 
356+ 	/* See if we were already called and have an active buffer */ 
357+ 	if  (data -> vbuf  ==  NULL ) {
358+ 		/* check first to see if we already have a buffer returned */ 
359+ 		* vbuf  =  k_fifo_get (& data -> fifo_out , K_NO_WAIT );
360+ 		if  (* vbuf  !=  NULL ) {
361+ 			LOG_DBG ("k_fifo_get returned: %p\n" , * vbuf );
362+ 			if  (HAL_DCMI_Stop (& data -> hdcmi ) !=  HAL_OK ) {
363+ 				LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
364+ 			}
365+ 			return  0 ;
366+ 		}
367+ 		data -> vbuf  =  k_fifo_get (& data -> fifo_in , K_NO_WAIT );
368+ 		LOG_DBG ("\tcamera buf: %p\n" , data -> vbuf );
369+ 		if  (data -> vbuf  ==  NULL ) {
370+ 			LOG_WRN ("Snapshot: No Buffers available!" );
371+ 			return  - ENOMEM ;
372+ 		}
373+ 
374+ 		if  (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_SNAPSHOT ,
375+ 				       (uint32_t )data -> vbuf -> buffer ,
376+ 				       data -> vbuf -> size  / 4 ) !=  HAL_OK ) {
377+ 			LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
378+ 			return  - EIO ;
379+ 		}
380+ 
381+ 		/* remember when we started this request */ 
382+ 		data -> snapshot_start_time  =  k_uptime_get_32 ();
383+ 	}
321384
322385	* vbuf  =  k_fifo_get (& data -> fifo_out , timeout );
323386	if  (* vbuf  ==  NULL ) {
387+ 		uint32_t  time_since_start_time  = 
388+ 			(uint32_t )(k_uptime_get_32 () -  data -> snapshot_start_time );
389+ 		if  (time_since_start_time  >  config -> snapshot_timeout ) {
390+ 			LOG_WRN ("Snapshot: Timed out!" );
391+ 			if  (HAL_DCMI_Stop (& data -> hdcmi ) !=  HAL_OK ) {
392+ 				LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
393+ 			}
394+ 			/* verify it did not come in during this procuessing */ 
395+ 			* vbuf  =  k_fifo_get (& data -> fifo_out , K_NO_WAIT );
396+ 			if  (* vbuf ) {
397+ 				return  0 ;
398+ 			}
399+ 
400+ 			if  (data -> vbuf  !=  NULL ) {
401+ 				k_fifo_put (& data -> fifo_in , data -> vbuf );
402+ 				data -> vbuf  =  NULL ;
403+ 			}
404+ 		}
405+ 
324406		return  - EAGAIN ;
325407	}
326408
409+ 	if  (HAL_DCMI_Stop (& data -> hdcmi ) !=  HAL_OK ) {
410+ 		LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
411+ 	}
327412	return  0 ;
328413}
329414
415+ static  int  video_stm32_dcmi_dequeue (const  struct  device  * dev , struct  video_buffer  * * vbuf ,
416+ 				    k_timeout_t  timeout )
417+ {
418+ 	struct  video_stm32_dcmi_data  * data  =  dev -> data ;
419+ 
420+ 	if  (data -> snapshot_mode ) {
421+ 		return  video_stm32_dcmi_snapshot (dev , vbuf , timeout );
422+ 	}
423+ 
424+ 	* vbuf  =  k_fifo_get (& data -> fifo_out , timeout );
425+ 	LOG_DBG ("k_fifo_get returned: %p\n" , * vbuf );
426+ 
427+ 	return  (* vbuf  ==  NULL ) ? - EAGAIN  : 0 ;
428+ }
429+ 
330430static  int  video_stm32_dcmi_get_caps (const  struct  device  * dev , struct  video_caps  * caps )
331431{
332432	const  struct  video_stm32_dcmi_config  * config  =  dev -> config ;
@@ -338,6 +438,32 @@ static int video_stm32_dcmi_get_caps(const struct device *dev, struct video_caps
338438	return  video_get_caps (config -> sensor_dev , caps );
339439}
340440
441+ static  int  video_stm32_dcmi_set_ctrl_snapshot (const  struct  device  * dev , int  value )
442+ {
443+ 	struct  video_stm32_dcmi_data  * data  =  dev -> data ;
444+ 
445+ 	LOG_INF ("Set Snapshot: %d\n" , value );
446+ 	if  ((CONFIG_VIDEO_BUFFER_POOL_NUM_MAX  ==  1 ) &&  (value  ==  0 )) {
447+ 		LOG_DBG ("Only one buffer so snapshot mode only" );
448+ 		return  - EINVAL ;
449+ 	}
450+ 
451+ 	data -> snapshot_mode  =  value ;
452+ 	return  0 ;
453+ }
454+ 
455+ static  int  video_stm32_dcmi_set_ctrl (const  struct  device  * dev , uint32_t  id )
456+ {
457+ 	struct  video_stm32_dcmi_data  * data  =  dev -> data ;
458+ 	struct  video_stm32_dcmi_ctrls  * ctrls  =  & data -> ctrls ;
459+ 
460+ 	if  (id  ==  VIDEO_CID_SNAPSHOT_MODE ) {
461+ 		return  video_stm32_dcmi_set_ctrl_snapshot (dev , ctrls -> snapshot .val );
462+ 	}
463+ 
464+ 	return  - ENOTSUP ;
465+ }
466+ 
341467static  int  video_stm32_dcmi_enum_frmival (const  struct  device  * dev , struct  video_frmival_enum  * fie )
342468{
343469	const  struct  video_stm32_dcmi_config  * config  =  dev -> config ;
@@ -455,13 +581,25 @@ static DEVICE_API(video, video_stm32_dcmi_driver_api) = {
455581	.enqueue  =  video_stm32_dcmi_enqueue ,
456582	.dequeue  =  video_stm32_dcmi_dequeue ,
457583	.get_caps  =  video_stm32_dcmi_get_caps ,
584+ 	.set_ctrl  =  video_stm32_dcmi_set_ctrl ,
458585	.enum_frmival  =  video_stm32_dcmi_enum_frmival ,
459586	.set_frmival  =  video_stm32_dcmi_set_frmival ,
460587	.get_frmival  =  video_stm32_dcmi_get_frmival ,
461588	.set_selection  =  video_stm32_dcmi_set_selection ,
462589	.get_selection  =  video_stm32_dcmi_get_selection ,
463590};
464591
592+ static  int  video_stm32_dcmi_init_controls (const  struct  device  * dev )
593+ {
594+ 	struct  video_stm32_dcmi_data  * data  =  dev -> data ;
595+ 	struct  video_stm32_dcmi_ctrls  * ctrls  =  & data -> ctrls ;
596+ 
597+ 	return  video_init_ctrl (& ctrls -> snapshot , dev , VIDEO_CID_SNAPSHOT_MODE ,
598+ 			      (struct  video_ctrl_range ){.min  =  0 , .max  =  1 , .step  =  1 ,
599+ 							.def  =  data -> snapshot_mode  ? 1  : 0 });
600+ }
601+ 
602+ 
465603static  void  video_stm32_dcmi_irq_config_func (const  struct  device  * dev )
466604{
467605	IRQ_CONNECT (DT_INST_IRQN (0 ), DT_INST_IRQ (0 , priority ),
@@ -542,6 +680,8 @@ static const struct video_stm32_dcmi_config video_stm32_dcmi_config_0 = {
542680	.irq_config  =  video_stm32_dcmi_irq_config_func ,
543681	.pctrl  =  PINCTRL_DT_INST_DEV_CONFIG_GET (0 ),
544682	.sensor_dev  =  SOURCE_DEV (0 ),
683+ 	.snapshot_mode  =  DT_INST_PROP (0 , snapshot_mode ),
684+ 	.snapshot_timeout  =  DT_INST_PROP (0 , snapshot_timeout ),
545685	DCMI_DMA_CHANNEL (0 , PERIPHERAL , MEMORY )
546686};
547687
@@ -572,6 +712,12 @@ static int video_stm32_dcmi_init(const struct device *dev)
572712		return  err ;
573713	}
574714
715+ 	/* See if we should initialize to only support snapshot mode or not */ 
716+ 	data -> snapshot_mode  =  config -> snapshot_mode ;
717+ 	if  (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX  ==  1 ) {
718+ 		LOG_DBG ("Only one buffer so snapshot mode only" );
719+ 		data -> snapshot_mode  =  true;
720+ 	}
575721	data -> dev  =  dev ;
576722	k_fifo_init (& data -> fifo_in );
577723	k_fifo_init (& data -> fifo_out );
@@ -589,7 +735,8 @@ static int video_stm32_dcmi_init(const struct device *dev)
589735	k_sleep (K_MSEC (100 ));
590736	LOG_DBG ("%s inited" , dev -> name );
591737
592- 	return  0 ;
738+ 	/* Initialize controls */ 
739+ 	return  video_stm32_dcmi_init_controls (dev );
593740}
594741
595742DEVICE_DT_INST_DEFINE (0 , & video_stm32_dcmi_init ,
0 commit comments