config FB_NVIDIA_I2C
        bool "Enable DDC Support"
-       depends on FB_NVIDIA && !PPC_OF
+       depends on FB_NVIDIA
        help
          This enables I2C support for nVidia Chipsets.  This is used
          only for getting EDID information from the attached display
 
 #include "nv_local.h"
 #include "nv_proto.h"
 
-void nvidia_create_i2c_busses(struct nvidia_par *par) {}
-void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
+#include "../edid.h"
 
-int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
+int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
 {
        struct nvidia_par *par = info->par;
-       struct device_node *dp;
+       struct device_node *parent, *dp;
        unsigned char *pedid = NULL;
-       unsigned char *disptype = NULL;
        static char *propnames[] = {
-               "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+               "DFP,EDID", "LCD,EDID", "EDID", "EDID1",
+               "EDID,B", "EDID,A", NULL };
        int i;
 
-       dp = pci_device_to_OF_node(par->pci_dev);
-       for (; dp != NULL; dp = dp->child) {
-               disptype = (unsigned char *)get_property(dp, "display-type", NULL);
-               if (disptype == NULL)
-                       continue;
-               if (strncmp(disptype, "LCD", 3) != 0)
-                       continue;
+       parent = pci_device_to_OF_node(par->pci_dev);
+       if (parent == NULL)
+               return -1;
+       if (par->twoHeads) {
+               char *pname;
+               int len;
+
+               for (dp = NULL;
+                    (dp = of_get_next_child(parent, dp)) != NULL;) {
+                       pname = (char *)get_property(dp, "name", NULL);
+                       if (!pname)
+                               continue;
+                       len = strlen(pname);
+                       if ((pname[len-1] == 'A' && conn == 1) ||
+                           (pname[len-1] == 'B' && conn == 2)) {
+                               for (i = 0; propnames[i] != NULL; ++i) {
+                                       pedid = (unsigned char *)
+                                               get_property(dp, propnames[i],
+                                                            NULL);
+                                       if (pedid != NULL)
+                                               break;
+                               }
+                               of_node_put(dp);
+                               break;
+                       }
+               }
+       }
+       if (pedid == NULL) {
                for (i = 0; propnames[i] != NULL; ++i) {
                        pedid = (unsigned char *)
-                               get_property(dp, propnames[i], NULL);
-                       if (pedid != NULL) {
-                               *out_edid = pedid;
-                               return 0;
-                       }
+                               get_property(parent, propnames[i], NULL);
+                       if (pedid != NULL)
+                               break;
                }
        }
-       return 1;
+       if (pedid) {
+               *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+               if (*out_edid == NULL)
+                       return -1;
+               memcpy(*out_edid, pedid, EDID_LENGTH);
+               printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
+               return 0;
+       }
+       return -1;
 }
 
 void NVLockUnlock(struct nvidia_par *par, int);
 
 /* in nvidia-i2c.c */
-#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
+#ifdef CONFIG_FB_NVIDIA_I2C
 void nvidia_create_i2c_busses(struct nvidia_par *par);
 void nvidia_delete_i2c_busses(struct nvidia_par *par);
 int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
 #else
 #define nvidia_create_i2c_busses(...)
 #define nvidia_delete_i2c_busses(...)
-#define nvidia_probe_i2c_connector(p, c, edid) \
-do {                                           \
-       *(edid) = NULL;                        \
-} while(0)
+#define nvidia_probe_i2c_connector(p, c, edid) (-1)
+#endif
+
+#ifdef CONFIG_FB_OF
+int nvidia_probe_of_connector(struct fb_info *info, int conn,
+                             u8 ** out_edid);
+#else
+#define nvidia_probe_of_connector(p, c, edid)  (-1)
 #endif
 
 /* in nv_accel.c */
 
        present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
 
        if (present)
-               printk("nvidiafb: CRTC%i found\n", output);
+               printk("nvidiafb: CRTC%i analog found\n", output);
        else
-               printk("nvidiafb: CRTC%i not found\n", output);
+               printk("nvidiafb: CRTC%i analog not found\n", output);
 
        NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
                0x0000EFFF);
        int FlatPanel = -1;     /* really means the CRTC is slaved */
        int Television = 0;
 
