Merge branch 'drm-ttm-unmappable' into drm-core-next
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nouveau_bios.c
index 075eb89..abc382a 100644 (file)
@@ -2573,48 +2573,34 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         * each GPIO according to various values listed in each entry
         */
 
-       const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
+       struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
        const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
-       const uint8_t *gpio_table = &bios->data[bios->dcb.gpio_table_ptr];
-       const uint8_t *gpio_entry;
        int i;
 
-       if (!iexec->execute)
-               return 1;
-
-       if (bios->dcb.version != 0x40) {
-               NV_ERROR(bios->dev, "DCB table not version 4.0\n");
-               return 0;
+       if (dev_priv->card_type != NV_50) {
+               NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
+               return -ENODEV;
        }
 
-       if (!bios->dcb.gpio_table_ptr) {
-               NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
-               return 0;
-       }
+       if (!iexec->execute)
+               return 1;
 
-       gpio_entry = gpio_table + gpio_table[1];
-       for (i = 0; i < gpio_table[2]; i++, gpio_entry += gpio_table[3]) {
-               uint32_t entry = ROM32(gpio_entry[0]), r, s, v;
-               int line = (entry & 0x0000001f);
+       for (i = 0; i < bios->dcb.gpio.entries; i++) {
+               struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
+               uint32_t r, s, v;
 
-               BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry);
+               BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);
 
-               if ((entry & 0x0000ff00) == 0x0000ff00)
-                       continue;
+               nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
 
-               r = nv50_gpio_reg[line >> 3];
-               s = (line & 0x07) << 2;
-               v = bios_rd32(bios, r) & ~(0x00000003 << s);
-               if (entry & 0x01000000)
-                       v |= (((entry & 0x60000000) >> 29) ^ 2) << s;
-               else
-                       v |= (((entry & 0x18000000) >> 27) ^ 2) << s;
-               bios_wr32(bios, r, v);
-
-               r = nv50_gpio_ctl[line >> 4];
-               s = (line & 0x0f);
+               /* The NVIDIA binary driver doesn't appear to actually do
+                * any of this, my VBIOS does however.
+                */
+               /* Not a clue, needs de-magicing */
+               r = nv50_gpio_ctl[gpio->line >> 4];
+               s = (gpio->line & 0x0f);
                v = bios_rd32(bios, r) & ~(0x00010001 << s);
-               switch ((entry & 0x06000000) >> 25) {
+               switch ((gpio->entry & 0x06000000) >> 25) {
                case 1:
                        v |= (0x00000001 << s);
                        break;
@@ -3659,6 +3645,21 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
                break;
        }
 
+       /* Dell Latitude D620 reports a too-high value for the dual-link
+        * transition freq, causing us to program the panel incorrectly.
+        *
+        * It doesn't appear the VBIOS actually uses its transition freq
+        * (90000kHz), instead it uses the "Number of LVDS channels" field
+        * out of the panel ID structure (http://www.spwg.org/).
+        *
+        * For the moment, a quirk will do :)
+        */
+       if ((dev->pdev->device == 0x01d7) &&
+           (dev->pdev->subsystem_vendor == 0x1028) &&
+           (dev->pdev->subsystem_device == 0x01c2)) {
+               bios->fp.duallink_transition_clk = 80000;
+       }
+
        /* set dual_link flag for EDID case */
        if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
                bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk);
@@ -5067,25 +5068,25 @@ parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
        gpio->tag = tag;
        gpio->line = line;
        gpio->invert = flags != 4;
+       gpio->entry = ent;
 }
 
 static void
 parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset)
 {
+       uint32_t entry = ROM32(bios->data[offset]);
        struct dcb_gpio_entry *gpio;
-       uint32_t ent = ROM32(bios->data[offset]);
-       uint8_t line = ent & 0x1f,
-               tag = ent >> 8 & 0xff;
 
-       if (tag == 0xff)
+       if ((entry & 0x0000ff00) == 0x0000ff00)
                return;
 
        gpio = new_gpio_entry(bios);
-
-       /* Currently unused, we may need more fields parsed at some
-        * point. */
-       gpio->tag = tag;
-       gpio->line = line;
+       gpio->tag = (entry & 0x0000ff00) >> 8;
+       gpio->line = (entry & 0x0000001f) >> 0;
+       gpio->state_default = (entry & 0x01000000) >> 24;
+       gpio->state[0] = (entry & 0x18000000) >> 27;
+       gpio->state[1] = (entry & 0x60000000) >> 29;
+       gpio->entry = entry;
 }
 
 static void