drm/nouveau/dp: return master dp table pointer too when looking up encoder
authorBen Skeggs <bskeggs@redhat.com>
Fri, 5 Aug 2011 04:07:04 +0000 (14:07 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 20 Sep 2011 06:11:18 +0000 (16:11 +1000)
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>
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.h
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_drv.h

index 73b590a71949ab8c70a97531a9457be934d9402e..58b2535e3b6bfac639b34b93bc4bbcc7735381d2 100644 (file)
@@ -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;
 }
index b28f0bceaed4470a52d918861e5cd1d5727691f5..8adb69e4a6b124f2034e0e80ed0ac97ca13a1b9f 100644 (file)
@@ -291,7 +291,6 @@ struct nvbios {
                struct dcb_entry *output;
                int crtc;
                uint16_t script_table_ptr;
-               uint16_t dp_table_ptr;
        } display;
 
        struct {
index d3552e76664737ec33333afc94d4119b49870a9b..25ecb776c7bc745f402ed9fedf4e2f67e161deb1 100644 (file)
@@ -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);
index d269b7ba45cc5c5f06e224ea5e7c2101f316a71c..ecaa4ffbeab9906b3c816d212cedeec5f6facc03 100644 (file)
@@ -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 *);