#include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/console.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
    return tweak;
 }
 
+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 void nvidia_save_vga(struct nvidia_par *par,
                            struct _riva_hw_state *state)
 {
 
 #undef DUMP_REG
 
-static void nvidia_write_regs(struct nvidia_par *par)
+static void nvidia_write_regs(struct nvidia_par *par,
+                             struct _riva_hw_state *state)
 {
-       struct _riva_hw_state *state = &par->ModeReg;
        int i;
 
        NVTRACE_ENTER();
        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;
 
        nvidia_vga_protect(par, 1);
 
-       nvidia_write_regs(par);
+       nvidia_write_regs(par, &par->ModeReg);
+       NVSetStartAddress(par, 0);
 
 #if defined (__BIG_ENDIAN)
        /* turn on LFB swapping */
        .fb_sync        = nvidiafb_sync,
 };
 
+#ifdef CONFIG_PM
+static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct nvidia_par *par = info->par;
+
+       acquire_console_sem();
+       par->pm_state = state.event;
+
+       if (state.event == PM_EVENT_FREEZE) {
+               dev->dev.power.power_state = state;
+       } else {
+               fb_set_suspend(info, 1);
+               nvidiafb_blank(FB_BLANK_POWERDOWN, info);
+               nvidia_write_regs(par, &par->SavedReg);
+               pci_save_state(dev);
+               pci_disable_device(dev);
+               pci_set_power_state(dev, pci_choose_state(dev, state));
+       }
+
+       release_console_sem();
+       return 0;
+}
+
+static int nvidiafb_resume(struct pci_dev *dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+       struct nvidia_par *par = info->par;
+
+       acquire_console_sem();
+       pci_set_power_state(dev, PCI_D0);
+
+       if (par->pm_state != PM_EVENT_FREEZE) {
+               pci_restore_state(dev);
+               pci_enable_device(dev);
+               pci_set_master(dev);
+       }
+
+       par->pm_state = PM_EVENT_ON;
+       nvidiafb_set_par(info);
+       fb_set_suspend (info, 0);
+       nvidiafb_blank(FB_BLANK_UNBLANK, info);
+
+       release_console_sem();
+       return 0;
+}
+#else
+#define nvidiafb_suspend NULL
+#define nvidiafb_resume NULL
+#endif
+
 static int __devinit nvidia_set_fbinfo(struct fb_info *info)
 {
        struct fb_monspecs *specs = &info->monspecs;
 static struct pci_driver nvidiafb_driver = {
        .name = "nvidiafb",
        .id_table = nvidiafb_pci_tbl,
-       .probe = nvidiafb_probe,
-       .remove = __exit_p(nvidiafb_remove),
+       .probe    = nvidiafb_probe,
+       .suspend  = nvidiafb_suspend,
+       .resume   = nvidiafb_resume,
+       .remove   = __exit_p(nvidiafb_remove),
 };
 
 /* ------------------------------------------------------------------------- *