drm/nouveau: match U/DP script against SOR link

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>
This commit is contained in:
Ben Skeggs 2010-06-01 13:40:41 +10:00 committed by Dave Airlie
parent f712d0c7e7
commit 1eb38100ab
1 changed files with 20 additions and 3 deletions

View File

@ -3920,7 +3920,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
static uint8_t * static uint8_t *
bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, 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 drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios; 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; uint16_t table;
int i, v; 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) { for (i = 0; i < record_nr; i++, record += record_len) {
table = ROM16(bios->data[record]); table = ROM16(bios->data[record]);
if (!table) if (!table)
continue; continue;
entry = ROM32(bios->data[table]); entry = ROM32(bios->data[table]);
if (match_link) {
v = (entry & 0x00c00000) >> 22;
if (!(v & dcbent->sorconf.link))
continue;
}
v = (entry & 0x000f0000) >> 16; v = (entry & 0x000f0000) >> 16;
if (!(v & dcbent->or)) if (!(v & dcbent->or))
continue; continue;
@ -3975,7 +3992,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
*length = table[4]; *length = table[4];
return bios_output_config_match(dev, dcbent, return bios_output_config_match(dev, dcbent,
bios->display.dp_table_ptr + table[1], bios->display.dp_table_ptr + table[1],
table[2], table[3]); table[2], table[3], table[0] >= 0x21);
} }
int int
@ -4064,7 +4081,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
dcbent->type, dcbent->location, dcbent->or); dcbent->type, dcbent->location, dcbent->or);
otable = bios_output_config_match(dev, dcbent, table[1] + otable = bios_output_config_match(dev, dcbent, table[1] +
bios->display.script_table_ptr, bios->display.script_table_ptr,
table[2], table[3]); table[2], table[3], table[0] >= 0x21);
if (!otable) { if (!otable) {
NV_ERROR(dev, "Couldn't find matching output script table\n"); NV_ERROR(dev, "Couldn't find matching output script table\n");
return 1; return 1;