You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
6.2 KiB
Diff
188 lines
6.2 KiB
Diff
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)
|