summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2020-07-21 11:52:18 +0200
committerPhilipp Zabel <p.zabel@pengutronix.de>2021-05-10 17:20:29 +0200
commit4618cb7903d6e37690fff85a47126a4917e06495 (patch)
treeb941e541666c2cd74bcbd4b5a57a47418199618d /drivers
parent17b9a94656fe19aef3647c4f93d93be51697ceb1 (diff)
gpu: ipu-v3: Add Rec.709 limited range support to DP
Add YCbCr encoding and quantization range parameters to ipu_dp_setup_channel() and configure the CSC DP matrix accordingly. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c9
-rw-r--r--drivers/gpu/ipu-v3/ipu-dp.c25
2 files changed, 28 insertions, 6 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 544d8eaf7c36..9d8f1b65ac0d 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -651,11 +651,14 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
switch (ipu_plane->dp_flow) {
case IPU_DP_FLOW_SYNC_BG:
- ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
+ ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
+ DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
+ IPUV3_COLORSPACE_RGB);
break;
case IPU_DP_FLOW_SYNC_FG:
- ipu_dp_setup_channel(ipu_plane->dp, ics,
- IPUV3_COLORSPACE_UNKNOWN);
+ ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
+ DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
+ IPUV3_COLORSPACE_UNKNOWN);
break;
}
diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index 8f67e985f26a..6a558205db96 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -10,6 +10,7 @@
#include <linux/io.h>
#include <linux/err.h>
+#include <drm/drm_color_mgmt.h>
#include <video/imx-ipu-v3.h>
#include "ipu-prv.h"
@@ -125,6 +126,8 @@ int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
static void ipu_dp_csc_init(struct ipu_flow *flow,
+ enum drm_color_encoding ycbcr_enc,
+ enum drm_color_range range,
enum ipu_color_space in,
enum ipu_color_space out,
u32 place)
@@ -148,7 +151,18 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
flow->base + DP_CSC_0);
writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
flow->base + DP_CSC_1);
+ } else if (ycbcr_enc == DRM_COLOR_YCBCR_BT709) {
+ /* Rec.709 limited range */
+ writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
+ writel(0x0e5 | (0x095 << 16), flow->base + DP_CSC_A_1);
+ writel(0x3e5 | (0x3bc << 16), flow->base + DP_CSC_A_2);
+ writel(0x095 | (0x10e << 16), flow->base + DP_CSC_A_3);
+ writel(0x000 | (0x3e10 << 16) | (1 << 30),
+ flow->base + DP_CSC_0);
+ writel(0x09a | (1 << 14) | (0x3dbe << 16) | (1 << 30),
+ flow->base + DP_CSC_1);
} else {
+ /* BT.601 limited range */
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);
@@ -165,6 +179,8 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
}
int ipu_dp_setup_channel(struct ipu_dp *dp,
+ enum drm_color_encoding ycbcr_enc,
+ enum drm_color_range range,
enum ipu_color_space in,
enum ipu_color_space out)
{
@@ -183,7 +199,8 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
* foreground and background are of same colorspace, put
* colorspace converter after combining unit.
*/
- ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
+ ipu_dp_csc_init(flow, ycbcr_enc, range,
+ flow->foreground.in_cs, flow->out_cs,
DP_COM_CONF_CSC_DEF_BOTH);
} else {
if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
@@ -192,10 +209,12 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
* foreground identical to output, apply color
* conversion on background
*/
- ipu_dp_csc_init(flow, flow->background.in_cs,
+ ipu_dp_csc_init(flow, ycbcr_enc, range,
+ flow->background.in_cs,
flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
else
- ipu_dp_csc_init(flow, flow->foreground.in_cs,
+ ipu_dp_csc_init(flow, ycbcr_enc, range,
+ flow->foreground.in_cs,
flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
}