Commit 9b5c8d5f authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Mauro Carvalho Chehab
Browse files

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: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Reviewed-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent fc8c7238
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -277,9 +277,10 @@ void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
}
EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);

void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
			       u32 pixelformat)
{
	u32 ilo, sly;
	u32 ilo, sly, sluv;

	if (stride < 0) {
		stride = -stride;
@@ -290,9 +291,30 @@ void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)

	sly = (stride * 2) - 1;

	switch (pixelformat) {
	case V4L2_PIX_FMT_YUV420:
	case V4L2_PIX_FMT_YVU420:
		sluv = stride / 2 - 1;
		break;
	case V4L2_PIX_FMT_NV12:
		sluv = stride - 1;
		break;
	case V4L2_PIX_FMT_YUV422P:
		sluv = stride - 1;
		break;
	case V4L2_PIX_FMT_NV16:
		sluv = stride * 2 - 1;
		break;
	default:
		sluv = 0;
		break;
	}

	ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
	ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
	ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
	if (sluv)
		ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
};
EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);

+2 −1
Original line number Diff line number Diff line
@@ -412,7 +412,8 @@ static int prp_setup_channel(struct prp_priv *priv,
	if (image.pix.field == V4L2_FIELD_NONE &&
	    V4L2_FIELD_HAS_BOTH(infmt->field) &&
	    channel == priv->out_ch)
		ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline);
		ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline,
					  image.pix.pixelformat);

	ret = ipu_ic_task_idma_init(priv->ic, channel,
				    image.pix.width, image.pix.height,
+2 −1
Original line number Diff line number Diff line
@@ -512,7 +512,8 @@ static int csi_idmac_setup_channel(struct csi_priv *priv)
	if (image.pix.field == V4L2_FIELD_NONE &&
	    V4L2_FIELD_HAS_BOTH(infmt->field))
		ipu_cpmem_interlaced_scan(priv->idmac_ch,
					  image.pix.bytesperline);
					  image.pix.bytesperline,
					  image.pix.pixelformat);

	ipu_idmac_set_double_buffer(priv->idmac_ch, true);

+2 −1
Original line number Diff line number Diff line
@@ -258,7 +258,8 @@ void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride);
void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch);
void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf);
void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off);
void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride);
void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
			       u32 pixelformat);
void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id);
int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch);
void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize);