aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch187
1 files changed, 187 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch b/target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch
new file mode 100644
index 0000000000..14c95579ab
--- /dev/null
+++ b/target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch
@@ -0,0 +1,187 @@
+From 1a8c7e6db6898ea62820bdd4fc9ef70b04ea528a Mon Sep 17 00:00:00 2001
+From: Laurentiu Palcu <laurentiu.palcu@nxp.com>
+Date: Thu, 7 Nov 2019 15:23:41 +0200
+Subject: [PATCH] drm/imx/hdp: handle the various deep-color settings
+
+iMX8MQ has the ability to handle color depths up to 12bpc. This patch adds
+support for higher color depths for various modes.
+
+Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
+---
+ drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 132 ++++++++++++++----------
+ 1 file changed, 75 insertions(+), 57 deletions(-)
+
+--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
++++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
+@@ -67,58 +67,20 @@ static void hdmi_lanes_config(struct cdn
+ cdns_mhdp_reg_write(mhdp, LANES_CONFIG, 0x00400000 | mhdp->lane_mapping);
+ }
+
+-#define RGB_ALLOWED_COLORIMETRY (BIT(HDMI_EXTENDED_COLORIMETRY_BT2020) |\
+- BIT(HDMI_EXTENDED_COLORIMETRY_OPRGB))
+-#define YCC_ALLOWED_COLORIMETRY (BIT(HDMI_EXTENDED_COLORIMETRY_BT2020) |\
+- BIT(HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM) |\
+- BIT(HDMI_EXTENDED_COLORIMETRY_OPYCC_601) |\
+- BIT(HDMI_EXTENDED_COLORIMETRY_S_YCC_601) |\
+- BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_709) |\
+- BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_601))
+ static int hdmi_avi_info_set(struct cdns_mhdp_device *mhdp,
+- struct drm_display_mode *mode)
++ struct drm_display_mode *mode)
+ {
+ struct hdmi_avi_infoframe frame;
+-#if 0
+- struct drm_display_info *di = &mhdp->connector.base.display_info;
+- enum hdmi_extended_colorimetry ext_col;
+- u32 sink_col, allowed_col;
+-#endif
+ int format = mhdp->video_info.color_fmt;
++ struct drm_connector_state *conn_state = mhdp->connector.base.state;
++ struct drm_display_mode *adj_mode;
++ enum hdmi_quantization_range qr;
+ u8 buf[32];
+ int ret;
+
+ /* Initialise info frame from DRM mode */
+- drm_hdmi_avi_infoframe_from_display_mode(&frame, &mhdp->connector.base, mode);
+-
+-#if 0 //TODO to DCSS
+- /* Set up colorimetry */
+- allowed_col = format == PXL_RGB ? RGB_ALLOWED_COLORIMETRY :
+- YCC_ALLOWED_COLORIMETRY;
+-
+- sink_col = di->hdmi.colorimetry & allowed_col;
+-
+- if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_BT2020))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_BT2020;
+- else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
+- else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_OPRGB))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_OPRGB;
+- else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_709))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
+- else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_OPYCC_601))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_OPYCC_601;
+- else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_S_YCC_601))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_S_YCC_601;
+- else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_601))
+- ext_col = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+- else
+- ext_col = 0;
+-
+- frame.colorimetry = sink_col ? HDMI_COLORIMETRY_EXTENDED :
+- HDMI_COLORIMETRY_NONE;
+- frame.extended_colorimetry = ext_col;
+-#endif
++ drm_hdmi_avi_infoframe_from_display_mode(&frame, &mhdp->connector.base,
++ mode);
+
+ switch (format) {
+ case YCBCR_4_4_4:
+@@ -135,6 +97,19 @@ static int hdmi_avi_info_set(struct cdns
+ break;
+ }
+
++ drm_hdmi_avi_infoframe_colorspace(&frame, conn_state);
++
++ adj_mode = &mhdp->bridge.base.encoder->crtc->state->adjusted_mode;
++
++ qr = drm_default_rgb_quant_range(adj_mode);
++
++ drm_hdmi_avi_infoframe_quant_range(&frame, &mhdp->connector.base,
++ adj_mode, qr);
++
++ ret = hdmi_avi_infoframe_check(&frame);
++ if (WARN_ON(ret))
++ return false;
++
+ ret = hdmi_avi_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1);
+ if (ret < 0) {
+ DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
+@@ -404,19 +379,6 @@ static void cdns_hdmi_bridge_mode_set(st
+ struct drm_display_info *display_info = &mhdp->connector.base.display_info;
+ struct video_info *video = &mhdp->video_info;
+
+- switch (display_info->bpc) {
+- case 10:
+- video->color_depth = 10;
+- break;
+- case 6:
+- video->color_depth = 6;
+- break;
+- default:
+- video->color_depth = 8;
+- break;
+- }
+-
+- video->color_fmt = PXL_RGB;
+ video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
+ video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
+
+@@ -428,10 +390,66 @@ static void cdns_hdmi_bridge_mode_set(st
+ mutex_unlock(&mhdp->lock);
+ }
+
++bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ struct cdns_mhdp_device *mhdp = bridge->driver_private;
++ struct drm_display_info *di = &mhdp->connector.base.display_info;
++ struct video_info *video = &mhdp->video_info;
++ int vic = drm_match_cea_mode(mode);
++
++ video->color_depth = 8;
++ video->color_fmt = PXL_RGB;
++
++ /* for all other platforms, other than imx8mq */
++ if (strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) {
++ if (di->bpc == 10 || di->bpc == 6)
++ video->color_depth = di->bpc;
++
++ return true;
++ }
++
++ /* imx8mq */
++ if (vic == 97 || vic == 96) {
++ if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
++ video->color_depth = 12;
++ else if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
++ video->color_depth = 10;
++
++ if (drm_mode_is_420_only(di, mode) ||
++ (drm_mode_is_420_also(di, mode) &&
++ video->color_depth > 8)) {
++ video->color_fmt = YCBCR_4_2_0;
++
++ adjusted_mode->private_flags = 1;
++ return true;
++ }
++
++ video->color_depth = 8;
++ return true;
++ }
++
++ /* Any defined maximum tmds clock limit we must not exceed*/
++ if ((di->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) &&
++ (mode->clock * 3 / 2 <= di->max_tmds_clock))
++ video->color_depth = 12;
++ else if ((di->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
++ (mode->clock * 5 / 4 <= di->max_tmds_clock))
++ video->color_depth = 10;
++
++ /* 10-bit color depth for the following modes is not supported */
++ if ((vic == 95 || vic == 94 || vic == 93) && video->color_depth == 10)
++ video->color_depth = 8;
++
++ return true;
++}
++
+ static const struct drm_bridge_funcs cdns_hdmi_bridge_funcs = {
+ .attach = cdns_hdmi_bridge_attach,
+ .mode_set = cdns_hdmi_bridge_mode_set,
+ .mode_valid = cdns_hdmi_bridge_mode_valid,
++ .mode_fixup = cdns_hdmi_bridge_mode_fixup,
+ };
+
+ static void hotplug_work_func(struct work_struct *work)