|
@@ -21,6 +21,7 @@
|
|
|
#include <linux/fb.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/pci.h>
|
|
|
+#include <linux/console.h>
|
|
|
#ifdef CONFIG_MTRR
|
|
|
#include <asm/mtrr.h>
|
|
|
#endif
|
|
@@ -615,6 +616,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par,
|
|
|
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)
|
|
|
{
|
|
@@ -643,9 +668,9 @@ static void nvidia_save_vga(struct nvidia_par *par,
|
|
|
|
|
|
#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();
|
|
@@ -694,32 +719,6 @@ static void nvidia_write_regs(struct nvidia_par *par)
|
|
|
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;
|
|
@@ -1068,7 +1067,8 @@ static int nvidiafb_set_par(struct fb_info *info)
|
|
|
|
|
|
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 */
|
|
@@ -1377,6 +1377,57 @@ static struct fb_ops nvidia_fb_ops = {
|
|
|
.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;
|
|
@@ -1798,8 +1849,10 @@ static int __devinit nvidiafb_setup(char *options)
|
|
|
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),
|
|
|
};
|
|
|
|
|
|
/* ------------------------------------------------------------------------- *
|