]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_bios.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nouveau_bios.c
index b2293576f27895f3b67e41e563675ab52519b3ad..6bdab891c64ecdee354ad5d10ea9890ec56b96d6 100644 (file)
@@ -1927,7 +1927,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
         * offset      (8  bit): opcode
         * offset + 1  (16 bit): time
         *
-        * Sleep for "time" miliseconds.
+        * Sleep for "time" milliseconds.
         */
 
        unsigned time = ROM16(bios->data[offset + 1]);
@@ -1935,7 +1935,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
        if (!iexec->execute)
                return 3;
 
-       BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n",
+       BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n",
                offset, time);
 
        msleep(time);
@@ -6053,52 +6053,17 @@ static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb)
        return entry;
 }
 
-static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
+static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c,
+                                int heads, int or)
 {
        struct dcb_entry *entry = new_dcb_entry(dcb);
 
-       entry->type = 0;
+       entry->type = type;
        entry->i2c_index = i2c;
        entry->heads = heads;
-       entry->location = DCB_LOC_ON_CHIP;
-       entry->or = 1;
-}
-
-static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
-{
-       struct dcb_entry *entry = new_dcb_entry(dcb);
-
-       entry->type = 2;
-       entry->i2c_index = LEGACY_I2C_PANEL;
-       entry->heads = twoHeads ? 3 : 1;
-       entry->location = !DCB_LOC_ON_CHIP;     /* ie OFF CHIP */
-       entry->or = 1;  /* means |0x10 gets set on CRE_LCD__INDEX */
-       entry->duallink_possible = false; /* SiI164 and co. are single link */
-
-#if 0
-       /*
-        * For dvi-a either crtc probably works, but my card appears to only
-        * support dvi-d.  "nvidia" still attempts to program it for dvi-a,
-        * doing the full fp output setup (program 0x6808.. fp dimension regs,
-        * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
-        * the monitor picks up the mode res ok and lights up, but no pixel
-        * data appears, so the board manufacturer probably connected up the
-        * sync lines, but missed the video traces / components
-        *
-        * with this introduction, dvi-a left as an exercise for the reader.
-        */
-       fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads);
-#endif
-}
-
-static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads)
-{
-       struct dcb_entry *entry = new_dcb_entry(dcb);
-
-       entry->type = 1;
-       entry->i2c_index = LEGACY_I2C_TV;
-       entry->heads = twoHeads ? 3 : 1;
-       entry->location = !DCB_LOC_ON_CHIP;     /* ie OFF CHIP */
+       if (type != OUTPUT_ANALOG)
+               entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
+       entry->or = or;
 }
 
 static bool
@@ -6263,7 +6228,7 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb,
                entry->tvconf.has_component_output = false;
                break;
        case OUTPUT_LVDS:
-               if ((conn & 0x00003f00) != 0x10)
+               if ((conn & 0x00003f00) >> 8 != 0x10)
                        entry->lvdsconf.use_straps_for_mode = true;
                entry->lvdsconf.use_power_scripts = true;
                break;
@@ -6345,6 +6310,9 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
 static bool
 apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct dcb_table *dcb = &dev_priv->vbios.dcb;
+
        /* Dell Precision M6300
         *   DCB entry 2: 02025312 00000010
         *   DCB entry 3: 02026312 00000020
@@ -6362,11 +6330,51 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
                        return false;
        }
 
+       /* GeForce3 Ti 200
+        *
+        * DCB reports an LVDS output that should be TMDS:
+        *   DCB entry 1: f2005014 ffffffff
+        */
+       if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
+               if (*conn == 0xf2005014 && *conf == 0xffffffff) {
+                       fabricate_dcb_output(dcb, OUTPUT_TMDS, 1, 1, 1);
+                       return false;
+               }
+       }
+
        return true;
 }
 
+static void
+fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
+{
+       struct dcb_table *dcb = &bios->dcb;
+       int all_heads = (nv_two_heads(dev) ? 3 : 1);
+
+#ifdef __powerpc__
+       /* Apple iMac G4 NV17 */
+       if (of_machine_is_compatible("PowerMac4,5")) {
+               fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1);
+               fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2);
+               return;
+       }
+#endif
+
+       /* Make up some sane defaults */
+       fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1);
+
+       if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
+               fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV,
+                                    all_heads, 0);
+
+       else if (bios->tmds.output0_script_ptr ||
+                bios->tmds.output1_script_ptr)
+               fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL,
+                                    all_heads, 1);
+}
+
 static int
-parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct dcb_table *dcb = &bios->dcb;
@@ -6386,12 +6394,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
 
        /* this situation likely means a really old card, pre DCB */
        if (dcbptr == 0x0) {
-               NV_INFO(dev, "Assuming a CRT output exists\n");
-               fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
-
-               if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
-                       fabricate_tv_output(dcb, twoHeads);
-
+               fabricate_dcb_encoder_table(dev, bios);
                return 0;
        }
 
@@ -6451,21 +6454,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
                 */
                NV_TRACEWARN(dev, "No useful information in BIOS output table; "
                                  "adding all possible outputs\n");
-               fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
-
-               /*
-                * Attempt to detect TV before DVI because the test
-                * for the former is more accurate and it rules the
-                * latter out.
-                */
-               if (nv04_tv_identify(dev,
-                                    bios->legacy.i2c_indices.tv) >= 0)
-                       fabricate_tv_output(dcb, twoHeads);
-
-               else if (bios->tmds.output0_script_ptr ||
-                        bios->tmds.output1_script_ptr)
-                       fabricate_dvi_i_output(dcb, twoHeads);
-
+               fabricate_dcb_encoder_table(dev, bios);
                return 0;
        }
 
@@ -6859,7 +6848,7 @@ nouveau_bios_init(struct drm_device *dev)
        if (ret)
                return ret;
 
-       ret = parse_dcb_table(dev, bios, nv_two_heads(dev));
+       ret = parse_dcb_table(dev, bios);
        if (ret)
                return ret;