@@ -134,6 +134,62 @@ struct stm32_dcmipp_config {
134
134
#define STM32_DCMIPP_WIDTH_MAX 4094
135
135
#define STM32_DCMIPP_HEIGHT_MAX 4094
136
136
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
+
137
193
/* Callback getting called for each frame written into memory */
138
194
void HAL_DCMIPP_PIPE_FrameEventCallback (DCMIPP_HandleTypeDef * hdcmipp , uint32_t Pipe )
139
195
{
@@ -171,7 +227,6 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
171
227
struct stm32_dcmipp_data * dcmipp =
172
228
CONTAINER_OF (hdcmipp , struct stm32_dcmipp_data , hdcmipp );
173
229
struct stm32_dcmipp_pipe_data * pipe = dcmipp -> pipe [Pipe ];
174
- int ret ;
175
230
176
231
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
177
232
/*
@@ -209,17 +264,8 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
209
264
return ;
210
265
}
211
266
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 );
223
269
}
224
270
225
271
#if defined(STM32_DCMIPP_HAS_CSI )
@@ -443,7 +489,13 @@ static const struct stm32_dcmipp_mapping {
443
489
PIXEL_PIPE_FMT (ABGR32 , ARGB8888 , 0 , (BIT (1 ) | BIT (2 ))),
444
490
PIXEL_PIPE_FMT (RGBA32 , ARGB8888 , 1 , (BIT (1 ) | BIT (2 ))),
445
491
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 )),
447
499
#endif
448
500
};
449
501
@@ -464,6 +516,9 @@ static const struct stm32_dcmipp_mapping {
464
516
((fmt) == VIDEO_PIX_FMT_GREY || \
465
517
(fmt) == VIDEO_PIX_FMT_YUYV || (fmt) == VIDEO_PIX_FMT_YVYU || \
466
518
(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 || \
467
522
(fmt) == VIDEO_PIX_FMT_XYUV32) ? VIDEO_COLORSPACE_YUV : \
468
523
\
469
524
VIDEO_COLORSPACE_RAW)
@@ -859,6 +914,95 @@ static int stm32_dcmipp_set_yuv_conversion(struct stm32_dcmipp_pipe_data *pipe,
859
914
}
860
915
#endif
861
916
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
+
862
1006
static int stm32_dcmipp_stream_enable (const struct device * dev )
863
1007
{
864
1008
struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
@@ -946,7 +1090,7 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
946
1090
pipe_cfg .FrameRate = DCMIPP_FRAME_RATE_ALL ;
947
1091
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
948
1092
if (pipe -> id == DCMIPP_PIPE1 || pipe -> id == DCMIPP_PIPE2 ) {
949
- pipe_cfg .PixelPipePitch = fmt -> pitch ;
1093
+ pipe_cfg .PixelPipePitch = VIDEO_Y_PLANE_PITCH ( fmt ) ;
950
1094
pipe_cfg .PixelPackerFormat = mapping -> pixels .dcmipp_format ;
951
1095
}
952
1096
#endif
@@ -1042,25 +1186,9 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
1042
1186
#endif
1043
1187
1044
1188
/* 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 ) {
1062
1191
LOG_ERR ("Failed to start the pipeline" );
1063
- ret = - EIO ;
1064
1192
goto out ;
1065
1193
}
1066
1194
@@ -1183,7 +1311,6 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
1183
1311
{
1184
1312
struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
1185
1313
struct stm32_dcmipp_data * dcmipp = pipe -> dcmipp ;
1186
- int ret ;
1187
1314
1188
1315
k_mutex_lock (& pipe -> lock , K_FOREVER );
1189
1316
@@ -1194,13 +1321,7 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
1194
1321
if (pipe -> state == STM32_DCMIPP_WAIT_FOR_BUFFER ) {
1195
1322
LOG_DBG ("Restart CPTREQ after wait for buffer" );
1196
1323
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 );
1204
1325
if (pipe -> id == DCMIPP_PIPE0 ) {
1205
1326
SET_BIT (dcmipp -> hdcmipp .Instance -> P0FCTCR , DCMIPP_P0FCTCR_CPTREQ );
1206
1327
}
0 commit comments