diff options
Diffstat (limited to 'drivers/video/nvidia')
-rw-r--r-- | drivers/video/nvidia/nv_accel.c | 12 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_type.h | 1 | ||||
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 115 |
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 | ||
619 | static 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 | |||
618 | static void nvidia_save_vga(struct nvidia_par *par, | 643 | static 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 | ||
646 | static void nvidia_write_regs(struct nvidia_par *par) | 671 | static 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 | ||
697 | static 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 | |||
723 | static int nvidia_calc_regs(struct fb_info *info) | 722 | static 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 | ||
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 | ||
1430 | |||
1380 | static int __devinit nvidia_set_fbinfo(struct fb_info *info) | 1431 | static 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) | |||
1798 | static struct pci_driver nvidiafb_driver = { | 1849 | static 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 | /* ------------------------------------------------------------------------- * |