aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/nvidia
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
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')
-rw-r--r--drivers/video/nvidia/nv_accel.c12
-rw-r--r--drivers/video/nvidia/nv_type.h1
-rw-r--r--drivers/video/nvidia/nvidia.c115
3 files changed, 97 insertions, 31 deletions
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
index f377a29ec97a..4aefb8f41637 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/nvidia/nv_accel.c
@@ -300,6 +300,9 @@ int nvidiafb_sync(struct fb_info *info)
300{ 300{
301 struct nvidia_par *par = info->par; 301 struct nvidia_par *par = info->par;
302 302
303 if (info->state != FBINFO_STATE_RUNNING)
304 return 0;
305
303 if (!par->lockup) 306 if (!par->lockup)
304 NVFlush(par); 307 NVFlush(par);
305 308
@@ -313,6 +316,9 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
313{ 316{
314 struct nvidia_par *par = info->par; 317 struct nvidia_par *par = info->par;
315 318
319 if (info->state != FBINFO_STATE_RUNNING)
320 return;
321
316 if (par->lockup) 322 if (par->lockup)
317 return cfb_copyarea(info, region); 323 return cfb_copyarea(info, region);
318 324
@@ -329,6 +335,9 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
329 struct nvidia_par *par = info->par; 335 struct nvidia_par *par = info->par;
330 u32 color; 336 u32 color;
331 337
338 if (info->state != FBINFO_STATE_RUNNING)
339 return;
340
332 if (par->lockup) 341 if (par->lockup)
333 return cfb_fillrect(info, rect); 342 return cfb_fillrect(info, rect);
334 343
@@ -412,6 +421,9 @@ void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
412{ 421{
413 struct nvidia_par *par = info->par; 422 struct nvidia_par *par = info->par;
414 423
424 if (info->state != FBINFO_STATE_RUNNING)
425 return;
426
415 if (image->depth == 1 && !par->lockup) 427 if (image->depth == 1 && !par->lockup)
416 nvidiafb_mono_color_expand(info, image); 428 nvidiafb_mono_color_expand(info, image);
417 else 429 else
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
index e4a5b1da71c4..acdc26693402 100644
--- a/drivers/video/nvidia/nv_type.h
+++ b/drivers/video/nvidia/nv_type.h
@@ -129,6 +129,7 @@ struct nvidia_par {
129 int fpHeight; 129 int fpHeight;
130 int PanelTweak; 130 int PanelTweak;
131 int paneltweak; 131 int paneltweak;
132 int pm_state;
132 u32 crtcSync_read; 133 u32 crtcSync_read;
133 u32 fpSyncs; 134 u32 fpSyncs;
134 u32 dmaPut; 135 u32 dmaPut;
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/* ------------------------------------------------------------------------- *