drm/nouveau/disp: limit dp capabilities as per dcb
authorBen Skeggs <bskeggs@redhat.com>
Wed, 19 Mar 2014 23:28:00 +0000 (09:28 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 26 Mar 2014 04:08:20 +0000 (14:08 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/disp/dport.c
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c

index 1bd4c63369c16f96fd30762c1faaddb60acdf337..2aedb4e47d0335f9c7b5ffab1876848e5aeb499b 100644 (file)
@@ -312,6 +312,14 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
                ERR("failed to read DPCD\n");
        }
 
+       /* bring capabilities within encoder limits */
+       if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) {
+               dp->dpcd[2] &= ~0x1f;
+               dp->dpcd[2] |= dp->outp->dpconf.link_nr;
+       }
+       if (dp->dpcd[1] > dp->outp->dpconf.link_bw)
+               dp->dpcd[1] = dp->outp->dpconf.link_bw;
+
        /* adjust required bandwidth for 8B/10B coding overhead */
        datarate = (datarate / 8) * 10;
 
index 2d9b9d7a7992111cc1d4bd0ff3e60254bf52dcb5..88606bfaf84742c3c87a26d0d8387c29fecc9d81 100644 (file)
@@ -142,9 +142,36 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,
                if (*ver >= 0x40) {
                        u32 conf = nv_ro32(bios, dcb + 0x04);
                        switch (outp->type) {
+                       case DCB_OUTPUT_DP:
+                               switch (conf & 0x00e00000) {
+                               case 0x00000000:
+                                       outp->dpconf.link_bw = 0x06;
+                                       break;
+                               case 0x00200000:
+                                       outp->dpconf.link_bw = 0x0a;
+                                       break;
+                               case 0x00400000:
+                               default:
+                                       outp->dpconf.link_bw = 0x14;
+                                       break;
+                               }
+
+                               switch (conf & 0x0f000000) {
+                               case 0x0f000000:
+                                       outp->dpconf.link_nr = 4;
+                                       break;
+                               case 0x03000000:
+                                       outp->dpconf.link_nr = 2;
+                                       break;
+                               case 0x01000000:
+                               default:
+                                       outp->dpconf.link_nr = 1;
+                                       break;
+                               }
+
+                               /* fall-through... */
                        case DCB_OUTPUT_TMDS:
                        case DCB_OUTPUT_LVDS:
-                       case DCB_OUTPUT_DP:
                                outp->link = (conf & 0x00000030) >> 4;
                                outp->sorconf.link = outp->link; /*XXX*/
                                outp->extdev = 0x00;