Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Antonino A. Daplas and committed by
Linus Torvalds
7a07cd78 15bdab95

+97 -31
+12
drivers/video/nvidia/nv_accel.c
··· 300 300 { 301 301 struct nvidia_par *par = info->par; 302 302 303 + if (info->state != FBINFO_STATE_RUNNING) 304 + return 0; 305 + 303 306 if (!par->lockup) 304 307 NVFlush(par); 305 308 ··· 315 312 void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) 316 313 { 317 314 struct nvidia_par *par = info->par; 315 + 316 + if (info->state != FBINFO_STATE_RUNNING) 317 + return; 318 318 319 319 if (par->lockup) 320 320 return cfb_copyarea(info, region); ··· 334 328 { 335 329 struct nvidia_par *par = info->par; 336 330 u32 color; 331 + 332 + if (info->state != FBINFO_STATE_RUNNING) 333 + return; 337 334 338 335 if (par->lockup) 339 336 return cfb_fillrect(info, rect); ··· 420 411 void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image) 421 412 { 422 413 struct nvidia_par *par = info->par; 414 + 415 + if (info->state != FBINFO_STATE_RUNNING) 416 + return; 423 417 424 418 if (image->depth == 1 && !par->lockup) 425 419 nvidiafb_mono_color_expand(info, image);
+1
drivers/video/nvidia/nv_type.h
··· 129 129 int fpHeight; 130 130 int PanelTweak; 131 131 int paneltweak; 132 + int pm_state; 132 133 u32 crtcSync_read; 133 134 u32 fpSyncs; 134 135 u32 dmaPut;
+84 -31
drivers/video/nvidia/nvidia.c
··· 21 21 #include <linux/fb.h> 22 22 #include <linux/init.h> 23 23 #include <linux/pci.h> 24 + #include <linux/console.h> 24 25 #ifdef CONFIG_MTRR 25 26 #include <asm/mtrr.h> 26 27 #endif ··· 616 615 return tweak; 617 616 } 618 617 618 + static void nvidia_vga_protect(struct nvidia_par *par, int on) 619 + { 620 + unsigned char tmp; 621 + 622 + if (on) { 623 + /* 624 + * Turn off screen and disable sequencer. 625 + */ 626 + tmp = NVReadSeq(par, 0x01); 627 + 628 + NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ 629 + NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ 630 + } else { 631 + /* 632 + * Reenable sequencer, then turn on screen. 633 + */ 634 + 635 + tmp = NVReadSeq(par, 0x01); 636 + 637 + NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ 638 + NVWriteSeq(par, 0x00, 0x03); /* End Reset */ 639 + } 640 + } 641 + 619 642 static void nvidia_save_vga(struct nvidia_par *par, 620 643 struct _riva_hw_state *state) 621 644 { ··· 668 643 669 644 #undef DUMP_REG 670 645 671 - static void nvidia_write_regs(struct nvidia_par *par) 646 + static void nvidia_write_regs(struct nvidia_par *par, 647 + struct _riva_hw_state *state) 672 648 { 673 - struct _riva_hw_state *state = &par->ModeReg; 674 649 int i; 675 650 676 651 NVTRACE_ENTER(); ··· 718 693 719 694 NVTRACE_LEAVE(); 720 695 } 721 - 722 - static void nvidia_vga_protect(struct nvidia_par *par, int on) 723 - { 724 - unsigned char tmp; 725 - 726 - if (on) { 727 - /* 728 - * Turn off screen and disable sequencer. 729 - */ 730 - tmp = NVReadSeq(par, 0x01); 731 - 732 - NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ 733 - NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ 734 - } else { 735 - /* 736 - * Reenable sequencer, then turn on screen. 737 - */ 738 - 739 - tmp = NVReadSeq(par, 0x01); 740 - 741 - NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ 742 - NVWriteSeq(par, 0x00, 0x03); /* End Reset */ 743 - } 744 - } 745 - 746 - 747 696 748 697 static int nvidia_calc_regs(struct fb_info *info) 749 698 { ··· 1067 1068 1068 1069 nvidia_vga_protect(par, 1); 1069 1070 1070 - nvidia_write_regs(par); 1071 + nvidia_write_regs(par, &par->ModeReg); 1072 + NVSetStartAddress(par, 0); 1071 1073 1072 1074 #if defined (__BIG_ENDIAN) 1073 1075 /* turn on LFB swapping */ ··· 1376 1376 .fb_cursor = nvidiafb_cursor, 1377 1377 .fb_sync = nvidiafb_sync, 1378 1378 }; 1379 + 1380 + #ifdef CONFIG_PM 1381 + static 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 + 1404 + static 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 1379 1430 1380 1431 static int __devinit nvidia_set_fbinfo(struct fb_info *info) 1381 1432 { ··· 1849 1798 static struct pci_driver nvidiafb_driver = { 1850 1799 .name = "nvidiafb", 1851 1800 .id_table = nvidiafb_pci_tbl, 1852 - .probe = nvidiafb_probe, 1853 - .remove = __exit_p(nvidiafb_remove), 1801 + .probe = nvidiafb_probe, 1802 + .suspend = nvidiafb_suspend, 1803 + .resume = nvidiafb_resume, 1804 + .remove = __exit_p(nvidiafb_remove), 1854 1805 }; 1855 1806 1856 1807 /* ------------------------------------------------------------------------- *