@@ -134,6 +134,62 @@ struct stm32_dcmipp_config {
134134#define  STM32_DCMIPP_WIDTH_MAX 	4094
135135#define  STM32_DCMIPP_HEIGHT_MAX 	4094
136136
137+ #define  VIDEO_FMT_IS_SEMI_PLANAR (fmt )			\
138+ 	(((fmt)->pixelformat == VIDEO_PIX_FMT_NV12 ||	\
139+ 	  (fmt)->pixelformat == VIDEO_PIX_FMT_NV21 ||	\
140+ 	  (fmt)->pixelformat == VIDEO_PIX_FMT_NV16 ||	\
141+ 	  (fmt)->pixelformat == VIDEO_PIX_FMT_NV61) ? true : false)
142+ 
143+ #define  VIDEO_FMT_IS_PLANAR (fmt )			\
144+ 	(((fmt)->pixelformat == VIDEO_PIX_FMT_YUV420 ||	\
145+ 	  (fmt)->pixelformat == VIDEO_PIX_FMT_YVU420) ? true : false)
146+ 
147+ #define  VIDEO_Y_PLANE_PITCH (fmt )						\
148+ 	((VIDEO_FMT_IS_PLANAR(fmt) || VIDEO_FMT_IS_SEMI_PLANAR(fmt)) ?		\
149+ 	 (fmt)->width : (fmt)->pitch)
150+ 
151+ #define  VIDEO_FMT_PLANAR_Y_PLANE_SIZE (fmt )	((fmt)->width * (fmt)->height)
152+ 
153+ static  void  stm32_dcmipp_set_next_buffer_addr (struct  stm32_dcmipp_pipe_data  * pipe )
154+ {
155+ 	struct  stm32_dcmipp_data  * dcmipp  =  pipe -> dcmipp ;
156+ #if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
157+ 	struct  video_format  * fmt  =  & pipe -> fmt ;
158+ #endif 
159+ 	uint8_t  * plane  =  pipe -> next -> buffer ;
160+ 
161+ 	/* TODO - the HAL is missing a SetMemoryAddress for auxiliary addresses */ 
162+ 	/* Update main buffer address */ 
163+ 	if  (pipe -> id  ==  DCMIPP_PIPE0 ) {
164+ 		WRITE_REG (dcmipp -> hdcmipp .Instance -> P0PPM0AR1 , (uint32_t )plane );
165+ 	}
166+ #if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
167+ 	else  if  (pipe -> id  ==  DCMIPP_PIPE1 ) {
168+ 		WRITE_REG (dcmipp -> hdcmipp .Instance -> P1PPM0AR1 , (uint32_t )plane );
169+ 	} else  {
170+ 		WRITE_REG (dcmipp -> hdcmipp .Instance -> P2PPM0AR1 , (uint32_t )plane );
171+ 	}
172+ 
173+ 	if  (pipe -> id  !=  DCMIPP_PIPE1 ) {
174+ 		return ;
175+ 	}
176+ 
177+ 	if  (VIDEO_FMT_IS_SEMI_PLANAR (fmt ) ||  VIDEO_FMT_IS_PLANAR (fmt )) {
178+ 		/* Y plane has 8 bit per pixel, next plane is located at off + width * height */ 
179+ 		plane  +=  VIDEO_FMT_PLANAR_Y_PLANE_SIZE (fmt );
180+ 
181+ 		WRITE_REG (dcmipp -> hdcmipp .Instance -> P1PPM1AR1 , (uint32_t )plane );
182+ 
183+ 		if  (VIDEO_FMT_IS_PLANAR (fmt )) {
184+ 			/* In case of YUV420 / YVU420, U plane has half width / half height */ 
185+ 			plane  +=  VIDEO_FMT_PLANAR_Y_PLANE_SIZE (fmt ) / 4 ;
186+ 
187+ 			WRITE_REG (dcmipp -> hdcmipp .Instance -> P1PPM2AR1 , (uint32_t )plane );
188+ 		}
189+ 	}
190+ #endif 
191+ }
192+ 
137193/* Callback getting called for each frame written into memory */ 
138194void  HAL_DCMIPP_PIPE_FrameEventCallback (DCMIPP_HandleTypeDef  * hdcmipp , uint32_t  Pipe )
139195{
@@ -171,7 +227,6 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
171227	struct  stm32_dcmipp_data  * dcmipp  = 
172228			CONTAINER_OF (hdcmipp , struct  stm32_dcmipp_data , hdcmipp );
173229	struct  stm32_dcmipp_pipe_data  * pipe  =  dcmipp -> pipe [Pipe ];
174- 	int  ret ;
175230
176231#if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
177232	/* 
@@ -209,17 +264,8 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
209264		return ;
210265	}
211266
212- 	/* 
213- 	 * TODO - we only support 1 buffer formats for the time being, setting of 
214- 	 * MEMORY_ADDRESS_1 and MEMORY_ADDRESS_2 required depending on the pixelformat 
215- 	 * for Pipe1 
216- 	 */ 
217- 	ret  =  HAL_DCMIPP_PIPE_SetMemoryAddress (& dcmipp -> hdcmipp , Pipe , DCMIPP_MEMORY_ADDRESS_0 ,
218- 					       (uint32_t )pipe -> next -> buffer );
219- 	if  (ret  !=  HAL_OK ) {
220- 		LOG_ERR ("Failed to update memory address" );
221- 		return ;
222- 	}
267+ 	/* Update buffer address */ 
268+ 	stm32_dcmipp_set_next_buffer_addr (pipe );
223269}
224270
225271#if  defined(STM32_DCMIPP_HAS_CSI )
@@ -443,7 +489,13 @@ static const struct stm32_dcmipp_mapping {
443489	PIXEL_PIPE_FMT (ABGR32 , ARGB8888 , 0 , (BIT (1 ) | BIT (2 ))),
444490	PIXEL_PIPE_FMT (RGBA32 , ARGB8888 , 1 , (BIT (1 ) | BIT (2 ))),
445491	PIXEL_PIPE_FMT (BGRA32 , RGBA888 , 0 , (BIT (1 ) | BIT (2 ))),
446- 	/* TODO - need to add the semiplanar & planar formats */ 
492+ 	/* Multi-planes are only available on Pipe main (1) */ 
493+ 	PIXEL_PIPE_FMT (NV12 , YUV420_2 , 0 , BIT (1 )),
494+ 	PIXEL_PIPE_FMT (NV21 , YUV420_2 , 1 , BIT (1 )),
495+ 	PIXEL_PIPE_FMT (NV16 , YUV422_2 , 0 , BIT (1 )),
496+ 	PIXEL_PIPE_FMT (NV61 , YUV422_2 , 1 , BIT (1 )),
497+ 	PIXEL_PIPE_FMT (YUV420 , YUV420_3 , 0 , BIT (1 )),
498+ 	PIXEL_PIPE_FMT (YVU420 , YUV420_3 , 1 , BIT (1 )),
447499#endif 
448500};
449501
@@ -464,6 +516,9 @@ static const struct stm32_dcmipp_mapping {
464516	 ((fmt) == VIDEO_PIX_FMT_GREY ||					\
465517	  (fmt) == VIDEO_PIX_FMT_YUYV || (fmt) == VIDEO_PIX_FMT_YVYU ||		\
466518	  (fmt) == VIDEO_PIX_FMT_VYUY || (fmt) == VIDEO_PIX_FMT_UYVY ||		\
519+ 	  (fmt) == VIDEO_PIX_FMT_NV12 || (fmt) == VIDEO_PIX_FMT_NV21 ||		\
520+ 	  (fmt) == VIDEO_PIX_FMT_NV16 || (fmt) == VIDEO_PIX_FMT_NV61 ||		\
521+ 	  (fmt) == VIDEO_PIX_FMT_YUV420 || (fmt) == VIDEO_PIX_FMT_YVU420 ||	\
467522	  (fmt) == VIDEO_PIX_FMT_XYUV32) ? VIDEO_COLORSPACE_YUV :		\
468523										\
469524	  VIDEO_COLORSPACE_RAW)
@@ -859,6 +914,95 @@ static int stm32_dcmipp_set_yuv_conversion(struct stm32_dcmipp_pipe_data *pipe,
859914}
860915#endif 
861916
917+ static  int  stm32_dcmipp_start_pipeline (const  struct  device  * dev ,
918+ 				       struct  stm32_dcmipp_pipe_data  * pipe )
919+ {
920+ 	const  struct  stm32_dcmipp_config  * config  =  dev -> config ;
921+ 	struct  stm32_dcmipp_data  * dcmipp  =  pipe -> dcmipp ;
922+ #if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
923+ 	struct  video_format  * fmt  =  & pipe -> fmt ;
924+ #endif 
925+ 	int  ret ;
926+ 
927+ #if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
928+ 	if  (VIDEO_FMT_IS_PLANAR (fmt )) {
929+ 		uint8_t  * u_addr  =  pipe -> next -> buffer  +  VIDEO_FMT_PLANAR_Y_PLANE_SIZE (fmt );
930+ 		uint8_t  * v_addr  =  u_addr  +  (VIDEO_FMT_PLANAR_Y_PLANE_SIZE (fmt ) / 4 );
931+ 		DCMIPP_FullPlanarDstAddressTypeDef  planar_addr  =  {
932+ 			.YAddress  =  (uint32_t )pipe -> next -> buffer ,
933+ 			.UAddress  =  (uint32_t )u_addr ,
934+ 			.VAddress  =  (uint32_t )v_addr ,
935+ 		};
936+ 
937+ 		if  (config -> bus_type  ==  VIDEO_BUS_TYPE_PARALLEL ) {
938+ 			ret  =  HAL_DCMIPP_PIPE_FullPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
939+ 							      & planar_addr , DCMIPP_MODE_CONTINUOUS );
940+ 		}
941+ #if  defined(STM32_DCMIPP_HAS_CSI )
942+ 		else  if  (config -> bus_type  ==  VIDEO_BUS_TYPE_CSI2_DPHY ) {
943+ 			ret  =  HAL_DCMIPP_CSI_PIPE_FullPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
944+ 								  DCMIPP_VIRTUAL_CHANNEL0 ,
945+ 								  & planar_addr ,
946+ 								  DCMIPP_MODE_CONTINUOUS );
947+ 		}
948+ #endif 
949+ 		else  {
950+ 			LOG_ERR ("Invalid bus_type" );
951+ 			ret  =  - EINVAL ;
952+ 		}
953+ 	} else  if  (VIDEO_FMT_IS_SEMI_PLANAR (fmt )) {
954+ 		uint8_t  * uv_addr  =  pipe -> next -> buffer  +  VIDEO_FMT_PLANAR_Y_PLANE_SIZE (fmt );
955+ 		DCMIPP_SemiPlanarDstAddressTypeDef  semiplanar_addr  =  {
956+ 			.YAddress  =  (uint32_t )pipe -> next -> buffer ,
957+ 			.UVAddress  =  (uint32_t )uv_addr ,
958+ 		};
959+ 
960+ 		if  (config -> bus_type  ==  VIDEO_BUS_TYPE_PARALLEL ) {
961+ 			ret  =  HAL_DCMIPP_PIPE_SemiPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
962+ 							      & semiplanar_addr ,
963+ 							      DCMIPP_MODE_CONTINUOUS );
964+ 		}
965+ #if  defined(STM32_DCMIPP_HAS_CSI )
966+ 		else  if  (config -> bus_type  ==  VIDEO_BUS_TYPE_CSI2_DPHY ) {
967+ 			ret  =  HAL_DCMIPP_CSI_PIPE_SemiPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
968+ 								  DCMIPP_VIRTUAL_CHANNEL0 ,
969+ 								  & semiplanar_addr ,
970+ 								  DCMIPP_MODE_CONTINUOUS );
971+ 		}
972+ #endif 
973+ 		else  {
974+ 			LOG_ERR ("Invalid bus_type" );
975+ 			ret  =  - EINVAL ;
976+ 		}
977+ 	} else  {
978+ #endif 
979+ 		if  (config -> bus_type  ==  VIDEO_BUS_TYPE_PARALLEL ) {
980+ 			ret  =  HAL_DCMIPP_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id ,
981+ 						    (uint32_t )pipe -> next -> buffer ,
982+ 						    DCMIPP_MODE_CONTINUOUS );
983+ 		}
984+ #if  defined(STM32_DCMIPP_HAS_CSI )
985+ 		else  if  (config -> bus_type  ==  VIDEO_BUS_TYPE_CSI2_DPHY ) {
986+ 			ret  =  HAL_DCMIPP_CSI_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id ,
987+ 							DCMIPP_VIRTUAL_CHANNEL0 ,
988+ 							(uint32_t )pipe -> next -> buffer ,
989+ 							DCMIPP_MODE_CONTINUOUS );
990+ 		}
991+ #endif 
992+ 		else  {
993+ 			LOG_ERR ("Invalid bus_type" );
994+ 			ret  =  - EINVAL ;
995+ 		}
996+ #if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
997+ 	}
998+ #endif 
999+ 	if  (ret  !=  HAL_OK ) {
1000+ 		return  - EIO ;
1001+ 	}
1002+ 
1003+ 	return  0 ;
1004+ }
1005+ 
8621006static  int  stm32_dcmipp_stream_enable (const  struct  device  * dev )
8631007{
8641008	struct  stm32_dcmipp_pipe_data  * pipe  =  dev -> data ;
@@ -946,7 +1090,7 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
9461090	pipe_cfg .FrameRate   =  DCMIPP_FRAME_RATE_ALL ;
9471091#if  defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
9481092	if  (pipe -> id  ==  DCMIPP_PIPE1  ||  pipe -> id  ==  DCMIPP_PIPE2 ) {
949- 		pipe_cfg .PixelPipePitch  =  fmt -> pitch ;
1093+ 		pipe_cfg .PixelPipePitch  =  VIDEO_Y_PLANE_PITCH ( fmt ) ;
9501094		pipe_cfg .PixelPackerFormat  =  mapping -> pixels .dcmipp_format ;
9511095	}
9521096#endif 
@@ -1042,25 +1186,9 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
10421186#endif 
10431187
10441188	/* Enable the DCMIPP Pipeline */ 
1045- 	if  (config -> bus_type  ==  VIDEO_BUS_TYPE_PARALLEL ) {
1046- 		ret  =  HAL_DCMIPP_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id ,
1047- 					(uint32_t )pipe -> next -> buffer , DCMIPP_MODE_CONTINUOUS );
1048- 	}
1049- #if  defined(STM32_DCMIPP_HAS_CSI )
1050- 	else  if  (config -> bus_type  ==  VIDEO_BUS_TYPE_CSI2_DPHY ) {
1051- 		ret  =  HAL_DCMIPP_CSI_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id , DCMIPP_VIRTUAL_CHANNEL0 ,
1052- 						(uint32_t )pipe -> next -> buffer ,
1053- 						DCMIPP_MODE_CONTINUOUS );
1054- 	}
1055- #endif 
1056- 	else  {
1057- 		LOG_ERR ("Invalid bus_type" );
1058- 		ret  =  - EINVAL ;
1059- 		goto out ;
1060- 	}
1061- 	if  (ret  !=  HAL_OK ) {
1189+ 	ret  =  stm32_dcmipp_start_pipeline (dev , pipe );
1190+ 	if  (ret  <  0 ) {
10621191		LOG_ERR ("Failed to start the pipeline" );
1063- 		ret  =  - EIO ;
10641192		goto out ;
10651193	}
10661194
@@ -1183,7 +1311,6 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
11831311{
11841312	struct  stm32_dcmipp_pipe_data  * pipe  =  dev -> data ;
11851313	struct  stm32_dcmipp_data  * dcmipp  =  pipe -> dcmipp ;
1186- 	int  ret ;
11871314
11881315	k_mutex_lock (& pipe -> lock , K_FOREVER );
11891316
@@ -1194,13 +1321,7 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
11941321	if  (pipe -> state  ==  STM32_DCMIPP_WAIT_FOR_BUFFER ) {
11951322		LOG_DBG ("Restart CPTREQ after wait for buffer" );
11961323		pipe -> next  =  vbuf ;
1197- 		ret  =  HAL_DCMIPP_PIPE_SetMemoryAddress (& dcmipp -> hdcmipp , pipe -> id ,
1198- 						       DCMIPP_MEMORY_ADDRESS_0 ,
1199- 						       (uint32_t )pipe -> next -> buffer );
1200- 		if  (ret  !=  HAL_OK ) {
1201- 			LOG_ERR ("Failed to update memory address" );
1202- 			return  - EIO ;
1203- 		}
1324+ 		stm32_dcmipp_set_next_buffer_addr (pipe );
12041325		if  (pipe -> id  ==  DCMIPP_PIPE0 ) {
12051326			SET_BIT (dcmipp -> hdcmipp .Instance -> P0FCTCR , DCMIPP_P0FCTCR_CPTREQ );
12061327		}
0 commit comments