aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/nvidia/nvidia.c
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2006-03-27 04:17:22 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:55 -0500
commit7a07cd786dbd0111b9dd977e114438220cb4eee5 (patch)
tree5aba3ac594def43624d6014b384b228029b6418c /drivers/video/nvidia/nvidia.c
parent15bdab959c9bb909c0317480dd9b35748a8f7887 (diff)
[PATCH] nvidiafb: add suspend and resume hooks
Add suspend and resume hooks to make software suspend more reliable. Resuming from standby should generally work. Resuming from mem and from disk requires that the GPU is disabled. Adding these to the suspend script... fbset -accel false -a /* suspend here */ fbset -accel true -a ... should generally work. In addition, resuming from mem requires that the video card has to be POSTed by the BIOS or some other utility. Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/nvidia/nvidia.c')
-rw-r--r--drivers/video/nvidia/nvidia.c115
1 files changed, 84 insertions, 31 deletions
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index a7c4e5e8ead6..c758b386f146 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -21,6 +21,7 @@
21#include <linux/fb.h> 21#include <linux/fb.h>
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/console.h>
24#ifdef CONFIG_MTRR 25#ifdef CONFIG_MTRR
25#include <asm/mtrr.h> 26#include <asm/mtrr.h>
26#endif 27#endif
@@ -615,6 +616,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par,
615 return tweak; 616 return tweak;
616} 617}
617 618
619static void nvidia_vga_protect(struct nvidia_par *par, int on)
620{
621 unsigned char tmp;
622
623 if (on) {
624 /*
625 * Turn off screen and disable sequencer.
626 */
627 tmp = NVReadSeq(par, 0x01);
628
629 NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
630 NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
631 } else {
632 /*
633 * Reenable sequencer, then turn on screen.
634 */
635
636 tmp = NVReadSeq(par, 0x01);
637
638 NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
639 NVWriteSeq(par, 0x00, 0x03); /* End Reset */
640 }
641}
642
618static void nvidia_save_vga(struct nvidia_par *par, 643static void nvidia_save_vga(struct nvidia_par *par,
619 struct _riva_hw_state *state) 644 struct _riva_hw_state *state)
620{ 645{
@@ -643,9 +668,9 @@ static void nvidia_save_vga(struct nvidia_par *par,
643 668
644#undef DUMP_REG 669#undef DUMP_REG
645 670
646static void nvidia_write_regs(struct nvidia_par *par) 671static void nvidia_write_regs(struct nvidia_par *par,
672 struct _riva_hw_state *state)
647{ 673{
648 struct _riva_hw_state *state = &par->ModeReg;
649 int i; 674 int i;
650 675
651 NVTRACE_ENTER(); 676 NVTRACE_ENTER();
@@ -694,32 +719,6 @@ static void nvidia_write_regs(struct nvidia_par *par)
694 NVTRACE_LEAVE(); 719 NVTRACE_LEAVE();
695} 720}
696 721
697static void nvidia_vga_protect(struct nvidia_par *par, int on)
698{
699 unsigned char tmp;
700
701 if (on) {
702 /*
703 * Turn off screen and disable sequencer.
704 */
705 tmp = NVReadSeq(par, 0x01);
706
707 NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
708 NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
709 } else {
710 /*
711 * Reenable sequencer, then turn on screen.
712 */
713
714 tmp = NVReadSeq(par, 0x01);
715
716 NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
717 NVWriteSeq(par, 0x00, 0x03); /* End Reset */
718 }
719}
720
721
722
723static int nvidia_calc_regs(struct fb_info *info) 722static int nvidia_calc_regs(struct fb_info *info)
724{ 723{
725 struct nvidia_par *par = info->par; 724 struct nvidia_par *par = info->par;
@@ -1068,7 +1067,8 @@ static int nvidiafb_set_par(struct fb_info *info)
1068 1067
1069 nvidia_vga_protect(par, 1); 1068 nvidia_vga_protect(par, 1);
1070 1069
1071 nvidia_write_regs(par); 1070 nvidia_write_regs(par, &par->ModeReg);
1071 NVSetStartAddress(par, 0);
1072 1072
1073#if defined (__BIG_ENDIAN) 1073#if defined (__BIG_ENDIAN)
1074 /* turn on LFB swapping */ 1074 /* turn on LFB swapping */
@@ -1377,6 +1377,57 @@ static struct fb_ops nvidia_fb_ops = {
1377 .fb_sync = nvidiafb_sync, 1377 .fb_sync = nvidiafb_sync,
1378}; 1378};
1379 1379
1380#ifdef CONFIG_PM
1381static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
1382{
1383 struct fb_info *info = pci_get_drvdata(dev);
1384 struct nvidia_par *par = info->par;
1385
1386 acquire_console_sem();
1387 par->pm_state = state.event;
1388
1389 if (state.event == PM_EVENT_FREEZE) {
1390 dev->dev.power.power_state = state;
1391 } else {
1392 fb_set_suspend(info, 1);
1393 nvidiafb_blank(FB_BLANK_POWERDOWN, info);
1394 nvidia_write_regs(par, &par->SavedReg);
1395 pci_save_state(dev);
1396 pci_disable_device(dev);
1397 pci_set_power_state(dev, pci_choose_state(dev, state));
1398 }
1399
1400 release_console_sem();
1401 return 0;
1402}
1403
1404static int nvidiafb_resume(struct pci_dev *dev)
1405{
1406 struct fb_info *info = pci_get_drvdata(dev);
1407 struct nvidia_par *par = info->par;
1408
1409 acquire_console_sem();
1410 pci_set_power_state(dev, PCI_D0);
1411
1412 if (par->pm_state != PM_EVENT_FREEZE) {
1413 pci_restore_state(dev);
1414 pci_enable_device(dev);
1415 pci_set_master(dev);
1416 }
1417
1418 par->pm_state = PM_EVENT_ON;
1419 nvidiafb_set_par(info);
1420 fb_set_suspend (info, 0);
1421 nvidiafb_blank(FB_BLANK_UNBLANK, info);
1422
1423 release_console_sem();
1424 return 0;
1425}
1426#else
1427#define nvidiafb_suspend NULL
1428#define nvidiafb_resume NULL
1429#endif
1430
1380static int __devinit nvidia_set_fbinfo(struct fb_info *info) 1431static int __devinit nvidia_set_fbinfo(struct fb_info *info)
1381{ 1432{
1382 struct fb_monspecs *specs = &info->monspecs; 1433 struct fb_monspecs *specs = &info->monspecs;
@@ -1798,8 +1849,10 @@ static int __devinit nvidiafb_setup(char *options)
1798static struct pci_driver nvidiafb_driver = { 1849static struct pci_driver nvidiafb_driver = {
1799 .name = "nvidiafb", 1850 .name = "nvidiafb",
1800 .id_table = nvidiafb_pci_tbl, 1851 .id_table = nvidiafb_pci_tbl,
1801 .probe = nvidiafb_probe, 1852 .probe = nvidiafb_probe,
1802 .remove = __exit_p(nvidiafb_remove), 1853 .suspend = nvidiafb_suspend,
1854 .resume = nvidiafb_resume,
1855 .remove = __exit_p(nvidiafb_remove),
1803}; 1856};
1804 1857
1805/* ------------------------------------------------------------------------- * 1858/* ------------------------------------------------------------------------- *