14c95579ab6c7a02907070f2323a6e5c98402268
[openwrt/openwrt.git] /
1 From 1a8c7e6db6898ea62820bdd4fc9ef70b04ea528a Mon Sep 17 00:00:00 2001
2 From: Laurentiu Palcu <laurentiu.palcu@nxp.com>
3 Date: Thu, 7 Nov 2019 15:23:41 +0200
4 Subject: [PATCH] drm/imx/hdp: handle the various deep-color settings
5
6 iMX8MQ has the ability to handle color depths up to 12bpc. This patch adds
7 support for higher color depths for various modes.
8
9 Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
10 ---
11 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 132 ++++++++++++++----------
12 1 file changed, 75 insertions(+), 57 deletions(-)
13
14 --- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
15 +++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
16 @@ -67,58 +67,20 @@ static void hdmi_lanes_config(struct cdn
17 cdns_mhdp_reg_write(mhdp, LANES_CONFIG, 0x00400000 | mhdp->lane_mapping);
18 }
19
20 -#define RGB_ALLOWED_COLORIMETRY (BIT(HDMI_EXTENDED_COLORIMETRY_BT2020) |\
21 - BIT(HDMI_EXTENDED_COLORIMETRY_OPRGB))
22 -#define YCC_ALLOWED_COLORIMETRY (BIT(HDMI_EXTENDED_COLORIMETRY_BT2020) |\
23 - BIT(HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM) |\
24 - BIT(HDMI_EXTENDED_COLORIMETRY_OPYCC_601) |\
25 - BIT(HDMI_EXTENDED_COLORIMETRY_S_YCC_601) |\
26 - BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_709) |\
27 - BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_601))
28 static int hdmi_avi_info_set(struct cdns_mhdp_device *mhdp,
29 - struct drm_display_mode *mode)
30 + struct drm_display_mode *mode)
31 {
32 struct hdmi_avi_infoframe frame;
33 -#if 0
34 - struct drm_display_info *di = &mhdp->connector.base.display_info;
35 - enum hdmi_extended_colorimetry ext_col;
36 - u32 sink_col, allowed_col;
37 -#endif
38 int format = mhdp->video_info.color_fmt;
39 + struct drm_connector_state *conn_state = mhdp->connector.base.state;
40 + struct drm_display_mode *adj_mode;
41 + enum hdmi_quantization_range qr;
42 u8 buf[32];
43 int ret;
44
45 /* Initialise info frame from DRM mode */
46 - drm_hdmi_avi_infoframe_from_display_mode(&frame, &mhdp->connector.base, mode);
47 -
48 -#if 0 //TODO to DCSS
49 - /* Set up colorimetry */
50 - allowed_col = format == PXL_RGB ? RGB_ALLOWED_COLORIMETRY :
51 - YCC_ALLOWED_COLORIMETRY;
52 -
53 - sink_col = di->hdmi.colorimetry & allowed_col;
54 -
55 - if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_BT2020))
56 - ext_col = HDMI_EXTENDED_COLORIMETRY_BT2020;
57 - else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM))
58 - ext_col = HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM;
59 - else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_OPRGB))
60 - ext_col = HDMI_EXTENDED_COLORIMETRY_OPRGB;
61 - else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_709))
62 - ext_col = HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
63 - else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_OPYCC_601))
64 - ext_col = HDMI_EXTENDED_COLORIMETRY_OPYCC_601;
65 - else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_S_YCC_601))
66 - ext_col = HDMI_EXTENDED_COLORIMETRY_S_YCC_601;
67 - else if (sink_col & BIT(HDMI_EXTENDED_COLORIMETRY_XV_YCC_601))
68 - ext_col = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
69 - else
70 - ext_col = 0;
71 -
72 - frame.colorimetry = sink_col ? HDMI_COLORIMETRY_EXTENDED :
73 - HDMI_COLORIMETRY_NONE;
74 - frame.extended_colorimetry = ext_col;
75 -#endif
76 + drm_hdmi_avi_infoframe_from_display_mode(&frame, &mhdp->connector.base,
77 + mode);
78
79 switch (format) {
80 case YCBCR_4_4_4:
81 @@ -135,6 +97,19 @@ static int hdmi_avi_info_set(struct cdns
82 break;
83 }
84
85 + drm_hdmi_avi_infoframe_colorspace(&frame, conn_state);
86 +
87 + adj_mode = &mhdp->bridge.base.encoder->crtc->state->adjusted_mode;
88 +
89 + qr = drm_default_rgb_quant_range(adj_mode);
90 +
91 + drm_hdmi_avi_infoframe_quant_range(&frame, &mhdp->connector.base,
92 + adj_mode, qr);
93 +
94 + ret = hdmi_avi_infoframe_check(&frame);
95 + if (WARN_ON(ret))
96 + return false;
97 +
98 ret = hdmi_avi_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1);
99 if (ret < 0) {
100 DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
101 @@ -404,19 +379,6 @@ static void cdns_hdmi_bridge_mode_set(st
102 struct drm_display_info *display_info = &mhdp->connector.base.display_info;
103 struct video_info *video = &mhdp->video_info;
104
105 - switch (display_info->bpc) {
106 - case 10:
107 - video->color_depth = 10;
108 - break;
109 - case 6:
110 - video->color_depth = 6;
111 - break;
112 - default:
113 - video->color_depth = 8;
114 - break;
115 - }
116 -
117 - video->color_fmt = PXL_RGB;
118 video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
119 video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
120
121 @@ -428,10 +390,66 @@ static void cdns_hdmi_bridge_mode_set(st
122 mutex_unlock(&mhdp->lock);
123 }
124
125 +bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
126 + const struct drm_display_mode *mode,
127 + struct drm_display_mode *adjusted_mode)
128 +{
129 + struct cdns_mhdp_device *mhdp = bridge->driver_private;
130 + struct drm_display_info *di = &mhdp->connector.base.display_info;
131 + struct video_info *video = &mhdp->video_info;
132 + int vic = drm_match_cea_mode(mode);
133 +
134 + video->color_depth = 8;
135 + video->color_fmt = PXL_RGB;
136 +
137 + /* for all other platforms, other than imx8mq */
138 + if (strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) {
139 + if (di->bpc == 10 || di->bpc == 6)
140 + video->color_depth = di->bpc;
141 +
142 + return true;
143 + }
144 +
145 + /* imx8mq */
146 + if (vic == 97 || vic == 96) {
147 + if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
148 + video->color_depth = 12;
149 + else if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
150 + video->color_depth = 10;
151 +
152 + if (drm_mode_is_420_only(di, mode) ||
153 + (drm_mode_is_420_also(di, mode) &&
154 + video->color_depth > 8)) {
155 + video->color_fmt = YCBCR_4_2_0;
156 +
157 + adjusted_mode->private_flags = 1;
158 + return true;
159 + }
160 +
161 + video->color_depth = 8;
162 + return true;
163 + }
164 +
165 + /* Any defined maximum tmds clock limit we must not exceed*/
166 + if ((di->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) &&
167 + (mode->clock * 3 / 2 <= di->max_tmds_clock))
168 + video->color_depth = 12;
169 + else if ((di->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
170 + (mode->clock * 5 / 4 <= di->max_tmds_clock))
171 + video->color_depth = 10;
172 +
173 + /* 10-bit color depth for the following modes is not supported */
174 + if ((vic == 95 || vic == 94 || vic == 93) && video->color_depth == 10)
175 + video->color_depth = 8;
176 +
177 + return true;
178 +}
179 +
180 static const struct drm_bridge_funcs cdns_hdmi_bridge_funcs = {
181 .attach = cdns_hdmi_bridge_attach,
182 .mode_set = cdns_hdmi_bridge_mode_set,
183 .mode_valid = cdns_hdmi_bridge_mode_valid,
184 + .mode_fixup = cdns_hdmi_bridge_mode_fixup,
185 };
186
187 static void hotplug_work_func(struct work_struct *work)