From patchwork Fri Oct 31 22:53:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Longerbeam X-Patchwork-Id: 5207381 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9C83C9F318 for ; Fri, 31 Oct 2014 23:56:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9384B2014A for ; Fri, 31 Oct 2014 23:56:55 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 8646520120 for ; Fri, 31 Oct 2014 23:56:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 30BB16E855; Fri, 31 Oct 2014 16:56:39 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pd0-f169.google.com (mail-pd0-f169.google.com [209.85.192.169]) by gabe.freedesktop.org (Postfix) with ESMTP id D8BBE6E84A for ; Fri, 31 Oct 2014 15:56:53 -0700 (PDT) Received: by mail-pd0-f169.google.com with SMTP id y10so8110941pdj.28 for ; Fri, 31 Oct 2014 15:56:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=eNJwLZoJoAbgdbbcoQrBt7exqjlhWKifbED+KwI2oTQ=; b=IMvjL9YqG5SPzmRnXf30JlBpGQDbXmB5S3uwTFrKZz087b+yCWYx13fYCgecyAutGb 42Qo5T+5GXsXU/AgxSRLDC7UIVVaXUJ8rIjFZFSMeuW/nGng0Q6ESWRMnGG6nfmFBHF0 iqzpQ/xdOpHAtY7F1+EvuSnGjhQTGXmHnW8iLrjb8zO8tW7pPelDyaYkd3vXt75CFrgu DYSD1vIPBCfQqIzWPfEUtyep+NyWlGFk9zFGkUONI0yKuonqgjUrbeFhlWR3BmwyfFa0 Jj6mp/9bkupu9SdF7KA8WUv3XHhc0at6yn0W+/Hx7VIx79JA0phvx9w66KoFIWmAMFAF rHFg== X-Received: by 10.66.97.39 with SMTP id dx7mr27576254pab.65.1414796213605; Fri, 31 Oct 2014 15:56:53 -0700 (PDT) Received: from mothership.mgc.mentorg.com (c-50-152-159-227.hsd1.ca.comcast.net. [50.152.159.227]) by mx.google.com with ESMTPSA id ev8sm10870656pdb.28.2014.10.31.15.56.52 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 31 Oct 2014 15:56:53 -0700 (PDT) From: Steve Longerbeam X-Google-Original-From: Steve Longerbeam To: dri-devel@lists.freedesktop.org Subject: [PATCH 07/72] gpu: ipu-v3: Add ipu_dp_set_chroma_key() Date: Fri, 31 Oct 2014 15:53:50 -0700 Message-Id: <1414796095-10107-8-git-send-email-steve_longerbeam@mentor.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1414796095-10107-1-git-send-email-steve_longerbeam@mentor.com> References: <1414796095-10107-1-git-send-email-steve_longerbeam@mentor.com> X-Mailman-Approved-At: Fri, 31 Oct 2014 16:56:31 -0700 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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. Signed-off-by: Steve Longerbeam --- 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