[PATCH] fbcon/fbdev: Move softcursor out of fbdev to fbcon
[safe/jmp/linux-2.6] / drivers / video / nvidia / nvidia.c
index 308defc..cbe165b 100644 (file)
@@ -411,6 +411,7 @@ MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
 
 /* command line data, set in nvidiafb_setup() */
 static int flatpanel __devinitdata = -1;       /* Autodetect later */
+static int fpdither __devinitdata = -1;
 static int forceCRTC __devinitdata = -1;
 static int hwcur __devinitdata = 0;
 static int noaccel __devinitdata = 0;
@@ -627,41 +628,85 @@ static void nvidia_save_vga(struct nvidia_par *par,
        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;
@@ -868,7 +913,7 @@ static void nvidia_init_vga(struct fb_info *info)
        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;
@@ -982,16 +1027,24 @@ static int nvidiafb_set_par(struct fb_info *info)
        NVTRACE_ENTER();
 
        NVLockUnlock(par, 1);
-       if (!par->FlatPanel || (info->var.bits_per_pixel != 24) ||
-           !par->twoHeads)
+       if (!par->FlatPanel || !par->twoHeads)
                par->FPDither = 0;
 
+       if (par->FPDither < 0) {
+               if ((par->Chipset & 0x0ff0) == 0x0110)
+                       par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528)
+                                          & 0x00010000);
+               else
+                       par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
+               printk(KERN_INFO PFX "Flat panel dithering %s\n",
+                      par->FPDither ? "enabled" : "disabled");
+       }
+
        info->fix.visual = (info->var.bits_per_pixel == 8) ?
            FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 
        nvidia_init_vga(info);
        nvidia_calc_regs(info);
-       nvidia_write_regs(par);
 
        NVLockUnlock(par, 0);
        if (par->twoHeads) {
@@ -1000,7 +1053,22 @@ static int nvidiafb_set_par(struct fb_info *info)
                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) {
@@ -1022,7 +1090,7 @@ static int nvidiafb_set_par(struct fb_info *info)
 
        par->cursor_reset = 1;
 
-       NVWriteCrtc(par, 0x11, 0xff);
+       nvidia_vga_protect(par, 0);
 
        NVTRACE_LEAVE();
        return 0;
@@ -1365,7 +1433,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
        if (!hwcur)
-           info->fbops->fb_cursor = soft_cursor;
+           info->fbops->fb_cursor = NULL;
 
        info->var.accel_flags = (!noaccel);
 
@@ -1490,9 +1558,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
        sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
 
        par->FlatPanel = flatpanel;
-
        if (flatpanel == 1)
                printk(KERN_INFO PFX "flatpanel support enabled\n");
+       par->FPDither = fpdither;
 
        par->CRTCnumber = forceCRTC;
        par->FpScale = (!noscale);
@@ -1671,6 +1739,8 @@ static int __devinit nvidiafb_setup(char *options)
                } else if (!strncmp(this_opt, "nomtrr", 6)) {
                        nomtrr = 1;
 #endif
+               } else if (!strncmp(this_opt, "fpdither:", 9)) {
+                       fpdither = simple_strtol(this_opt+9, NULL, 0);
                } else
                        mode_option = this_opt;
        }
@@ -1717,7 +1787,11 @@ module_exit(nvidiafb_exit);
 module_param(flatpanel, int, 0);
 MODULE_PARM_DESC(flatpanel,
                 "Enables experimental flat panel support for some chipsets. "
-                "(0 or 1=enabled) (default=0)");
+                "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
+module_param(fpdither, int, 0);
+MODULE_PARM_DESC(fpdither,
+                "Enables dithering of flat panel for 6 bits panels. "
+                "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
 module_param(hwcur, int, 0);
 MODULE_PARM_DESC(hwcur,
                 "Enables hardware cursor implementation. (0 or 1=enabled) "