aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-11-03 22:40:36 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-11-08 00:39:57 -0500
commit8df1d0c07f18bd84ea7d8c7bc2cff45ba2b09680 (patch)
tree70e72b11046c63bb370b50220393a38c27c397c0
parent4767fae8f8e28a3be8fbe7eedf7f843aab97cfba (diff)
drm/nouveau/disp: semi-complete link training sequence even if display disappears
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
index 15448b9abac8..1bd4c63369c1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -70,17 +70,10 @@ dp_set_link_config(struct dp_state *dp)
70 }; 70 };
71 u32 lnkcmp; 71 u32 lnkcmp;
72 u8 sink[2]; 72 u8 sink[2];
73 int ret;
73 74
74 DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); 75 DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
75 76
76 /* set desired link configuration on the sink */
77 sink[0] = dp->link_bw / 27000;
78 sink[1] = dp->link_nr;
79 if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP)
80 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
81
82 nv_wraux(dp->aux, DPCD_LC00, sink, 2);
83
84 /* set desired link configuration on the source */ 77 /* set desired link configuration on the source */
85 if ((lnkcmp = dp->info.lnkcmp)) { 78 if ((lnkcmp = dp->info.lnkcmp)) {
86 if (dp->version < 0x30) { 79 if (dp->version < 0x30) {
@@ -96,10 +89,22 @@ dp_set_link_config(struct dp_state *dp)
96 nvbios_exec(&init); 89 nvbios_exec(&init);
97 } 90 }
98 91
99 return dp->func->lnk_ctl(dp->disp, dp->outp, dp->head, 92 ret = dp->func->lnk_ctl(dp->disp, dp->outp, dp->head,
100 dp->link_nr, dp->link_bw / 27000, 93 dp->link_nr, dp->link_bw / 27000,
101 dp->dpcd[DPCD_RC02] & 94 dp->dpcd[DPCD_RC02] &
102 DPCD_RC02_ENHANCED_FRAME_CAP); 95 DPCD_RC02_ENHANCED_FRAME_CAP);
96 if (ret) {
97 ERR("lnk_ctl failed with %d\n", ret);
98 return ret;
99 }
100
101 /* set desired link configuration on the sink */
102 sink[0] = dp->link_bw / 27000;
103 sink[1] = dp->link_nr;
104 if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP)
105 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
106
107 return nv_wraux(dp->aux, DPCD_LC00, sink, 2);
103} 108}
104 109
105static void 110static void
@@ -294,8 +299,17 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
294 299
295 ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd)); 300 ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd));
296 if (ret) { 301 if (ret) {
302 /* it's possible the display has been unplugged before we
303 * get here. we still need to execute the full set of
304 * vbios scripts, and program the OR at a high enough
305 * frequency to satisfy the target mode. failure to do
306 * so results at best in an UPDATE hanging, and at worst
307 * with PDISP running away to join the circus.
308 */
309 dp->dpcd[1] = link_bw[0] / 27000;
310 dp->dpcd[2] = 4;
311 dp->dpcd[3] = 0x00;
297 ERR("failed to read DPCD\n"); 312 ERR("failed to read DPCD\n");
298 return ret;
299 } 313 }
300 314
301 /* adjust required bandwidth for 8B/10B coding overhead */ 315 /* adjust required bandwidth for 8B/10B coding overhead */
@@ -328,8 +342,10 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
328 !dp_link_train_eq(dp)) 342 !dp_link_train_eq(dp))
329 break; 343 break;
330 } else 344 } else
331 if (ret >= 1) { 345 if (ret) {
332 /* dp_set_link_config() handled training */ 346 /* dp_set_link_config() handled training, or
347 * we failed to communicate with the sink.
348 */
333 break; 349 break;
334 } 350 }
335 351
@@ -344,5 +360,5 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
344 360
345 /* execute post-train script from vbios */ 361 /* execute post-train script from vbios */
346 dp_link_train_fini(dp); 362 dp_link_train_fini(dp);
347 return true; 363 return (ret < 0) ? false : true;
348} 364}