Skip to content

Commit 5c21020

Browse files
author
Alain Volmat
committed
Merge branch 'pr-dcmipp-planar-addition' into HEAD
2 parents 1cb0b6a + 85c17b2 commit 5c21020

File tree

2 files changed

+367
-41
lines changed

2 files changed

+367
-41
lines changed

drivers/video/video_stm32_dcmipp.c

Lines changed: 169 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define STM32_DCMIPP_HAS_PIXEL_PIPES
3535
#endif
3636

37+
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
3738
/* Weak function declaration in order to interface with external ISP handler */
3839
void __weak stm32_dcmipp_isp_vsync_update(DCMIPP_HandleTypeDef *hdcmipp, uint32_t Pipe)
3940
{
@@ -53,6 +54,7 @@ int __weak stm32_dcmipp_isp_stop(void)
5354
{
5455
return 0;
5556
}
57+
#endif
5658

5759
LOG_MODULE_REGISTER(stm32_dcmipp, CONFIG_VIDEO_LOG_LEVEL);
5860

@@ -132,6 +134,49 @@ struct stm32_dcmipp_config {
132134
#define STM32_DCMIPP_WIDTH_MAX 4094
133135
#define STM32_DCMIPP_HEIGHT_MAX 4094
134136

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+
135180
/* Callback getting called for each frame written into memory */
136181
void HAL_DCMIPP_PIPE_FrameEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t Pipe)
137182
{
@@ -169,13 +214,14 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
169214
struct stm32_dcmipp_data *dcmipp =
170215
CONTAINER_OF(hdcmipp, struct stm32_dcmipp_data, hdcmipp);
171216
struct stm32_dcmipp_pipe_data *pipe = dcmipp->pipe[Pipe];
172-
int ret;
173217

218+
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
174219
/*
175220
* Let the external ISP handler know that a VSYNC happened a new statistics are
176221
* thus available
177222
*/
178223
stm32_dcmipp_isp_vsync_update(hdcmipp, Pipe);
224+
#endif
179225

180226
if (pipe->state != STM32_DCMIPP_RUNNING) {
181227
return;
@@ -205,17 +251,8 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
205251
return;
206252
}
207253

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);
219256
}
220257

221258
#if defined(STM32_DCMIPP_HAS_CSI)
@@ -439,7 +476,13 @@ static const struct stm32_dcmipp_mapping {
439476
PIXEL_PIPE_FMT(ABGR32, ARGB8888, 0, (BIT(1) | BIT(2))),
440477
PIXEL_PIPE_FMT(RGBA32, ARGB8888, 1, (BIT(1) | BIT(2))),
441478
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)),
443486
#endif
444487
};
445488

@@ -460,6 +503,9 @@ static const struct stm32_dcmipp_mapping {
460503
((fmt) == VIDEO_PIX_FMT_GREY || \
461504
(fmt) == VIDEO_PIX_FMT_YUYV || (fmt) == VIDEO_PIX_FMT_YVYU || \
462505
(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 || \
463509
(fmt) == VIDEO_PIX_FMT_XYUV32) ? VIDEO_COLORSPACE_YUV : \
464510
\
465511
VIDEO_COLORSPACE_RAW)
@@ -855,6 +901,98 @@ static int stm32_dcmipp_set_yuv_conversion(struct stm32_dcmipp_pipe_data *pipe,
855901
}
856902
#endif
857903

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+
858996
static int stm32_dcmipp_stream_enable(const struct device *dev)
859997
{
860998
struct stm32_dcmipp_pipe_data *pipe = dev->data;
@@ -942,7 +1080,16 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
9421080
pipe_cfg.FrameRate = DCMIPP_FRAME_RATE_ALL;
9431081
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
9441082
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+
}
9461093
pipe_cfg.PixelPackerFormat = mapping->pixels.dcmipp_format;
9471094
}
9481095
#endif
@@ -1029,34 +1176,18 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
10291176
goto out;
10301177
}
10311178
}
1032-
#endif
10331179

10341180
/* Initialize the external ISP handling stack */
10351181
ret = stm32_dcmipp_isp_init(&dcmipp->hdcmipp, config->source_dev);
10361182
if (ret < 0) {
10371183
goto out;
10381184
}
1185+
#endif
10391186

10401187
/* 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) {
10581190
LOG_ERR("Failed to start the pipeline");
1059-
ret = -EIO;
10601191
goto out;
10611192
}
10621193

@@ -1082,11 +1213,13 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
10821213
}
10831214
}
10841215

1216+
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
10851217
/* Start the external ISP handling */
10861218
ret = stm32_dcmipp_isp_start();
10871219
if (ret < 0) {
10881220
goto out;
10891221
}
1222+
#endif
10901223

10911224
pipe->state = STM32_DCMIPP_RUNNING;
10921225
pipe->is_streaming = true;
@@ -1112,11 +1245,13 @@ static int stm32_dcmipp_stream_disable(const struct device *dev)
11121245
goto out;
11131246
}
11141247

1248+
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
11151249
/* Stop the external ISP handling */
11161250
ret = stm32_dcmipp_isp_stop();
11171251
if (ret < 0) {
11181252
goto out;
11191253
}
1254+
#endif
11201255

11211256
/* Disable the DCMIPP Pipeline */
11221257
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
11751310
{
11761311
struct stm32_dcmipp_pipe_data *pipe = dev->data;
11771312
struct stm32_dcmipp_data *dcmipp = pipe->dcmipp;
1178-
int ret;
11791313

11801314
k_mutex_lock(&pipe->lock, K_FOREVER);
11811315

@@ -1186,13 +1320,7 @@ static int stm32_dcmipp_enqueue(const struct device *dev, struct video_buffer *v
11861320
if (pipe->state == STM32_DCMIPP_WAIT_FOR_BUFFER) {
11871321
LOG_DBG("Restart CPTREQ after wait for buffer");
11881322
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);
11961324
if (pipe->id == DCMIPP_PIPE0) {
11971325
SET_BIT(dcmipp->hdcmipp.Instance->P0FCTCR, DCMIPP_P0FCTCR_CPTREQ);
11981326
}

0 commit comments

Comments
 (0)