diff options
author | Steve Longerbeam <slongerbeam@gmail.com> | 2019-01-09 13:30:06 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2019-01-16 14:12:20 -0500 |
commit | 9b5c8d5ffb20cc4f4b1476cb1ad57e0f9b934788 (patch) | |
tree | eaeabe3d984667fe020a926f8f7e33d8b520127d | |
parent | fc8c723852380b0f4349bb06cf553a6bba47462e (diff) |
media: gpu: ipu-v3: Add planar support to interlaced scan
To support interlaced scan with planar formats, cpmem SLUV must
be programmed with the correct chroma line stride. For full and
partial planar 4:2:2 (YUV422P, NV16), chroma line stride must
be doubled. For full and partial planar 4:2:0 (YUV420, YVU420, NV12),
chroma line stride must _not_ be doubled, since a single chroma line
is shared by two luma lines.
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-cpmem.c | 26 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-ic-prpencvf.c | 3 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media-csi.c | 3 | ||||
-rw-r--r-- | include/video/imx-ipu-v3.h | 3 |
4 files changed, 30 insertions, 5 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index 163fadb8a33a..d047a6867c59 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c | |||
@@ -277,9 +277,10 @@ void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off) | |||
277 | } | 277 | } |
278 | EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset); | 278 | EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset); |
279 | 279 | ||
280 | void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride) | 280 | void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride, |
281 | u32 pixelformat) | ||
281 | { | 282 | { |
282 | u32 ilo, sly; | 283 | u32 ilo, sly, sluv; |
283 | 284 | ||
284 | if (stride < 0) { | 285 | if (stride < 0) { |
285 | stride = -stride; | 286 | stride = -stride; |
@@ -290,9 +291,30 @@ void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride) | |||
290 | 291 | ||
291 | sly = (stride * 2) - 1; | 292 | sly = (stride * 2) - 1; |
292 | 293 | ||
294 | switch (pixelformat) { | ||
295 | case V4L2_PIX_FMT_YUV420: | ||
296 | case V4L2_PIX_FMT_YVU420: | ||
297 | sluv = stride / 2 - 1; | ||
298 | break; | ||
299 | case V4L2_PIX_FMT_NV12: | ||
300 | sluv = stride - 1; | ||
301 | break; | ||
302 | case V4L2_PIX_FMT_YUV422P: | ||
303 | sluv = stride - 1; | ||
304 | break; | ||
305 | case V4L2_PIX_FMT_NV16: | ||
306 | sluv = stride * 2 - 1; | ||
307 | break; | ||
308 | default: | ||
309 | sluv = 0; | ||
310 | break; | ||
311 | } | ||
312 | |||
293 | ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1); | 313 | ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1); |
294 | ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo); | 314 | ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo); |
295 | ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly); | 315 | ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly); |
316 | if (sluv) | ||
317 | ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv); | ||
296 | }; | 318 | }; |
297 | EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan); | 319 | EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan); |
298 | 320 | ||
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c b/drivers/staging/media/imx/imx-ic-prpencvf.c index 28f41caba05d..af7224846bd5 100644 --- a/drivers/staging/media/imx/imx-ic-prpencvf.c +++ b/drivers/staging/media/imx/imx-ic-prpencvf.c | |||
@@ -412,7 +412,8 @@ static int prp_setup_channel(struct prp_priv *priv, | |||
412 | if (image.pix.field == V4L2_FIELD_NONE && | 412 | if (image.pix.field == V4L2_FIELD_NONE && |
413 | V4L2_FIELD_HAS_BOTH(infmt->field) && | 413 | V4L2_FIELD_HAS_BOTH(infmt->field) && |
414 | channel == priv->out_ch) | 414 | channel == priv->out_ch) |
415 | ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline); | 415 | ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline, |
416 | image.pix.pixelformat); | ||
416 | 417 | ||
417 | ret = ipu_ic_task_idma_init(priv->ic, channel, | 418 | ret = ipu_ic_task_idma_init(priv->ic, channel, |
418 | image.pix.width, image.pix.height, | 419 | image.pix.width, image.pix.height, |
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index c2a8d9cd31b7..da4808348845 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c | |||
@@ -512,7 +512,8 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) | |||
512 | if (image.pix.field == V4L2_FIELD_NONE && | 512 | if (image.pix.field == V4L2_FIELD_NONE && |
513 | V4L2_FIELD_HAS_BOTH(infmt->field)) | 513 | V4L2_FIELD_HAS_BOTH(infmt->field)) |
514 | ipu_cpmem_interlaced_scan(priv->idmac_ch, | 514 | ipu_cpmem_interlaced_scan(priv->idmac_ch, |
515 | image.pix.bytesperline); | 515 | image.pix.bytesperline, |
516 | image.pix.pixelformat); | ||
516 | 517 | ||
517 | ipu_idmac_set_double_buffer(priv->idmac_ch, true); | 518 | ipu_idmac_set_double_buffer(priv->idmac_ch, true); |
518 | 519 | ||
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index bbc8481f567d..c887f4bee5f8 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h | |||
@@ -258,7 +258,8 @@ void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride); | |||
258 | void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch); | 258 | void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch); |
259 | void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf); | 259 | void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf); |
260 | void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off); | 260 | void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off); |
261 | void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride); | 261 | void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride, |
262 | u32 pixelformat); | ||
262 | void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id); | 263 | void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id); |
263 | int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch); | 264 | int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch); |
264 | void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize); | 265 | void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize); |