drm/nouveau: match U/DP script against SOR link
authorBen Skeggs <bskeggs@redhat.com>
Tue, 1 Jun 2010 03:40:41 +0000 (13:40 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 8 Jun 2010 01:02:38 +0000 (11:02 +1000)
It appears version 0x21 'U' and 'd' tables require us to take the SOR link
into account when selecting the appropriate table for a particular output.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/nouveau/nouveau_bios.c

index 9ba2dea..47a27a4 100644 (file)
@@ -3920,7 +3920,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
 
 static uint8_t *
 bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
-                        uint16_t record, int record_len, int record_nr)
+                        uint16_t record, int record_len, int record_nr,
+                        bool match_link)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvbios *bios = &dev_priv->vbios;
@@ -3928,12 +3929,28 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
        uint16_t table;
        int i, v;
 
+       switch (dcbent->type) {
+       case OUTPUT_TMDS:
+       case OUTPUT_LVDS:
+       case OUTPUT_DP:
+               break;
+       default:
+               match_link = false;
+               break;
+       }
+
        for (i = 0; i < record_nr; i++, record += record_len) {
                table = ROM16(bios->data[record]);
                if (!table)
                        continue;
                entry = ROM32(bios->data[table]);
 
+               if (match_link) {
+                       v = (entry & 0x00c00000) >> 22;
+                       if (!(v & dcbent->sorconf.link))
+                               continue;
+               }
+
                v = (entry & 0x000f0000) >> 16;
                if (!(v & dcbent->or))
                        continue;
@@ -3975,7 +3992,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
        *length = table[4];
        return bios_output_config_match(dev, dcbent,
                                        bios->display.dp_table_ptr + table[1],
-                                       table[2], table[3]);
+                                       table[2], table[3], table[0] >= 0x21);
 }
 
 int
@@ -4064,7 +4081,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
                        dcbent->type, dcbent->location, dcbent->or);
        otable = bios_output_config_match(dev, dcbent, table[1] +
                                          bios->display.script_table_ptr,
-                                         table[2], table[3]);
+                                         table[2], table[3], table[0] >= 0x21);
        if (!otable) {
                NV_ERROR(dev, "Couldn't find matching output script table\n");
                return 1;