@@ -134,6 +134,49 @@ struct stm32_dcmipp_config {
134
134
#define STM32_DCMIPP_WIDTH_MAX 4094
135
135
#define STM32_DCMIPP_HEIGHT_MAX 4094
136
136
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
+
137
180
/* Callback getting called for each frame written into memory */
138
181
void HAL_DCMIPP_PIPE_FrameEventCallback (DCMIPP_HandleTypeDef * hdcmipp , uint32_t Pipe )
139
182
{
@@ -171,7 +214,6 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
171
214
struct stm32_dcmipp_data * dcmipp =
172
215
CONTAINER_OF (hdcmipp , struct stm32_dcmipp_data , hdcmipp );
173
216
struct stm32_dcmipp_pipe_data * pipe = dcmipp -> pipe [Pipe ];
174
- int ret ;
175
217
176
218
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
177
219
/*
@@ -209,17 +251,8 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
209
251
return ;
210
252
}
211
253
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 );
223
256
}
224
257
225
258
#if defined(STM32_DCMIPP_HAS_CSI )
@@ -443,7 +476,13 @@ static const struct stm32_dcmipp_mapping {
443
476
PIXEL_PIPE_FMT (ABGR32 , ARGB8888 , 0 , (BIT (1 ) | BIT (2 ))),
444
477
PIXEL_PIPE_FMT (RGBA32 , ARGB8888 , 1 , (BIT (1 ) | BIT (2 ))),
445
478
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 )),
447
486
#endif
448
487
};
449
488
@@ -464,6 +503,9 @@ static const struct stm32_dcmipp_mapping {
464
503
((fmt) == VIDEO_PIX_FMT_GREY || \
465
504
(fmt) == VIDEO_PIX_FMT_YUYV || (fmt) == VIDEO_PIX_FMT_YVYU || \
466
505
(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 || \
467
509
(fmt) == VIDEO_PIX_FMT_XYUV32) ? VIDEO_COLORSPACE_YUV : \
468
510
\
469
511
VIDEO_COLORSPACE_RAW)
@@ -859,6 +901,98 @@ static int stm32_dcmipp_set_yuv_conversion(struct stm32_dcmipp_pipe_data *pipe,
859
901
}
860
902
#endif
861
903
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
+
862
996
static int stm32_dcmipp_stream_enable (const struct device * dev )
863
997
{
864
998
struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
@@ -946,7 +1080,16 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
946
1080
pipe_cfg .FrameRate = DCMIPP_FRAME_RATE_ALL ;
947
1081
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
948
1082
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
+ }
950
1093
pipe_cfg .PixelPackerFormat = mapping -> pixels .dcmipp_format ;
951
1094
}
952
1095
#endif
@@ -1042,25 +1185,9 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
1042
1185
#endif
1043
1186
1044
1187
/* 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 ) {
1062
1190
LOG_ERR ("Failed to start the pipeline" );
1063
- ret = - EIO ;
1064
1191
goto out ;
1065
1192
}
1066
1193
@@ -1183,7 +1310,6 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
1183
1310
{
1184
1311
struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
1185
1312
struct stm32_dcmipp_data * dcmipp = pipe -> dcmipp ;
1186
- int ret ;
1187
1313
1188
1314
k_mutex_lock (& pipe -> lock , K_FOREVER );
1189
1315
@@ -1194,13 +1320,7 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
1194
1320
if (pipe -> state == STM32_DCMIPP_WAIT_FOR_BUFFER ) {
1195
1321
LOG_DBG ("Restart CPTREQ after wait for buffer" );
1196
1322
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 );
1204
1324
if (pipe -> id == DCMIPP_PIPE0 ) {
1205
1325
SET_BIT (dcmipp -> hdcmipp .Instance -> P0FCTCR , DCMIPP_P0FCTCR_CPTREQ );
1206
1326
}
0 commit comments