[PATCH 07/72] gpu: ipu-v3: Add ipu_dp_set_chroma_key()
Philipp Zabel
p.zabel at pengutronix.de
Mon Nov 3 04:31:22 PST 2014
Am Freitag, den 31.10.2014, 15:53 -0700 schrieb Steve Longerbeam:
> Adds the function ipu_dp_set_chroma_key(), which sets up a color key
> value for a DP foreground plane.
>
> ipu_dp_set_chroma_key() accepts a color key value in RGB24 format.
> If the combiner unit colorspace is YUV, the key must be converted
> to YUV444, using the same CSC coefficients as programmed in the DP.
> So pull out the CSC coefficients from ipu_dp_csc_init() to make
> them available to rgb24_to_yuv444() that converts to color key.
What is the rationale to disallow specifying the color key in YUV?
Regardless of the new feature, I like the move to static const
coefficient tables. Maybe split that into two patches?
regards
Philipp
> Signed-off-by: Steve Longerbeam <steve_longerbeam at mentor.com>
> ---
> drivers/gpu/ipu-v3/ipu-dp.c | 121 ++++++++++++++++++++++++++++++++++++-------
> include/video/imx-ipu-v3.h | 1 +
> 2 files changed, 103 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
> index 98686ed..e4026f1 100644
> --- a/drivers/gpu/ipu-v3/ipu-dp.c
> +++ b/drivers/gpu/ipu-v3/ipu-dp.c
> @@ -84,6 +84,52 @@ static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
> return container_of(dp, struct ipu_flow, background);
> }
>
> +static const int rgb2yuv_coeff[5][3] = {
> + { 0x0099, 0x012d, 0x003a },
> + { 0x03a9, 0x0356, 0x0100 },
> + { 0x0100, 0x0329, 0x03d6 },
> + { 0x0000, 0x0200, 0x0200 }, /* B0, B1, B2 */
> + { 0x2, 0x2, 0x2 }, /* S0, S1, S2 */
> +};
> +
> +static const int yuv2rgb_coeff[5][3] = {
> + { 0x0095, 0x0000, 0x00cc },
> + { 0x0095, 0x03ce, 0x0398 },
> + { 0x0095, 0x00ff, 0x0000 },
> + { 0x3e42, 0x010a, 0x3dd6 }, /* B0,B1,B2 */
> + { 0x1, 0x1, 0x1 }, /* S0,S1,S2 */
> +};
> +
> +/*
> + * This is used to convert an RGB24 color key to YUV444, using
> + * the same CSC coefficients as programmed in the DP.
> + */
> +static u32 rgb24_to_yuv444(u32 rgb24)
> +{
> + u32 red, green, blue;
> + int i, c[3];
> +
> + red = (rgb24 >> 16) & 0xff;
> + green = (rgb24 >> 8) & 0xff;
> + blue = (rgb24 >> 0) & 0xff;
> +
> + for (i = 0; i < 3; i++) {
> + c[i] = red * rgb2yuv_coeff[i][0];
> + c[i] += green * rgb2yuv_coeff[i][1];
> + c[i] += blue * rgb2yuv_coeff[i][2];
> + c[i] /= 16;
> + c[i] += rgb2yuv_coeff[3][i] * 4;
> + c[i] += 8;
> + c[i] /= 16;
> + if (c[i] < 0)
> + c[i] = 0;
> + if (c[i] > 255)
> + c[i] = 255;
> + }
> +
> + return (c[0] << 16) | (c[1] << 8) | c[2];
> +}
> +
> int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
> u8 alpha, bool bg_chan)
> {
> @@ -120,6 +166,48 @@ int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
> }
> EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
>
> +/*
> + * The input color_key must always be RGB24. It will be converted to
> + * YUV444 if the pixel format to the Combining unit is YUV space.
> + */
> +int ipu_dp_set_chroma_key(struct ipu_dp *dp, bool enable, u32 color_key)
> +{
> + struct ipu_flow *flow = to_flow(dp);
> + struct ipu_dp_priv *priv = flow->priv;
> + enum ipu_color_space combiner_cs;
> + u32 reg;
> +
> + mutex_lock(&priv->mutex);
> +
> + if (flow->foreground.in_cs == flow->background.in_cs)
> + combiner_cs = flow->foreground.in_cs;
> + else
> + combiner_cs = flow->out_cs;
> +
> + if (combiner_cs == IPUV3_COLORSPACE_YUV)
> + color_key = rgb24_to_yuv444(color_key);
> +
> + color_key &= 0x00ffffff;
> +
> + if (enable) {
> + reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & ~0x00FFFFFFL;
> + writel(reg | color_key, flow->base + DP_GRAPH_WIND_CTRL);
> +
> + reg = readl(flow->base + DP_COM_CONF);
> + writel(reg | DP_COM_CONF_GWCKE, flow->base + DP_COM_CONF);
> + } else {
> + reg = readl(flow->base + DP_COM_CONF);
> + writel(reg & ~DP_COM_CONF_GWCKE, flow->base + DP_COM_CONF);
> + }
> +
> + ipu_srm_dp_sync_update(priv->ipu);
> +
> + mutex_unlock(&priv->mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(ipu_dp_set_chroma_key);
> +
> int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
> {
> struct ipu_flow *flow = to_flow(dp);
> @@ -138,6 +226,7 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
> enum ipu_color_space out,
> u32 place)
> {
> + const int (*c)[3];
> u32 reg;
>
> reg = readl(flow->base + DP_COM_CONF);
> @@ -148,25 +237,19 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
> return;
> }
>
> - if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
> - writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
> - writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
> - writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
> - writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
> - writel(0x3d6 | (0x0000 << 16) | (2 << 30),
> - flow->base + DP_CSC_0);
> - writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
> - flow->base + DP_CSC_1);
> - } else {
> - writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
> - writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
> - writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
> - writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
> - writel(0x000 | (0x3e42 << 16) | (1 << 30),
> - flow->base + DP_CSC_0);
> - writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
> - flow->base + DP_CSC_1);
> - }
> + if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV)
> + c = rgb2yuv_coeff;
> + else
> + c = yuv2rgb_coeff;
> +
> + writel(c[0][0] | (c[0][1] << 16), flow->base + DP_CSC_A_0);
> + writel(c[0][2] | (c[1][0] << 16), flow->base + DP_CSC_A_1);
> + writel(c[1][1] | (c[1][2] << 16), flow->base + DP_CSC_A_2);
> + writel(c[2][0] | (c[2][1] << 16), flow->base + DP_CSC_A_3);
> + writel(c[2][2] | (c[3][0] << 16) | (c[4][0] << 30),
> + flow->base + DP_CSC_0);
> + writel(c[3][1] | (c[4][1] << 14) | (c[3][2] << 16) | (c[4][2] << 30),
> + flow->base + DP_CSC_1);
>
> reg |= place;
>
> diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
> index 03cda50..e878343 100644
> --- a/include/video/imx-ipu-v3.h
> +++ b/include/video/imx-ipu-v3.h
> @@ -273,6 +273,7 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
> int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
> int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
> bool bg_chan);
> +int ipu_dp_set_chroma_key(struct ipu_dp *dp, bool enable, u32 color_key);
>
> /*
> * IPU CMOS Sensor Interface (csi) functions
More information about the dri-devel
mailing list