diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2020-07-21 11:52:18 +0200 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2021-05-10 17:20:29 +0200 |
commit | 4618cb7903d6e37690fff85a47126a4917e06495 (patch) | |
tree | b941e541666c2cd74bcbd4b5a57a47418199618d /drivers | |
parent | 17b9a94656fe19aef3647c4f93d93be51697ceb1 (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.c | 9 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-dp.c | 25 |
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); } |