Skip to content

Commit

Permalink
drm/nouveau/dp: add support for displayport table 0x30
Browse files Browse the repository at this point in the history
Written from observations of my NVD9's vbios, completely untested due to
my NVD9 lacking actual DisplayPort connectors..

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Sep 20, 2011
1 parent 5f1800b commit c16a3a3
Showing 1 changed file with 48 additions and 22 deletions.
70 changes: 48 additions & 22 deletions drivers/gpu/drm/nouveau/nouveau_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
switch (table[0]) {
case 0x20:
case 0x21:
case 0x30:
break;
default:
NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]);
Expand Down Expand Up @@ -339,6 +340,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
int or = dp->or, link = dp->link;
u8 *entry, sink[2];
u32 dp_ctrl;
u16 script;

NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);

Expand All @@ -360,10 +362,17 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
*/
entry = ROMPTR(&dev_priv->vbios, dp->entry[10]);
if (entry) {
while (dp->link_bw < (ROM16(entry[0]) * 10))
entry += 4;
if (dp->table[0] < 0x30) {
while (dp->link_bw < (ROM16(entry[0]) * 10))
entry += 4;
script = ROM16(entry[2]);
} else {
while (dp->link_bw < (entry[0] * 27000))
entry += 3;
script = ROM16(entry[1]);
}

nouveau_bios_run_init_table(dev, ROM16(entry[2]), dp->dcb, dp->crtc);
nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc);
}

/* configure lane count on the source */
Expand Down Expand Up @@ -414,33 +423,50 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
shifts = nvaf_lane_map;

for (i = 0; i < dp->link_nr; i++) {
u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
u8 *conf = dp->entry + dp->table[4];
u8 *last = conf + (dp->entry[4] * dp->table[5]);

while (conf < last) {
if ((lane & 3) == conf[0] &&
(lane >> 2) == conf[1])
break;
conf += 5;
}
u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
u8 lpre = (lane & 0x0c) >> 2;
u8 lvsw = (lane & 0x03) >> 0;

if (conf == last)
return -EINVAL;
mask |= 0xff << shifts[i];
unk |= 1 << (shifts[i] >> 3);

dp->conf[i] = (conf[1] << 3) | conf[0];
if (conf[0] == DP_TRAIN_VOLTAGE_SWING_1200)
dp->conf[i] = (lpre << 3) | lvsw;
if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200)
dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED;
if (conf[1] == DP_TRAIN_PRE_EMPHASIS_9_5)
if (lpre == DP_TRAIN_PRE_EMPHASIS_9_5)
dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;

NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]);

mask |= 0xff << shifts[i];
drv |= conf[2] << shifts[i];
pre |= conf[3] << shifts[i];
unk = (unk & ~0x0000ff00) | (conf[4] << 8);
unk |= 1 << (shifts[i] >> 3);
if (dp->table[0] < 0x30) {
u8 *last = conf + (dp->entry[4] * dp->table[5]);
while (lvsw != conf[0] || lpre != conf[1]) {
conf += dp->table[5];
if (conf >= last)
return -EINVAL;
}

conf += 2;
} else {
/* no lookup table anymore, set entries for each
* combination of voltage swing and pre-emphasis
* level allowed by the DP spec.
*/
switch (lvsw) {
case 0: lpre += 0; break;
case 1: lpre += 4; break;
case 2: lpre += 7; break;
case 3: lpre += 9; break;
}

conf = conf + (lpre * dp->table[5]);
conf++;
}

drv |= conf[0] << shifts[i];
pre |= conf[1] << shifts[i];
unk = (unk & ~0x0000ff00) | (conf[2] << 8);
}

nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv);
Expand Down

0 comments on commit c16a3a3

Please sign in to comment.