+       memset(&monitorA, 0, sizeof(struct fb_monspecs));
+       memset(&monitorB, 0, sizeof(struct fb_monspecs));
+
        par->PRAMIN = par->REGS + (0x00710000 / 4);
        par->PCRTC0 = par->REGS + (0x00600000 / 4);
        par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
        nvidia_create_i2c_busses(par);
        if (!par->twoHeads) {
                par->CRTCnumber = 0;
-               nvidia_probe_i2c_connector(info, 1, &edidA);
+               if (nvidia_probe_i2c_connector(info, 1, &edidA))
+                       nvidia_probe_of_connector(info, 1, &edidA);
                if (edidA && !fb_parse_edid(edidA, &var)) {
                        printk("nvidiafb: EDID found from BUS1\n");
                        monA = &monitorA;
                oldhead = NV_RD32(par->PCRTC0, 0x00000860);
                NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
 
-               nvidia_probe_i2c_connector(info, 1, &edidA);
+               if (nvidia_probe_i2c_connector(info, 1, &edidA))
+                       nvidia_probe_of_connector(info, 1, &edidA);
                if (edidA && !fb_parse_edid(edidA, &var)) {
                        printk("nvidiafb: EDID found from BUS1\n");
                        monA = &monitorA;
                        fb_edid_to_monspecs(edidA, monA);
                }
 
-               nvidia_probe_i2c_connector(info, 2, &edidB);
+               if (nvidia_probe_i2c_connector(info, 2, &edidB))
+                       nvidia_probe_of_connector(info, 2, &edidB);
                if (edidB && !fb_parse_edid(edidB, &var)) {
                        printk("nvidiafb: EDID found from BUS2\n");
                        monB = &monitorB;
 
        NVTRACE_LEAVE();
 }
 
+#undef DUMP_REG
+
 static void nvidia_write_regs(struct nvidia_par *par)
 {
        struct _riva_hw_state *state = &par->ModeReg;
        int i;
 
        NVTRACE_ENTER();
-       NVWriteCrtc(par, 0x11, 0x00);
-
-       NVLockUnlock(par, 0);
 
        NVLoadStateExt(par, state);
 
        NVWriteMiscOut(par, state->misc_output);
 
+       for (i = 1; i < NUM_SEQ_REGS; i++) {
+#ifdef DUMP_REG
+               printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
+#endif
+               NVWriteSeq(par, i, state->seq[i]);
+       }
+
+       /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+       NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
+
        for (i = 0; i < NUM_CRT_REGS; i++) {
                switch (i) {
                case 0x19:
                case 0x20 ... 0x40:
                        break;
                default:
+#ifdef DUMP_REG
+                       printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
+#endif
                        NVWriteCrtc(par, i, state->crtc[i]);
                }
        }
 
-       for (i = 0; i < NUM_ATC_REGS; i++)
-               NVWriteAttr(par, i, state->attr[i]);
-
-       for (i = 0; i < NUM_GRC_REGS; i++)
+       for (i = 0; i < NUM_GRC_REGS; i++) {
+#ifdef DUMP_REG
+               printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
+#endif
                NVWriteGr(par, i, state->gra[i]);
+       }
+
+       for (i = 0; i < NUM_ATC_REGS; i++) {
+#ifdef DUMP_REG
+               printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
+#endif
+               NVWriteAttr(par, i, state->attr[i]);
+       }
 
-       for (i = 0; i < NUM_SEQ_REGS; i++)
-               NVWriteSeq(par, i, state->seq[i]);
        NVTRACE_LEAVE();
 }
 
+static void nvidia_vga_protect(struct nvidia_par *par, int on)
+{
+       unsigned char tmp;
+
+       if (on) {
+               /*
+                * Turn off screen and disable sequencer.
+                */
+               tmp = NVReadSeq(par, 0x01);
+
+               NVWriteSeq(par, 0x00, 0x01);            /* Synchronous Reset */
+               NVWriteSeq(par, 0x01, tmp | 0x20);      /* disable the display */
+       } else {
+               /*
+                * Reenable sequencer, then turn on screen.
+                */
+
+               tmp = NVReadSeq(par, 0x01);
+
+               NVWriteSeq(par, 0x01, tmp & ~0x20);     /* reenable display */
+               NVWriteSeq(par, 0x00, 0x03);            /* End Reset */
+       }
+}
+
+
+
 static int nvidia_calc_regs(struct fb_info *info)
 {
        struct nvidia_par *par = info->par;
        for (i = 0; i < 0x10; i++)
                state->attr[i] = i;
        state->attr[0x10] = 0x41;
-       state->attr[0x11] = 0x01;
+       state->attr[0x11] = 0xff;
        state->attr[0x12] = 0x0f;
        state->attr[0x13] = 0x00;
        state->attr[0x14] = 0x00;
 
        nvidia_init_vga(info);
        nvidia_calc_regs(info);
-       nvidia_write_regs(par);
 
        NVLockUnlock(par, 0);
        if (par->twoHeads) {
                NVLockUnlock(par, 0);
        }
 
-       NVWriteCrtc(par, 0x11, 0x00);
+       nvidia_vga_protect(par, 1);
+
+       nvidia_write_regs(par);
+
+#if defined (__BIG_ENDIAN)
+       /* turn on LFB swapping */
+       {
+               unsigned char tmp;
+
+               VGA_WR08(par->PCIO, 0x3d4, 0x46);
+               tmp = VGA_RD08(par->PCIO, 0x3d5);
+               tmp |= (1 << 7);
+               VGA_WR08(par->PCIO, 0x3d5, tmp);
+    }
+#endif
+
        info->fix.line_length = (info->var.xres_virtual *
                                 info->var.bits_per_pixel) >> 3;
        if (info->var.accel_flags) {
 
        par->cursor_reset = 1;
 
-       NVWriteCrtc(par, 0x11, 0xff);
+       nvidia_vga_protect(par, 0);
 
        NVTRACE_LEAVE();
        return 0;