@@ -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