34
34
#define STM32_DCMIPP_HAS_PIXEL_PIPES
35
35
#endif
36
36
37
+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
37
38
/* Weak function declaration in order to interface with external ISP handler */
38
39
void __weak stm32_dcmipp_isp_vsync_update (DCMIPP_HandleTypeDef * hdcmipp , uint32_t Pipe )
39
40
{
@@ -53,6 +54,7 @@ int __weak stm32_dcmipp_isp_stop(void)
53
54
{
54
55
return 0 ;
55
56
}
57
+ #endif
56
58
57
59
LOG_MODULE_REGISTER (stm32_dcmipp , CONFIG_VIDEO_LOG_LEVEL );
58
60
@@ -132,6 +134,49 @@ struct stm32_dcmipp_config {
132
134
#define STM32_DCMIPP_WIDTH_MAX 4094
133
135
#define STM32_DCMIPP_HEIGHT_MAX 4094
134
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
+
135
180
/* Callback getting called for each frame written into memory */
136
181
void HAL_DCMIPP_PIPE_FrameEventCallback (DCMIPP_HandleTypeDef * hdcmipp , uint32_t Pipe )
137
182
{
@@ -169,13 +214,14 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
169
214
struct stm32_dcmipp_data * dcmipp =
170
215
CONTAINER_OF (hdcmipp , struct stm32_dcmipp_data , hdcmipp );
171
216
struct stm32_dcmipp_pipe_data * pipe = dcmipp -> pipe [Pipe ];
172
- int ret ;
173
217
218
+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
174
219
/*
175
220
* Let the external ISP handler know that a VSYNC happened a new statistics are
176
221
* thus available
177
222
*/
178
223
stm32_dcmipp_isp_vsync_update (hdcmipp , Pipe );
224
+ #endif
179
225
180
226
if (pipe -> state != STM32_DCMIPP_RUNNING ) {
181
227
return ;
@@ -205,17 +251,8 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
205
251
return ;
206
252
}
207
253
208
- /*
209
- * TODO - we only support 1 buffer formats for the time being, setting of
210
- * MEMORY_ADDRESS_1 and MEMORY_ADDRESS_2 required depending on the pixelformat
211
- * for Pipe1
212
- */
213
- ret = HAL_DCMIPP_PIPE_SetMemoryAddress (& dcmipp -> hdcmipp , Pipe , DCMIPP_MEMORY_ADDRESS_0 ,
214
- (uint32_t )pipe -> next -> buffer );
215
- if (ret != HAL_OK ) {
216
- LOG_ERR ("Failed to update memory address" );
217
- return ;
218
- }
254
+ /* Update buffer address */
255
+ stm32_dcmipp_set_next_buffer_addr (pipe );
219
256
}
220
257
221
258
#if defined(STM32_DCMIPP_HAS_CSI )
@@ -439,7 +476,13 @@ static const struct stm32_dcmipp_mapping {
439
476
PIXEL_PIPE_FMT (ABGR32 , ARGB8888 , 0 , (BIT (1 ) | BIT (2 ))),
440
477
PIXEL_PIPE_FMT (RGBA32 , ARGB8888 , 1 , (BIT (1 ) | BIT (2 ))),
441
478
PIXEL_PIPE_FMT (BGRA32 , RGBA888 , 0 , (BIT (1 ) | BIT (2 ))),
442
- /* 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 )),
443
486
#endif
444
487
};
445
488
@@ -460,6 +503,9 @@ static const struct stm32_dcmipp_mapping {
460
503
((fmt) == VIDEO_PIX_FMT_GREY || \
461
504
(fmt) == VIDEO_PIX_FMT_YUYV || (fmt) == VIDEO_PIX_FMT_YVYU || \
462
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 || \
463
509
(fmt) == VIDEO_PIX_FMT_XYUV32) ? VIDEO_COLORSPACE_YUV : \
464
510
\
465
511
VIDEO_COLORSPACE_RAW)
@@ -855,6 +901,98 @@ static int stm32_dcmipp_set_yuv_conversion(struct stm32_dcmipp_pipe_data *pipe,
855
901
}
856
902
#endif
857
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
+
858
996
static int stm32_dcmipp_stream_enable (const struct device * dev )
859
997
{
860
998
struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
@@ -942,7 +1080,16 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
942
1080
pipe_cfg .FrameRate = DCMIPP_FRAME_RATE_ALL ;
943
1081
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
944
1082
if (pipe -> id == DCMIPP_PIPE1 || pipe -> id == DCMIPP_PIPE2 ) {
945
- 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
+ }
946
1093
pipe_cfg .PixelPackerFormat = mapping -> pixels .dcmipp_format ;
947
1094
}
948
1095
#endif
@@ -1029,34 +1176,18 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
1029
1176
goto out ;
1030
1177
}
1031
1178
}
1032
- #endif
1033
1179
1034
1180
/* Initialize the external ISP handling stack */
1035
1181
ret = stm32_dcmipp_isp_init (& dcmipp -> hdcmipp , config -> source_dev );
1036
1182
if (ret < 0 ) {
1037
1183
goto out ;
1038
1184
}
1185
+ #endif
1039
1186
1040
1187
/* Enable the DCMIPP Pipeline */
1041
- if (config -> bus_type == VIDEO_BUS_TYPE_PARALLEL ) {
1042
- ret = HAL_DCMIPP_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id ,
1043
- (uint32_t )pipe -> next -> buffer , DCMIPP_MODE_CONTINUOUS );
1044
- }
1045
- #if defined(STM32_DCMIPP_HAS_CSI )
1046
- else if (config -> bus_type == VIDEO_BUS_TYPE_CSI2_DPHY ) {
1047
- ret = HAL_DCMIPP_CSI_PIPE_Start (& dcmipp -> hdcmipp , pipe -> id , DCMIPP_VIRTUAL_CHANNEL0 ,
1048
- (uint32_t )pipe -> next -> buffer ,
1049
- DCMIPP_MODE_CONTINUOUS );
1050
- }
1051
- #endif
1052
- else {
1053
- LOG_ERR ("Invalid bus_type" );
1054
- ret = - EINVAL ;
1055
- goto out ;
1056
- }
1057
- if (ret != HAL_OK ) {
1188
+ ret = stm32_dcmipp_start_pipeline (dev , pipe );
1189
+ if (ret < 0 ) {
1058
1190
LOG_ERR ("Failed to start the pipeline" );
1059
- ret = - EIO ;
1060
1191
goto out ;
1061
1192
}
1062
1193
@@ -1082,11 +1213,13 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
1082
1213
}
1083
1214
}
1084
1215
1216
+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
1085
1217
/* Start the external ISP handling */
1086
1218
ret = stm32_dcmipp_isp_start ();
1087
1219
if (ret < 0 ) {
1088
1220
goto out ;
1089
1221
}
1222
+ #endif
1090
1223
1091
1224
pipe -> state = STM32_DCMIPP_RUNNING ;
1092
1225
pipe -> is_streaming = true;
@@ -1112,11 +1245,13 @@ static int stm32_dcmipp_stream_disable(const struct device *dev)
1112
1245
goto out ;
1113
1246
}
1114
1247
1248
+ #if defined(STM32_DCMIPP_HAS_PIXEL_PIPES )
1115
1249
/* Stop the external ISP handling */
1116
1250
ret = stm32_dcmipp_isp_stop ();
1117
1251
if (ret < 0 ) {
1118
1252
goto out ;
1119
1253
}
1254
+ #endif
1120
1255
1121
1256
/* Disable the DCMIPP Pipeline */
1122
1257
if (config -> bus_type == VIDEO_BUS_TYPE_PARALLEL ) {
@@ -1175,7 +1310,6 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
1175
1310
{
1176
1311
struct stm32_dcmipp_pipe_data * pipe = dev -> data ;
1177
1312
struct stm32_dcmipp_data * dcmipp = pipe -> dcmipp ;
1178
- int ret ;
1179
1313
1180
1314
k_mutex_lock (& pipe -> lock , K_FOREVER );
1181
1315
@@ -1186,13 +1320,7 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
1186
1320
if (pipe -> state == STM32_DCMIPP_WAIT_FOR_BUFFER ) {
1187
1321
LOG_DBG ("Restart CPTREQ after wait for buffer" );
1188
1322
pipe -> next = vbuf ;
1189
- ret = HAL_DCMIPP_PIPE_SetMemoryAddress (& dcmipp -> hdcmipp , pipe -> id ,
1190
- DCMIPP_MEMORY_ADDRESS_0 ,
1191
- (uint32_t )pipe -> next -> buffer );
1192
- if (ret != HAL_OK ) {
1193
- LOG_ERR ("Failed to update memory address" );
1194
- return - EIO ;
1195
- }
1323
+ stm32_dcmipp_set_next_buffer_addr (pipe );
1196
1324
if (pipe -> id == DCMIPP_PIPE0 ) {
1197
1325
SET_BIT (dcmipp -> hdcmipp .Instance -> P0FCTCR , DCMIPP_P0FCTCR_CPTREQ );
1198
1326
}
0 commit comments