9e90f7d73c0ff30e32b37b9c24ff47582ae8cf34
[openwrt/staging/mkresin.git] /
1 From 9ff3c9d6063c6464e243b85bbbbd03e2096a57c0 Mon Sep 17 00:00:00 2001
2 From: Sandor Yu <Sandor.yu@nxp.com>
3 Date: Mon, 28 Oct 2019 17:07:06 +0800
4 Subject: [PATCH] drm: mhdp: reset video mode after hdmi/dp cable plugin
5
6 DP need setup link training, and HDMI need reset hdmi sink SCDC
7 status after cable reconnected.
8 Add video mode_set function when cable plugin.
9 Add 20ms/50ms delay for hdmi/dp to waite FW stable.
10
11 Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
12 ---
13 drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 20 ++++----
14 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 63 ++++++++++++-------------
15 2 files changed, 43 insertions(+), 40 deletions(-)
16
17 --- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
18 +++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
19 @@ -108,19 +108,19 @@ static void dp_pixel_clk_reset(struct cd
20 cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, val);
21 }
22
23 -static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp,
24 - const struct drm_display_mode *mode)
25 +static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp)
26 {
27 u32 lane_mapping = mhdp->lane_mapping;
28 struct drm_dp_link *link = &mhdp->dp.link;
29 char linkid[6];
30 int ret;
31
32 - memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode));
33 + cdns_mhdp_plat_call(mhdp, pclk_rate);
34
35 - dp_pixel_clk_reset(mhdp);
36 + /* delay for DP FW stable after pixel clock relock */
37 + msleep(50);
38
39 - cdns_mhdp_plat_call(mhdp, pclk_rate);
40 + dp_pixel_clk_reset(mhdp);
41
42 ret = drm_dp_downstream_id(&mhdp->dp.aux, linkid);
43 if (ret < 0) {
44 @@ -330,11 +330,10 @@ static void cdns_dp_bridge_mode_set(stru
45 video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
46
47 DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock);
48 + memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode));
49
50 mutex_lock(&mhdp->lock);
51 -
52 - cdns_dp_mode_set(mhdp, mode);
53 -
54 + cdns_dp_mode_set(mhdp);
55 mutex_unlock(&mhdp->lock);
56 }
57
58 @@ -367,6 +366,11 @@ static void hotplug_work_func(struct wor
59 drm_helper_hpd_irq_event(connector->dev);
60
61 if (connector->status == connector_status_connected) {
62 + /* reset video mode after cable plugin */
63 + mutex_lock(&mhdp->lock);
64 + cdns_dp_mode_set(mhdp);
65 + mutex_unlock(&mhdp->lock);
66 +
67 DRM_INFO("HDMI/DP Cable Plug In\n");
68 enable_irq(mhdp->irq[IRQ_OUT]);
69 } else if (connector->status == connector_status_disconnected) {
70 --- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
71 +++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
72 @@ -11,11 +11,11 @@
73 */
74 #include <drm/bridge/cdns-mhdp-common.h>
75 #include <drm/drm_atomic_helper.h>
76 -#include <drm/drm_crtc_helper.h>
77 #include <drm/drm_edid.h>
78 #include <drm/drm_encoder_slave.h>
79 #include <drm/drm_of.h>
80 #include <drm/drm_probe_helper.h>
81 +#include <drm/drm_scdc_helper.h>
82 #include <drm/drmP.h>
83 #include <linux/delay.h>
84 #include <linux/err.h>
85 @@ -26,25 +26,30 @@
86 #include <linux/mutex.h>
87 #include <linux/of_device.h>
88
89 -static int hdmi_sink_config(struct cdns_mhdp_device *mhdp)
90 +static void hdmi_sink_config(struct cdns_mhdp_device *mhdp)
91 {
92 struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc;
93 u8 buff;
94 - int ret;
95 +
96 + /* check sink support SCDC or not */
97 + if (scdc->supported != true) {
98 + DRM_INFO("Sink Not Support SCDC\n");
99 + return;
100 + }
101
102 if (mhdp->hdmi.char_rate > 340000) {
103 /*
104 * TMDS Character Rate above 340MHz should working in HDMI2.0
105 * Enable scrambling and TMDS_Bit_Clock_Ratio
106 */
107 - buff = 3;
108 + buff = SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE;
109 mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
110 } else if (scdc->scrambling.low_rates) {
111 /*
112 * Enable scrambling and HDMI2.0 when scrambling capability of sink
113 * be indicated in the HF-VSDB LTE_340Mcsc_scramble bit
114 */
115 - buff = 1;
116 + buff = SCDC_SCRAMBLING_ENABLE;
117 mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
118 } else {
119 /* Default work in HDMI1.4 */
120 @@ -53,8 +58,7 @@ static int hdmi_sink_config(struct cdns_
121 }
122
123 /* TMDS config */
124 - ret = cdns_hdmi_scdc_write(mhdp, 0x20, buff);
125 - return ret;
126 + cdns_hdmi_scdc_write(mhdp, 0x20, buff);
127 }
128
129 static void hdmi_lanes_config(struct cdns_mhdp_device *mhdp)
130 @@ -142,7 +146,7 @@ static int hdmi_avi_info_set(struct cdns
131 return 0;
132 }
133
134 -static int hdmi_vendor_info_set(struct cdns_mhdp_device *mhdp,
135 +static void hdmi_vendor_info_set(struct cdns_mhdp_device *mhdp,
136 struct drm_display_mode *mode)
137 {
138 struct hdmi_vendor_infoframe frame;
139 @@ -152,19 +156,18 @@ static int hdmi_vendor_info_set(struct c
140 /* Initialise vendor frame from DRM mode */
141 ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame, &mhdp->connector.base, mode);
142 if (ret < 0) {
143 - DRM_WARN("Unable to init vendor infoframe: %d\n", ret);
144 - return -1;
145 + DRM_INFO("No vendor infoframe\n");
146 + return;
147 }
148
149 ret = hdmi_vendor_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1);
150 if (ret < 0) {
151 DRM_WARN("Unable to pack vendor infoframe: %d\n", ret);
152 - return -1;
153 + return;
154 }
155
156 buf[0] = 0;
157 cdns_mhdp_infoframe_set(mhdp, 3, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_VENDOR);
158 - return 0;
159 }
160
161 void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp)
162 @@ -172,9 +175,16 @@ void cdns_hdmi_mode_set(struct cdns_mhdp
163 struct drm_display_mode *mode = &mhdp->mode;
164 int ret;
165
166 - ret = hdmi_sink_config(mhdp);
167 - if (ret < 0)
168 - DRM_DEBUG("%s failed\n", __func__);
169 + hdmi_lanes_config(mhdp);
170 +
171 + cdns_mhdp_plat_call(mhdp, pclk_rate);
172 +
173 + /* delay for HDMI FW stable after pixel clock relock */
174 + msleep(20);
175 +
176 + cdns_mhdp_plat_call(mhdp, phy_set);
177 +
178 + hdmi_sink_config(mhdp);
179
180 ret = cdns_hdmi_ctrl_init(mhdp, mhdp->hdmi.hdmi_type, mhdp->hdmi.char_rate);
181 if (ret < 0) {
182 @@ -195,18 +205,13 @@ void cdns_hdmi_mode_set(struct cdns_mhdp
183 }
184
185 /* vendor info frame is enable only when HDMI1.4 4K mode */
186 - ret = hdmi_vendor_info_set(mhdp, mode);
187 - if (ret < 0)
188 - DRM_WARN("Unable to configure Vendor infoframe\n");
189 + hdmi_vendor_info_set(mhdp, mode);
190
191 ret = cdns_hdmi_mode_config(mhdp, mode, &mhdp->video_info);
192 if (ret < 0) {
193 DRM_ERROR("CDN_API_HDMITX_SetVic_blocking ret = %d\n", ret);
194 return;
195 }
196 -
197 - /* wait HDMI PHY pixel clock stable */
198 - msleep(50);
199 }
200
201 static enum drm_connector_status
202 @@ -335,20 +340,11 @@ static void cdns_hdmi_bridge_mode_set(st
203 video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
204 video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
205
206 - mutex_lock(&mhdp->lock);
207 -
208 DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock);
209 -
210 memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode));
211
212 - hdmi_lanes_config(mhdp);
213 -
214 - cdns_mhdp_plat_call(mhdp, pclk_rate);
215 -
216 - cdns_mhdp_plat_call(mhdp, phy_set);
217 -
218 + mutex_lock(&mhdp->lock);
219 cdns_hdmi_mode_set(mhdp);
220 -
221 mutex_unlock(&mhdp->lock);
222 }
223
224 @@ -367,8 +363,11 @@ static void hotplug_work_func(struct wor
225 drm_helper_hpd_irq_event(connector->dev);
226
227 if (connector->status == connector_status_connected) {
228 - /* Cable Connected */
229 DRM_INFO("HDMI Cable Plug In\n");
230 + /* reset video mode after cable plugin */
231 + mutex_lock(&mhdp->lock);
232 + cdns_hdmi_mode_set(mhdp);
233 + mutex_unlock(&mhdp->lock);
234 enable_irq(mhdp->irq[IRQ_OUT]);
235 } else if (connector->status == connector_status_disconnected) {
236 /* Cable Disconnedted */