@@ -134,6 +134,49 @@ struct stm32_dcmipp_config {
134134#define STM32_DCMIPP_WIDTH_MAX 4094
135135#define STM32_DCMIPP_HEIGHT_MAX 4094
136136
137+ static void stm32_dcmipp_set_next_buffer_addr (struct stm32_dcmipp_pipe_data * pipe )
138+ {
139+ struct stm32_dcmipp_data * dcmipp = pipe -> dcmipp ;
140+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
141+ struct video_format * fmt = & pipe -> fmt ;
142+ #endif
143+ uint8_t * plane = pipe -> next -> buffer ;
144+
145+ /* TODO - the HAL is missing a SetMemoryAddress for auxiliary addresses */
146+ /* Update main buffer address */
147+ if (pipe -> id == DCMIPP_PIPE0 ) {
148+ WRITE_REG (dcmipp -> hdcmipp .Instance -> P0PPM0AR1 , (uint32_t )plane );
149+ }
150+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
151+ else if (pipe -> id == DCMIPP_PIPE1 ) {
152+ WRITE_REG (dcmipp -> hdcmipp .Instance -> P1PPM0AR1 , (uint32_t )plane );
153+ } else {
154+ WRITE_REG (dcmipp -> hdcmipp .Instance -> P2PPM0AR1 , (uint32_t )plane );
155+ }
156+
157+ if (pipe -> id != DCMIPP_PIPE1 ) {
158+ return ;
159+ }
160+
161+ if (fmt -> pixelformat == VIDEO_PIX_FMT_NV12 || fmt -> pixelformat == VIDEO_PIX_FMT_NV21 ||
162+ fmt -> pixelformat == VIDEO_PIX_FMT_NV16 || fmt -> pixelformat == VIDEO_PIX_FMT_NV61 ||
163+ fmt -> pixelformat == VIDEO_PIX_FMT_YUV420 || fmt -> pixelformat == VIDEO_PIX_FMT_YVU420 ) {
164+ /* Y plane has 8 bit per pixel, next plane is located at off + width * height */
165+ plane += (fmt -> width * fmt -> height );
166+
167+ WRITE_REG (dcmipp -> hdcmipp .Instance -> P1PPM1AR1 , (uint32_t )plane );
168+
169+ if (fmt -> pixelformat == VIDEO_PIX_FMT_YUV420 ||
170+ fmt -> pixelformat == VIDEO_PIX_FMT_YVU420 ) {
171+ /* In case of YUV420 / YVU420, U plane has half width / half height */
172+ plane += (fmt -> width * fmt -> height ) / 4 ;
173+
174+ WRITE_REG (dcmipp -> hdcmipp .Instance -> P1PPM2AR1 , (uint32_t )plane );
175+ }
176+ }
177+ #endif
178+ }
179+
137180/* Callback getting called for each frame written into memory */
138181void HAL_DCMIPP_PIPE_FrameEventCallback (DCMIPP_HandleTypeDef * hdcmipp , uint32_t Pipe )
139182{
@@ -171,7 +214,6 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
171214 struct stm32_dcmipp_data * dcmipp =
172215 CONTAINER_OF (hdcmipp , struct stm32_dcmipp_data , hdcmipp );
173216 struct stm32_dcmipp_pipe_data * pipe = dcmipp -> pipe [Pipe ];
174- int ret ;
175217
176218#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
177219 /*
@@ -209,17 +251,8 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
209251 return ;
210252 }
211253
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- }
254+ /* Update buffer address */
255+ stm32_dcmipp_set_next_buffer_addr (pipe );
223256}
224257
225258#if defined(STM32_DCMIPP_HAS_CSI )
@@ -443,7 +476,13 @@ static const struct stm32_dcmipp_mapping {
443476 PIXEL_PIPE_FMT (ABGR32 , ARGB8888 , 0 , (BIT (1 ) | BIT (2 ))),
444477 PIXEL_PIPE_FMT (RGBA32 , ARGB8888 , 1 , (BIT (1 ) | BIT (2 ))),
445478 PIXEL_PIPE_FMT (BGRA32 , RGBA888 , 0 , (BIT (1 ) | BIT (2 ))),
446- /* TODO - need to add the semiplanar & planar formats */
479+ /* Multi-planes are only available on Pipe main (1) */
480+ PIXEL_PIPE_FMT (NV12 , YUV420_2 , 0 , BIT (1 )),
481+ PIXEL_PIPE_FMT (NV21 , YUV420_2 , 1 , BIT (1 )),
482+ PIXEL_PIPE_FMT (NV16 , YUV422_2 , 0 , BIT (1 )),
483+ PIXEL_PIPE_FMT (NV61 , YUV422_2 , 1 , BIT (1 )),
484+ PIXEL_PIPE_FMT (YUV420 , YUV420_3 , 0 , BIT (1 )),
485+ PIXEL_PIPE_FMT (YVU420 , YUV420_3 , 1 , BIT (1 )),
447486#endif
448487};
449488
@@ -464,6 +503,9 @@ static const struct stm32_dcmipp_mapping {
464503 ((fmt) == VIDEO_PIX_FMT_GREY || \
465504 (fmt) == VIDEO_PIX_FMT_YUYV || (fmt) == VIDEO_PIX_FMT_YVYU || \
466505 (fmt) == VIDEO_PIX_FMT_VYUY || (fmt) == VIDEO_PIX_FMT_UYVY || \
506+ (fmt) == VIDEO_PIX_FMT_NV12 || (fmt) == VIDEO_PIX_FMT_NV21 || \
507+ (fmt) == VIDEO_PIX_FMT_NV16 || (fmt) == VIDEO_PIX_FMT_NV61 || \
508+ (fmt) == VIDEO_PIX_FMT_YUV420 || (fmt) == VIDEO_PIX_FMT_YVU420 || \
467509 (fmt) == VIDEO_PIX_FMT_XYUV32) ? VIDEO_COLORSPACE_YUV : \
468510 \
469511 VIDEO_COLORSPACE_RAW)
@@ -859,6 +901,98 @@ static int stm32_dcmipp_set_yuv_conversion(struct stm32_dcmipp_pipe_data *pipe,
859901}
860902#endif
861903
904+ static int stm32_dcmipp_start_pipeline (const struct device * dev ,
905+ struct stm32_dcmipp_pipe_data * pipe )
906+ {
907+ const struct stm32_dcmipp_config * config = dev -> config ;
908+ struct stm32_dcmipp_data * dcmipp = pipe -> dcmipp ;
909+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
910+ struct video_format * fmt = & pipe -> fmt ;
911+ #endif
912+ int ret ;
913+
914+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
915+ if (fmt -> pixelformat == VIDEO_PIX_FMT_YUV420 || fmt -> pixelformat == VIDEO_PIX_FMT_YVU420 ) {
916+ uint8_t * u_addr = pipe -> next -> buffer + fmt -> width * fmt -> height ;
917+ uint8_t * v_addr = u_addr + (fmt -> width * fmt -> height / 4 );
918+ DCMIPP_FullPlanarDstAddressTypeDef planar_addr = {
919+ .YAddress = (uint32_t )pipe -> next -> buffer ,
920+ .UAddress = (uint32_t )u_addr ,
921+ .VAddress = (uint32_t )v_addr ,
922+ };
923+
924+ if (config -> bus_type == VIDEO_BUS_TYPE_PARALLEL ) {
925+ ret = HAL_DCMIPP_PIPE_FullPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
926+ & planar_addr , DCMIPP_MODE_CONTINUOUS );
927+ }
928+ #if defined(STM32_DCMIPP_HAS_CSI )
929+ else if (config -> bus_type == VIDEO_BUS_TYPE_CSI2_DPHY ) {
930+ ret = HAL_DCMIPP_CSI_PIPE_FullPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
931+ DCMIPP_VIRTUAL_CHANNEL0 ,
932+ & planar_addr ,
933+ DCMIPP_MODE_CONTINUOUS );
934+ }
935+ #endif
936+ else {
937+ LOG_ERR ("Invalid bus_type" );
938+ ret = - EINVAL ;
939+ }
940+ } else if (fmt -> pixelformat == VIDEO_PIX_FMT_NV12 ||
941+ fmt -> pixelformat == VIDEO_PIX_FMT_NV21 ||
942+ fmt -> pixelformat == VIDEO_PIX_FMT_NV16 ||
943+ fmt -> pixelformat == VIDEO_PIX_FMT_NV61 ) {
944+ uint8_t * uv_addr = pipe -> next -> buffer + fmt -> width * fmt -> height ;
945+ DCMIPP_SemiPlanarDstAddressTypeDef semiplanar_addr = {
946+ .YAddress = (uint32_t )pipe -> next -> buffer ,
947+ .UVAddress = (uint32_t )uv_addr ,
948+ };
949+
950+ if (config -> bus_type == VIDEO_BUS_TYPE_PARALLEL ) {
951+ ret = HAL_DCMIPP_PIPE_SemiPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
952+ & semiplanar_addr ,
953+ DCMIPP_MODE_CONTINUOUS );
954+ }
955+ #if defined(STM32_DCMIPP_HAS_CSI )
956+ else if (config -> bus_type == VIDEO_BUS_TYPE_CSI2_DPHY ) {
957+ ret = HAL_DCMIPP_CSI_PIPE_SemiPlanarStart (& dcmipp -> hdcmipp , pipe -> id ,
958+ DCMIPP_VIRTUAL_CHANNEL0 ,
959+ & semiplanar_addr ,
960+ DCMIPP_MODE_CONTINUOUS );
961+ }
962+ #endif
963+ else {
964+ LOG_ERR ("Invalid bus_type" );
965+ ret = - EINVAL ;
966+ }
967+ } else {
968+ #endif
969+ if (config -> bus_type == VIDEO_BUS_TYPE_PARALLEL ) {
970+ ret = HAL_DCMIPP_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id ,
971+ (uint32_t )pipe -> next -> buffer ,
972+ DCMIPP_MODE_CONTINUOUS );
973+ }
974+ #if defined(STM32_DCMIPP_HAS_CSI )
975+ else if (config -> bus_type == VIDEO_BUS_TYPE_CSI2_DPHY ) {
976+ ret = HAL_DCMIPP_CSI_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id ,
977+ DCMIPP_VIRTUAL_CHANNEL0 ,
978+ (uint32_t )pipe -> next -> buffer ,
979+ DCMIPP_MODE_CONTINUOUS );
980+ }
981+ #endif
982+ else {
983+ LOG_ERR ("Invalid bus_type" );
984+ ret = - EINVAL ;
985+ }
986+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
987+ }
988+ #endif
989+ if (ret != HAL_OK ) {
990+ return - EIO ;
991+ }
992+
993+ return 0 ;
994+ }
995+
862996static int stm32_dcmipp_stream_enable (const struct device * dev )
863997{
864998 struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
@@ -946,7 +1080,16 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
9461080 pipe_cfg .FrameRate = DCMIPP_FRAME_RATE_ALL ;
9471081#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
9481082 if (pipe -> id == DCMIPP_PIPE1 || pipe -> id == DCMIPP_PIPE2 ) {
949- pipe_cfg .PixelPipePitch = fmt -> pitch ;
1083+ if (fmt -> pixelformat == VIDEO_PIX_FMT_NV12 ||
1084+ fmt -> pixelformat == VIDEO_PIX_FMT_NV21 ||
1085+ fmt -> pixelformat == VIDEO_PIX_FMT_NV16 ||
1086+ fmt -> pixelformat == VIDEO_PIX_FMT_NV61 ||
1087+ fmt -> pixelformat == VIDEO_PIX_FMT_YUV420 ||
1088+ fmt -> pixelformat == VIDEO_PIX_FMT_YVU420 ) {
1089+ pipe_cfg .PixelPipePitch = fmt -> width ;
1090+ } else {
1091+ pipe_cfg .PixelPipePitch = fmt -> pitch ;
1092+ }
9501093 pipe_cfg .PixelPackerFormat = mapping -> pixels .dcmipp_format ;
9511094 }
9521095#endif
@@ -1042,25 +1185,9 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
10421185#endif
10431186
10441187 /* 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 ) {
1188+ ret = stm32_dcmipp_start_pipeline (dev , pipe );
1189+ if (ret < 0 ) {
10621190 LOG_ERR ("Failed to start the pipeline" );
1063- ret = - EIO ;
10641191 goto out ;
10651192 }
10661193
@@ -1183,7 +1310,6 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
11831310{
11841311 struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
11851312 struct stm32_dcmipp_data * dcmipp = pipe -> dcmipp ;
1186- int ret ;
11871313
11881314 k_mutex_lock (& pipe -> lock , K_FOREVER );
11891315
@@ -1194,13 +1320,7 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
11941320 if (pipe -> state == STM32_DCMIPP_WAIT_FOR_BUFFER ) {
11951321 LOG_DBG ("Restart CPTREQ after wait for buffer" );
11961322 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- }
1323+ stm32_dcmipp_set_next_buffer_addr (pipe );
12041324 if (pipe -> id == DCMIPP_PIPE0 ) {
12051325 SET_BIT (dcmipp -> hdcmipp .Instance -> P0FCTCR , DCMIPP_P0FCTCR_CPTREQ );
12061326 }
0 commit comments