diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-08-05 14:07:04 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 16:11:18 +1000 |
commit | 5f1800bd8a774f773e3be71702da7ec77188b283 (patch) | |
tree | 00ee052cf8f838434c92a24409e5bbfb6e8c807f | |
parent | 721b0821ad8fea80ea1b6b84cb9646881959e662 (diff) |
drm/nouveau/dp: return master dp table pointer too when looking up encoder
Will need to be able to distinguish 2.0/2.1 from 3.0 soon. Also, move
the vbios parsing to nouveau_dp where it belongs.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 53 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dp.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 3 |
4 files changed, 66 insertions, 70 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 73b590a7194..58b2535e3b6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -1182,18 +1182,16 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) struct dcb_entry *dcb = bios->display.output; struct drm_device *dev = bios->dev; uint8_t cond = bios->data[offset + 1]; - uint8_t *table, headerlen; + uint8_t *table, *entry; BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); if (!iexec->execute) return 3; - table = nouveau_bios_dp_table(dev, dcb, &headerlen); - if (!table) { - NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); + table = nouveau_dp_bios_data(dev, dcb, &entry); + if (!table) return 3; - } switch (cond) { case 0: @@ -1207,7 +1205,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) break; case 1: case 2: - if (!(table[5] & cond)) + if (!(entry[5] & cond)) iexec->execute = false; break; case 5: @@ -4454,40 +4452,6 @@ bios_encoder_match(struct dcb_entry *dcb, u32 hash) } } -void * -nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, - uint8_t *headerlen) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - uint8_t *table, *entry; - int i; - - if (!bios->display.dp_table_ptr) { - NV_ERROR(dev, "No pointer to DisplayPort table\n"); - return NULL; - } - table = &bios->data[bios->display.dp_table_ptr]; - - if (table[0] != 0x20 && table[0] != 0x21) { - NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n", - table[0]); - return NULL; - } - - entry = table + table[1]; - for (i = 0; i < table[3]; i++, entry += table[2]) { - u8 *etable = ROMPTR(bios, entry[0]); - if (etable && bios_encoder_match(dcbent, ROM32(etable[0]))) { - *headerlen = table[4]; - return etable; - } - } - - NV_ERROR(dev, "DisplayPort encoder table not found\n"); - return NULL; -} - int nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, struct dcb_entry *dcbent, int crtc) @@ -5503,14 +5467,6 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, return 0; } -static int -parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios, - struct bit_entry *bitentry) -{ - bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]); - return 0; -} - struct bit_table { const char id; int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); @@ -5584,7 +5540,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); - parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport)); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index b28f0bceaed..8adb69e4a6b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -291,7 +291,6 @@ struct nvbios { struct dcb_entry *output; int crtc; uint16_t script_table_ptr; - uint16_t dp_table_ptr; } display; struct { diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index d3552e76664..25ecb776c7b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -270,11 +270,57 @@ nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) unk); } +u8 * +nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; + struct bit_entry d; + u8 *table; + int i; + + if (bit_table(dev, 'd', &d)) { + NV_ERROR(dev, "BIT 'd' table not found\n"); + return NULL; + } + + if (d.version != 1) { + NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); + return NULL; + } + + table = ROMPTR(bios, d.data[0]); + if (!table) { + NV_ERROR(dev, "displayport table pointer invalid\n"); + return NULL; + } + + switch (table[0]) { + case 0x20: + case 0x21: + break; + default: + NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); + return NULL; + } + + for (i = 0; i < table[3]; i++) { + *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); + if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) + return table; + } + + NV_ERROR(dev, "displayport encoder table not found\n"); + return NULL; +} + /****************************************************************************** * link training *****************************************************************************/ struct dp_state { struct dcb_entry *dcb; + u8 *table; + u8 *entry; int auxch; int crtc; int or; @@ -291,7 +337,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) { struct drm_nouveau_private *dev_priv = dev->dev_private; int or = dp->or, link = dp->link; - u8 *bios, headerlen, sink[2]; + u8 *entry, sink[2]; u32 dp_ctrl; NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); @@ -312,12 +358,12 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) * table, that has (among other things) pointers to more scripts that * need to be executed, this time depending on link speed. */ - bios = nouveau_bios_dp_table(dev, dp->dcb, &headerlen); - if (bios && (bios = ROMPTR(&dev_priv->vbios, bios[10]))) { - while (dp->link_bw < (ROM16(bios[0]) * 10)) - bios += 4; + entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); + if (entry) { + while (dp->link_bw < (ROM16(entry[0]) * 10)) + entry += 4; - nouveau_bios_run_init_table(dev, ROM16(bios[2]), dp->dcb, dp->crtc); + nouveau_bios_run_init_table(dev, ROM16(entry[2]), dp->dcb, dp->crtc); } /* configure lane count on the source */ @@ -357,7 +403,6 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) { struct drm_nouveau_private *dev_priv = dev->dev_private; u32 mask = 0, drv = 0, pre = 0, unk = 0; - u8 *bios, *last, headerlen; const u8 *shifts; int link = dp->link; int or = dp->or; @@ -368,11 +413,10 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) else shifts = nvaf_lane_map; - bios = nouveau_bios_dp_table(dev, dp->dcb, &headerlen); - last = bios + headerlen + (bios[4] * 5); for (i = 0; i < dp->link_nr; i++) { u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; - u8 *conf = bios + headerlen; + u8 *conf = dp->entry + dp->table[4]; + u8 *last = conf + (dp->entry[4] * dp->table[5]); while (conf < last) { if ((lane & 3) == conf[0] && @@ -500,14 +544,13 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) const u32 bw_list[] = { 270000, 162000, 0 }; const u32 *link_bw = bw_list; struct dp_state dp; - u8 *bios, headerlen; auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); if (!auxch) return false; - bios = nouveau_bios_dp_table(dev, nv_encoder->dcb, &headerlen); - if (!bios) + dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); + if (!dp.table) return -EINVAL; dp.dcb = nv_encoder->dcb; @@ -524,16 +567,16 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); /* enable down-spreading, if possible */ - if (headerlen >= 16) { - u16 script = ROM16(bios[14]); + if (dp.table[1] >= 16) { + u16 script = ROM16(dp.entry[14]); if (nv_encoder->dp.dpcd[3] & 1) - script = ROM16(bios[12]); + script = ROM16(dp.entry[12]); nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); } /* execute pre-train script from vbios */ - nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc); + nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); /* start off at highest link rate supported by encoder and display */ while (*link_bw > nv_encoder->dp.link_bw) @@ -567,7 +610,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); /* execute post-train script from vbios */ - nouveau_bios_run_init_table(dev, ROM16(bios[8]), dp.dcb, dp.crtc); + nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); /* re-enable hotplug detect */ pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index d269b7ba45c..ecaa4ffbeab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1080,8 +1080,6 @@ extern int get_pll_limits(struct drm_device *, uint32_t limit_match, struct pll_lims *); extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, struct dcb_entry *, int crtc); -extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, - u8 *headerlen); extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, @@ -1103,6 +1101,7 @@ int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, bool nouveau_dp_detect(struct drm_encoder *); bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); +u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); /* nv04_fb.c */ extern int nv04_fb_init(struct drm_device *); |