diff options
Diffstat (limited to 'drivers/video/nvidia/nvidia.c')
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 119 |
1 files changed, 86 insertions, 33 deletions
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 7258b3245316..093ab9977c7c 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 |
@@ -297,6 +298,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { | |||
297 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 298 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
298 | {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT, | 299 | {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT, |
299 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 300 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
301 | {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280, | ||
302 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
300 | {PCI_VENDOR_ID_NVIDIA, 0x0252, | 303 | {PCI_VENDOR_ID_NVIDIA, 0x0252, |
301 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 304 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
302 | {PCI_VENDOR_ID_NVIDIA, 0x0313, | 305 | {PCI_VENDOR_ID_NVIDIA, 0x0313, |
@@ -616,6 +619,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par, | |||
616 | return tweak; | 619 | return tweak; |
617 | } | 620 | } |
618 | 621 | ||
622 | static void nvidia_vga_protect(struct nvidia_par *par, int on) | ||
623 | { | ||
624 | unsigned char tmp; | ||
625 | |||
626 | if (on) { | ||
627 | /* | ||
628 | * Turn off screen and disable sequencer. | ||
629 | */ | ||
630 | tmp = NVReadSeq(par, 0x01); | ||
631 | |||
632 | NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ | ||
633 | NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ | ||
634 | } else { | ||
635 | /* | ||
636 | * Reenable sequencer, then turn on screen. | ||
637 | */ | ||
638 | |||
639 | tmp = NVReadSeq(par, 0x01); | ||
640 | |||
641 | NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ | ||
642 | NVWriteSeq(par, 0x00, 0x03); /* End Reset */ | ||
643 | } | ||
644 | } | ||
645 | |||
619 | static void nvidia_save_vga(struct nvidia_par *par, | 646 | static void nvidia_save_vga(struct nvidia_par *par, |
620 | struct _riva_hw_state *state) | 647 | struct _riva_hw_state *state) |
621 | { | 648 | { |
@@ -644,9 +671,9 @@ static void nvidia_save_vga(struct nvidia_par *par, | |||
644 | 671 | ||
645 | #undef DUMP_REG | 672 | #undef DUMP_REG |
646 | 673 | ||
647 | static void nvidia_write_regs(struct nvidia_par *par) | 674 | static void nvidia_write_regs(struct nvidia_par *par, |
675 | struct _riva_hw_state *state) | ||
648 | { | 676 | { |
649 | struct _riva_hw_state *state = &par->ModeReg; | ||
650 | int i; | 677 | int i; |
651 | 678 | ||
652 | NVTRACE_ENTER(); | 679 | NVTRACE_ENTER(); |
@@ -695,32 +722,6 @@ static void nvidia_write_regs(struct nvidia_par *par) | |||
695 | NVTRACE_LEAVE(); | 722 | NVTRACE_LEAVE(); |
696 | } | 723 | } |
697 | 724 | ||
698 | static void nvidia_vga_protect(struct nvidia_par *par, int on) | ||
699 | { | ||
700 | unsigned char tmp; | ||
701 | |||
702 | if (on) { | ||
703 | /* | ||
704 | * Turn off screen and disable sequencer. | ||
705 | */ | ||
706 | tmp = NVReadSeq(par, 0x01); | ||
707 | |||
708 | NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ | ||
709 | NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ | ||
710 | } else { | ||
711 | /* | ||
712 | * Reenable sequencer, then turn on screen. | ||
713 | */ | ||
714 | |||
715 | tmp = NVReadSeq(par, 0x01); | ||
716 | |||
717 | NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ | ||
718 | NVWriteSeq(par, 0x00, 0x03); /* End Reset */ | ||
719 | } | ||
720 | } | ||
721 | |||
722 | |||
723 | |||
724 | static int nvidia_calc_regs(struct fb_info *info) | 725 | static int nvidia_calc_regs(struct fb_info *info) |
725 | { | 726 | { |
726 | struct nvidia_par *par = info->par; | 727 | struct nvidia_par *par = info->par; |
@@ -1069,7 +1070,8 @@ static int nvidiafb_set_par(struct fb_info *info) | |||
1069 | 1070 | ||
1070 | nvidia_vga_protect(par, 1); | 1071 | nvidia_vga_protect(par, 1); |
1071 | 1072 | ||
1072 | nvidia_write_regs(par); | 1073 | nvidia_write_regs(par, &par->ModeReg); |
1074 | NVSetStartAddress(par, 0); | ||
1073 | 1075 | ||
1074 | #if defined (__BIG_ENDIAN) | 1076 | #if defined (__BIG_ENDIAN) |
1075 | /* turn on LFB swapping */ | 1077 | /* turn on LFB swapping */ |
@@ -1378,6 +1380,57 @@ static struct fb_ops nvidia_fb_ops = { | |||
1378 | .fb_sync = nvidiafb_sync, | 1380 | .fb_sync = nvidiafb_sync, |
1379 | }; | 1381 | }; |
1380 | 1382 | ||
1383 | #ifdef CONFIG_PM | ||
1384 | static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state) | ||
1385 | { | ||
1386 | struct fb_info *info = pci_get_drvdata(dev); | ||
1387 | struct nvidia_par *par = info->par; | ||
1388 | |||
1389 | acquire_console_sem(); | ||
1390 | par->pm_state = state.event; | ||
1391 | |||
1392 | if (state.event == PM_EVENT_FREEZE) { | ||
1393 | dev->dev.power.power_state = state; | ||
1394 | } else { | ||
1395 | fb_set_suspend(info, 1); | ||
1396 | nvidiafb_blank(FB_BLANK_POWERDOWN, info); | ||
1397 | nvidia_write_regs(par, &par->SavedReg); | ||
1398 | pci_save_state(dev); | ||
1399 | pci_disable_device(dev); | ||
1400 | pci_set_power_state(dev, pci_choose_state(dev, state)); | ||
1401 | } | ||
1402 | |||
1403 | release_console_sem(); | ||
1404 | return 0; | ||
1405 | } | ||
1406 | |||
1407 | static int nvidiafb_resume(struct pci_dev *dev) | ||
1408 | { | ||
1409 | struct fb_info *info = pci_get_drvdata(dev); | ||
1410 | struct nvidia_par *par = info->par; | ||
1411 | |||
1412 | acquire_console_sem(); | ||
1413 | pci_set_power_state(dev, PCI_D0); | ||
1414 | |||
1415 | if (par->pm_state != PM_EVENT_FREEZE) { | ||
1416 | pci_restore_state(dev); | ||
1417 | pci_enable_device(dev); | ||
1418 | pci_set_master(dev); | ||
1419 | } | ||
1420 | |||
1421 | par->pm_state = PM_EVENT_ON; | ||
1422 | nvidiafb_set_par(info); | ||
1423 | fb_set_suspend (info, 0); | ||
1424 | nvidiafb_blank(FB_BLANK_UNBLANK, info); | ||
1425 | |||
1426 | release_console_sem(); | ||
1427 | return 0; | ||
1428 | } | ||
1429 | #else | ||
1430 | #define nvidiafb_suspend NULL | ||
1431 | #define nvidiafb_resume NULL | ||
1432 | #endif | ||
1433 | |||
1381 | static int __devinit nvidia_set_fbinfo(struct fb_info *info) | 1434 | static int __devinit nvidia_set_fbinfo(struct fb_info *info) |
1382 | { | 1435 | { |
1383 | struct fb_monspecs *specs = &info->monspecs; | 1436 | struct fb_monspecs *specs = &info->monspecs; |
@@ -1721,8 +1774,6 @@ static void __exit nvidiafb_remove(struct pci_dev *pd) | |||
1721 | struct nvidia_par *par = info->par; | 1774 | struct nvidia_par *par = info->par; |
1722 | 1775 | ||
1723 | NVTRACE_ENTER(); | 1776 | NVTRACE_ENTER(); |
1724 | if (!info) | ||
1725 | return; | ||
1726 | 1777 | ||
1727 | unregister_framebuffer(info); | 1778 | unregister_framebuffer(info); |
1728 | #ifdef CONFIG_MTRR | 1779 | #ifdef CONFIG_MTRR |
@@ -1799,8 +1850,10 @@ static int __devinit nvidiafb_setup(char *options) | |||
1799 | static struct pci_driver nvidiafb_driver = { | 1850 | static struct pci_driver nvidiafb_driver = { |
1800 | .name = "nvidiafb", | 1851 | .name = "nvidiafb", |
1801 | .id_table = nvidiafb_pci_tbl, | 1852 | .id_table = nvidiafb_pci_tbl, |
1802 | .probe = nvidiafb_probe, | 1853 | .probe = nvidiafb_probe, |
1803 | .remove = __exit_p(nvidiafb_remove), | 1854 | .suspend = nvidiafb_suspend, |
1855 | .resume = nvidiafb_resume, | ||
1856 | .remove = __exit_p(nvidiafb_remove), | ||
1804 | }; | 1857 | }; |
1805 | 1858 | ||
1806 | /* ------------------------------------------------------------------------- * | 1859 | /* ------------------------------------------------------------------------- * |