From f208b26e61df411cf0bee413bee57ff434e8b38a Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Tue, 21 May 2019 18:03:14 -0700 Subject: gpu: ipu-v3: ipu-ic: Fully describe colorspace conversions Only providing the input and output RGB/YUV space to the IC task init functions is not sufficient. To fully characterize a colorspace conversion, the Y'CbCr encoding standard, and quantization also need to be specified. Define a 'struct ipu_ic_colorspace' that includes all the above. This allows to actually enforce the fact that the IC: - can only encode to/from YUV and RGB full range. A follow-up patch will remove this restriction. - can only encode using BT.601 standard. A follow-up patch will add Rec.709 encoding support. The determination of the CSC coefficients based on the input/output 'struct ipu_ic_colorspace' are moved to a new exported function ipu_ic_calc_csc(), and 'struct ic_csc_params' is exported as 'struct ipu_ic_csc_params'. ipu_ic_calc_csc() fills a 'struct ipu_ic_csc' with the input/output 'struct ipu_ic_colorspace' and the calculated 'struct ic_csc_params' from those input/output colorspaces. The functions ipu_ic_task_init(_rsc)() now take a filled 'struct ipu_ic_csc'. The existing CSC coefficient tables and ipu_ic_calc_csc() are moved to a new module ipu-ic-csc.c. This is in preparation for adding more coefficient tables for limited range quantization and more encoding standards. The existing ycbcr2rgb and inverse rgb2ycbcr tables defined the BT.601 Y'CbCr encoding coefficients. The rgb2ycbcr table specifically described the BT.601 encoding from full range RGB to full range YUV. Table comments have been added in ipu-ic-csc.c to make this more clear. The ycbcr2rgb inverse table described encoding YUV limited range to RGB full range. To be consistent with the rgb2ycbcr table, this table is converted to YUV full range to RGB full range, and the comments are expanded in ipu-ic-csc.c. The ic_csc_rgb2rgb table was just an identity matrix, so it is renamed 'identity' in ipu-ic-csc.c. Signed-off-by: Steve Longerbeam [p.zabel@pengutronix.de: removed a superfluous blank line] Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-image-convert.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/ipu-v3/ipu-image-convert.c') diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c index 36e88434513a..d2457fde25fa 100644 --- a/drivers/gpu/ipu-v3/ipu-image-convert.c +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c @@ -146,6 +146,7 @@ struct ipu_image_convert_ctx { /* Source/destination image data and rotation mode */ struct ipu_image_convert_image in; struct ipu_image_convert_image out; + struct ipu_ic_csc csc; enum ipu_rotate_mode rot_mode; u32 downsize_coeff_h; u32 downsize_coeff_v; @@ -1308,7 +1309,6 @@ static int convert_start(struct ipu_image_convert_run *run, unsigned int tile) struct ipu_image_convert_priv *priv = chan->priv; struct ipu_image_convert_image *s_image = &ctx->in; struct ipu_image_convert_image *d_image = &ctx->out; - enum ipu_color_space src_cs, dest_cs; unsigned int dst_tile = ctx->out_tile_map[tile]; unsigned int dest_width, dest_height; unsigned int col, row; @@ -1318,9 +1318,6 @@ static int convert_start(struct ipu_image_convert_run *run, unsigned int tile) dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n", __func__, chan->ic_task, ctx, run, tile, dst_tile); - src_cs = ipu_pixelformat_to_colorspace(s_image->fmt->fourcc); - dest_cs = ipu_pixelformat_to_colorspace(d_image->fmt->fourcc); - if (ipu_rot_mode_is_irt(ctx->rot_mode)) { /* swap width/height for resizer */ dest_width = d_image->tile[dst_tile].height; @@ -1343,13 +1340,12 @@ static int convert_start(struct ipu_image_convert_run *run, unsigned int tile) s_image->tile[tile].height, dest_width, dest_height, rsc); /* setup the IC resizer and CSC */ - ret = ipu_ic_task_init_rsc(chan->ic, - s_image->tile[tile].width, - s_image->tile[tile].height, - dest_width, - dest_height, - src_cs, dest_cs, - rsc); + ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc, + s_image->tile[tile].width, + s_image->tile[tile].height, + dest_width, + dest_height, + rsc); if (ret) { dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret); return ret; @@ -2049,6 +2045,16 @@ ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task, calc_tile_resize_coefficients(ctx); + ret = ipu_ic_calc_csc(&ctx->csc, + s_image->base.pix.ycbcr_enc, + s_image->base.pix.quantization, + ipu_pixelformat_to_colorspace(s_image->fmt->fourcc), + d_image->base.pix.ycbcr_enc, + d_image->base.pix.quantization, + ipu_pixelformat_to_colorspace(d_image->fmt->fourcc)); + if (ret) + goto out_free; + dump_format(ctx, s_image); dump_format(ctx, d_image); -- cgit v1.2.3 From fee77829083ad70845bd650f3c84c5900c5abae1 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Thu, 13 Jun 2019 18:02:55 -0700 Subject: gpu: ipu-v3: image-convert: Enable double write reduction For the write channels with 4:2:0 subsampled YUV formats, avoid chroma overdraw by only writing chroma for even lines (skip odd chroma rows). This reduces necessary write memory bandwidth by at least 25% (more with rotation enabled). Signed-off-by: Steve Longerbeam Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-image-convert.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/ipu-v3/ipu-image-convert.c') diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c index d2457fde25fa..61643382bbde 100644 --- a/drivers/gpu/ipu-v3/ipu-image-convert.c +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c @@ -1280,6 +1280,15 @@ static void init_idmac_channel(struct ipu_image_convert_ctx *ctx, if (rot_mode) ipu_cpmem_set_rotation(channel, rot_mode); + /* + * Skip writing U and V components to odd rows in the output + * channels for planar 4:2:0. + */ + if ((channel == chan->out_chan || + channel == chan->rotation_out_chan) && + image->fmt->planar && image->fmt->uv_height_dec == 2) + ipu_cpmem_skip_odd_chroma_rows(channel); + if (channel == chan->rotation_in_chan || channel == chan->rotation_out_chan) { burst_size = 8; -- cgit v1.2.3