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 --- drivers/gpu/drm/imx/ipuv3-plane.c | 9 ++++++--- drivers/gpu/ipu-v3/ipu-dp.c | 25 ++++++++++++++++++++++--- include/video/imx-ipu-v3.h | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 075508051b5f..d77210043fe2 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -608,11 +608,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); }
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index d1b3889f74d8..c422a403c099 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -17,6 +17,7 @@ #include <linux/bitmap.h> #include <linux/fb.h> #include <linux/of.h> +#include <drm/drm_color_mgmt.h> #include <media/v4l2-mediabus.h> #include <video/videomode.h>
@@ -330,6 +331,7 @@ int ipu_dp_enable_channel(struct ipu_dp *dp); void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync); void ipu_dp_disable(struct ipu_soc *ipu); 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); 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,
Add COLOR_ENCODING and COLOR_RANGE plane properties and use them to control the DP CSC matrix.
Signed-off-by: Philipp Zabel p.zabel@pengutronix.de --- drivers/gpu/drm/imx/ipuv3-plane.c | 44 +++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index d77210043fe2..7909156d3a78 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -284,6 +284,8 @@ static void ipu_plane_state_reset(struct drm_plane *plane) __drm_atomic_helper_plane_reset(plane, &ipu_state->base); ipu_state->base.zpos = zpos; ipu_state->base.normalized_zpos = zpos; + ipu_state->base.color_encoding = DRM_COLOR_YCBCR_BT601; + ipu_state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; } }
@@ -589,6 +591,25 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, fb->modifier, &eba); }
+ if (!old_state->fb || + old_state->fb->format->format != fb->format->format || + old_state->color_encoding != state->color_encoding || + old_state->color_range != state->color_range) { + 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, state->color_encoding, + state->color_range, ics, + IPUV3_COLORSPACE_RGB); + break; + case IPU_DP_FLOW_SYNC_FG: + ipu_dp_setup_channel(ipu_plane->dp, state->color_encoding, + state->color_range, ics, + IPUV3_COLORSPACE_UNKNOWN); + break; + } + } + if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { /* nothing to do if PRE is used */ if (ipu_state->use_pre) @@ -605,20 +626,6 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, return; }
- 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, 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, DRM_COLOR_YCBCR_BT601, - DRM_COLOR_YCBCR_LIMITED_RANGE, ics, - IPUV3_COLORSPACE_UNKNOWN); - break; - } - ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
width = drm_rect_width(&state->src) >> 16; @@ -859,6 +866,15 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, if (ret) return ERR_PTR(ret);
+ ret = drm_plane_create_color_properties(&ipu_plane->base, + BIT(DRM_COLOR_YCBCR_BT601) | + BIT(DRM_COLOR_YCBCR_BT709), + BIT(DRM_COLOR_YCBCR_LIMITED_RANGE), + DRM_COLOR_YCBCR_BT601, + DRM_COLOR_YCBCR_LIMITED_RANGE); + if (ret) + return ERR_PTR(ret); + ret = ipu_plane_get_resources(dev, ipu_plane); if (ret) { DRM_ERROR("failed to get %s plane resources: %pe\n",
dri-devel@lists.freedesktop.org