Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp4125484imj; Tue, 19 Feb 2019 16:06:50 -0800 (PST) X-Google-Smtp-Source: AHgI3IavY1NS7qzGfwz6lYDKTtNpmZ+7lRY4+EHdL5Ly5Ec6Ft681iS6gw2+cZaI5ian3coqeieL X-Received: by 2002:a63:6984:: with SMTP id e126mr26817325pgc.143.1550621210582; Tue, 19 Feb 2019 16:06:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550621210; cv=none; d=google.com; s=arc-20160816; b=B9EIwGjoRqVyxGvx8xMybvj2Hi5M5JA7Rk64opC1tJFygxBpI8d4/5Xw+u6SZut53H F5CUtnJOhPD9GWAOb6FCmu2sosT04BqxVJVP3MhjgkS1cSrtAxaKGPbQLgrC6Wqrv4/2 8R+e8vR6JPlJngHGnidssDPeJoR5Nkz7WrF/8QUBst1w89hPW9VMPiQGoWhM6g6BUiMz 6hPUNEJcetybEM08a0V9YhYyLgKQX8+yQ8IcXZzIT/foGh33/FgV5+leF0Qu+3kDjiPN +Ck23I1Gt2Qo8nn6e6Yq+y88zxk5M1jizXtww0nLX5p4YixvtSFysTVivpn+Xa0pbzD5 m0cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=YMJ6Z/OI+JwxOvQ/XgxaTgw9XsPGx3EOUms81JPt9UA=; b=VNjfKI4Zm76Bt0hrJ5B5TYYSioE6FDU5GhjVUh3eQWCr5YnmQV68XHcjGrWLA7z/Px GLfFbPvjr3XLyQYJ1C3pHkRcKj1CVcqWaBHzFytw1wpf58Ckff+aiJO7j7SpUm3TgnA8 opQerdq6rmWBAKql07l5NvRzcXzGlJDy1XJyriAklt80DkW1no6EC3xzbQuAbv6vFvw2 l1Se+AWYkEEickcNU+V5FaTF+dsfoXZ2trP+czdM2q78zTzKbotG7YZlBRSrfB9ZaTvU zTFHsO3zjYq7WPMo7+xqBku5Np9rJVrh9MNR03zUT/LAxujZqUApxDPbSr6C1QqvQpRg peVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=iveaGDog; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o5si9197428pfi.22.2019.02.19.16.06.35; Tue, 19 Feb 2019 16:06:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=iveaGDog; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730124AbfBTAFm (ORCPT + 99 others); Tue, 19 Feb 2019 19:05:42 -0500 Received: from mail-pl1-f194.google.com ([209.85.214.194]:38857 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730062AbfBTAFk (ORCPT ); Tue, 19 Feb 2019 19:05:40 -0500 Received: by mail-pl1-f194.google.com with SMTP id e5so11225915plb.5; Tue, 19 Feb 2019 16:05:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YMJ6Z/OI+JwxOvQ/XgxaTgw9XsPGx3EOUms81JPt9UA=; b=iveaGDogIOgbGfnhozf96pLKX2ZZKTeoy5C6+l/I3uCjGR+qkmQDoSXLK6F3+pSwPB 2Y8BOyJLVcEOb2QGUTc2jmE8mL9v99zuYNNo4j2PDT8rj1HSdJl8A+Rvkw+1wTOM4QY4 4R0t9ugIHa6fbMUcLUH/tg+JZ47woGure0PxUyld8ZM3UNsI3dKSvxzc0xy9oI9eqjIz mx83Iohq2hAY2dp6apj5QsuuuQnhPNTpFMW4dGvWYKKcT9e/J3D4rpDtqMmQpm2NQoy7 FF6CsZk0jVbKvTTA6Otk6H2c8b2nitrI61P98b7Cm3SIfJ+GANdgrM/TgY90fnv59xU+ w66w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YMJ6Z/OI+JwxOvQ/XgxaTgw9XsPGx3EOUms81JPt9UA=; b=j9xlsdFI07V1QGI9KcPxHO7NQXVA31W3VsDkAsKkDN4hE/LPAJ85QmweI6OAjcr94t bV6fdN/xGPPssTmSRn2CFvg2Q2zCtPpNjuEXtqS2oFLcG0ZwM5pR7lx8FYNPx/6yFC+L xYM1Z+YbzsKKUFupXhdBIHKqj3Ec644S76pTJRYeT2hJmc27kBz8BDOGk/LIR+EX2Nv6 qmN1/bT8ZWLu4xYCsW4uWaTxYE2U9hFWQJOuDn4ub4rKSiAsmbEXSJm8BYRtq5mWG2qx yzys6kvfEZ9wGQgQmYlyHMoBoesErtYRyeLjU0G7vwDuDmdf0MTGbQgVf2v6THx9RNHc 9PWw== X-Gm-Message-State: AHQUAubs1NoTGiYItZG/UKuFkmnpW2hk/rcnkm5uhFLBuhDbeEVilyLm cQIv00Mczh5Ob35EJ0xrjIxx8BKt X-Received: by 2002:a17:902:780a:: with SMTP id p10mr34399164pll.54.1550621138398; Tue, 19 Feb 2019 16:05:38 -0800 (PST) Received: from majic.sklembedded.com (c-73-202-231-77.hsd1.ca.comcast.net. [73.202.231.77]) by smtp.googlemail.com with ESMTPSA id f14sm19159083pgv.23.2019.02.19.16.05.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 19 Feb 2019 16:05:37 -0800 (PST) From: Steve Longerbeam To: linux-media@vger.kernel.org Cc: Tim Harvey , Steve Longerbeam , Philipp Zabel , dri-devel@lists.freedesktop.org (open list:DRM DRIVERS FOR FREESCALE IMX), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v5 4/7] gpu: ipu-v3: ipu-ic: Add support for Rec.709 encoding Date: Tue, 19 Feb 2019 16:05:18 -0800 Message-Id: <20190220000521.31130-5-slongerbeam@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190220000521.31130-1-slongerbeam@gmail.com> References: <20190220000521.31130-1-slongerbeam@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for Rec.709 encoding and inverse encoding. The determination of the CSC coefficients based on the input/output colorspace parameters are moved to a new function calc_csc_coeffs(). Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v5: - moved API changes to a previous patch. - moved CSC coeff calc to new function calc_csc_coeffs(). Changes in v4: - fix compile error. Chnges in v3: - none. Changes in v2: - only return "Unsupported YCbCr encoding" error if inf != outf, since if inf == outf, the identity matrix can be used. Reported by Tim Harvey. --- drivers/gpu/ipu-v3/ipu-ic.c | 120 ++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c index 02043f23f411..012ea2239e97 100644 --- a/drivers/gpu/ipu-v3/ipu-ic.c +++ b/drivers/gpu/ipu-v3/ipu-ic.c @@ -214,6 +214,23 @@ static const struct ic_encode_coeff ic_encode_identity = { .scale = 2, }; +/* + * REC.709 encoding from RGB full range to YUV full range: + * + * Y = .2126 * R + .7152 * G + .0722 * B + * U = -.1146 * R - .3854 * G + .5000 * B + 128 + * V = .5000 * R - .4542 * G - .0458 * B + 128 + */ +static const struct ic_encode_coeff ic_encode_rgb2ycbcr_709 = { + .coeff = { + { 54, 183, 19 }, + { 483, 413, 128 }, + { 128, 396, 500 }, + }, + .offset = { 0, 512, 512 }, + .scale = 1, +}; + /* * Inverse BT.601 encoding from YUV full range to RGB full range: * @@ -237,28 +254,42 @@ static const struct ic_encode_coeff ic_encode_ycbcr2rgb_601 = { .scale = 2, }; -static int init_csc(struct ipu_ic *ic, - const struct ipu_ic_colorspace *in, - const struct ipu_ic_colorspace *out, - int csc_index) +/* + * Inverse REC.709 encoding from YUV full range to RGB full range: + * + * R = 1. * Y + 0 * (Cb - 128) + 1.5748 * (Cr - 128) + * G = 1. * Y - .1873 * (Cb - 128) - .4681 * (Cr - 128) + * B = 1. * Y + 1.8556 * (Cb - 128) + 0 * (Cr - 128) + * + * equivalently (factoring out the offsets): + * + * R = 1. * Y + 0 * Cb + 1.5748 * Cr - 201.574 + * G = 1. * Y - .1873 * Cb - .4681 * Cr + 83.891 + * B = 1. * Y + 1.8556 * Cb + 0 * Cr - 237.517 + */ +static const struct ic_encode_coeff ic_encode_ycbcr2rgb_709 = { + .coeff = { + { 128, 0, 202 }, + { 128, 488, 452 }, + { 128, 238, 0 }, + }, + .offset = { -403, 168, -475 }, + .scale = 2, +}; + +static int calc_csc_coeffs(struct ipu_ic_priv *priv, + struct ic_encode_coeff *coeff_out, + const struct ipu_ic_colorspace *in, + const struct ipu_ic_colorspace *out) { - struct ipu_ic_priv *priv = ic->priv; - const struct ic_encode_coeff *coeff; - u32 __iomem *base; - const u16 (*c)[3]; - const u16 *a; - u32 param; + const struct ic_encode_coeff *encode_coeff; + bool inverse_encode; if (in->colorspace != out->colorspace) { dev_err(priv->ipu->dev, "Cannot convert colorspaces\n"); return -ENOTSUPP; } - if (out->enc != V4L2_YCBCR_ENC_601) { - dev_err(priv->ipu->dev, "Only BT.601 encoding supported\n"); - return -ENOTSUPP; - } - if ((in->cs == IPUV3_COLORSPACE_YUV && in->quant != V4L2_QUANTIZATION_FULL_RANGE) || (out->cs == IPUV3_COLORSPACE_YUV && @@ -275,26 +306,63 @@ static int init_csc(struct ipu_ic *ic, return -ENOTSUPP; } + if (in->cs == out->cs) { + *coeff_out = ic_encode_identity; + + return 0; + } + + inverse_encode = (in->cs == IPUV3_COLORSPACE_YUV); + + switch (out->enc) { + case V4L2_YCBCR_ENC_601: + encode_coeff = inverse_encode ? + &ic_encode_ycbcr2rgb_601 : &ic_encode_rgb2ycbcr_601; + break; + case V4L2_YCBCR_ENC_709: + encode_coeff = inverse_encode ? + &ic_encode_ycbcr2rgb_709 : &ic_encode_rgb2ycbcr_709; + break; + default: + dev_err(priv->ipu->dev, "Unsupported YCbCr encoding\n"); + return -ENOTSUPP; + } + + *coeff_out = *encode_coeff; + + return 0; +} + +static int init_csc(struct ipu_ic *ic, + const struct ipu_ic_colorspace *in, + const struct ipu_ic_colorspace *out, + int csc_index) +{ + struct ipu_ic_priv *priv = ic->priv; + struct ic_encode_coeff coeff; + u32 __iomem *base; + const u16 (*c)[3]; + const u16 *a; + u32 param; + int ret; + + ret = calc_csc_coeffs(priv, &coeff, in, out); + if (ret) + return ret; + base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); - if (in->cs == out->cs) - coeff = &ic_encode_identity; - else if (in->cs == IPUV3_COLORSPACE_YUV) - coeff = &ic_encode_ycbcr2rgb_601; - else - coeff = &ic_encode_rgb2ycbcr_601; - /* Cast to unsigned */ - c = (const u16 (*)[3])coeff->coeff; - a = (const u16 *)coeff->offset; + c = (const u16 (*)[3])coeff.coeff; + a = (const u16 *)coeff.offset; param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) | ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff); writel(param, base++); - param = ((a[0] & 0x1fe0) >> 5) | (coeff->scale << 8) | - (coeff->sat << 10); + param = ((a[0] & 0x1fe0) >> 5) | (coeff.scale << 8) | + (coeff.sat << 10); writel(param, base++); param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) | -- 2.17.1