All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steve Longerbeam <slongerbeam@gmail.com>
To: linux-media@vger.kernel.org
Cc: Tim Harvey <tharvey@gateworks.com>,
	Steve Longerbeam <slongerbeam@gmail.com>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	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	[thread overview]
Message-ID: <20190220000521.31130-5-slongerbeam@gmail.com> (raw)
In-Reply-To: <20190220000521.31130-1-slongerbeam@gmail.com>

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 <tharvey@gateworks.com>
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
---
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


WARNING: multiple messages have this Message-ID (diff)
From: Steve Longerbeam <slongerbeam@gmail.com>
To: linux-media@vger.kernel.org
Cc: open list <linux-kernel@vger.kernel.org>,
	"open list:DRM DRIVERS FOR FREESCALE IMX"
	<dri-devel@lists.freedesktop.org>,
	Steve Longerbeam <slongerbeam@gmail.com>
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	[thread overview]
Message-ID: <20190220000521.31130-5-slongerbeam@gmail.com> (raw)
In-Reply-To: <20190220000521.31130-1-slongerbeam@gmail.com>

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 <tharvey@gateworks.com>
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
---
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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2019-02-20  0:05 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-20  0:05 [PATCH v5 0/7] media: imx: Add support for BT.709 encoding Steve Longerbeam
2019-02-20  0:05 ` [PATCH v5 1/7] gpu: ipu-v3: ipu-ic: Fix saturation bit offset in TPMEM Steve Longerbeam
2019-02-20  0:05   ` Steve Longerbeam
2019-02-20  0:05 ` [PATCH v5 2/7] gpu: ipu-v3: ipu-ic: Fix BT.601 coefficients Steve Longerbeam
2019-02-20  0:05   ` Steve Longerbeam
2019-02-20  0:05 ` [PATCH v5 3/7] gpu: ipu-v3: ipu-ic: Fully describe colorspace conversions Steve Longerbeam
2019-02-20  0:05   ` Steve Longerbeam
2019-02-20  0:05   ` Steve Longerbeam
2019-02-20  0:05 ` Steve Longerbeam [this message]
2019-02-20  0:05   ` [PATCH v5 4/7] gpu: ipu-v3: ipu-ic: Add support for Rec.709 encoding Steve Longerbeam
2019-02-20  0:05 ` [PATCH v5 5/7] gpu: ipu-v3: ipu-ic: Add support for limited range encoding Steve Longerbeam
2019-02-20  0:05   ` Steve Longerbeam
2019-02-20  0:05 ` [PATCH v5 6/7] media: imx: Try colorimetry at both sink and source pads Steve Longerbeam
2019-02-20  0:05 ` [PATCH v5 7/7] media: imx: Allow BT.709 encoding for IC routes Steve Longerbeam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190220000521.31130-5-slongerbeam@gmail.com \
    --to=slongerbeam@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=tharvey@gateworks.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.