aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/805-display-0028-drm-imx-hdp-handle-the-various-deep-color-settings.patch
blob: 14c95579ab6c7a02907070f2323a6e5c98402268 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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)