aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/nvidia/nvidia.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/nvidia/nvidia.c')
-rw-r--r--drivers/video/nvidia/nvidia.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index b97ec6901263..7c36b5fe582e 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -200,7 +200,7 @@ static int nvidia_panel_tweak(struct nvidia_par *par,
200 return tweak; 200 return tweak;
201} 201}
202 202
203static void nvidia_vga_protect(struct nvidia_par *par, int on) 203static void nvidia_screen_off(struct nvidia_par *par, int on)
204{ 204{
205 unsigned char tmp; 205 unsigned char tmp;
206 206
@@ -649,7 +649,7 @@ static int nvidiafb_set_par(struct fb_info *info)
649 NVLockUnlock(par, 0); 649 NVLockUnlock(par, 0);
650 } 650 }
651 651
652 nvidia_vga_protect(par, 1); 652 nvidia_screen_off(par, 1);
653 653
654 nvidia_write_regs(par, &par->ModeReg); 654 nvidia_write_regs(par, &par->ModeReg);
655 NVSetStartAddress(par, 0); 655 NVSetStartAddress(par, 0);
@@ -687,7 +687,7 @@ static int nvidiafb_set_par(struct fb_info *info)
687 687
688 par->cursor_reset = 1; 688 par->cursor_reset = 1;
689 689
690 nvidia_vga_protect(par, 0); 690 nvidia_screen_off(par, 0);
691 691
692#ifdef CONFIG_BOOTX_TEXT 692#ifdef CONFIG_BOOTX_TEXT
693 /* Update debug text engine */ 693 /* Update debug text engine */
@@ -696,6 +696,7 @@ static int nvidiafb_set_par(struct fb_info *info)
696 info->var.bits_per_pixel, info->fix.line_length); 696 info->var.bits_per_pixel, info->fix.line_length);
697#endif 697#endif
698 698
699 NVLockUnlock(par, 0);
699 NVTRACE_LEAVE(); 700 NVTRACE_LEAVE();
700 return 0; 701 return 0;
701} 702}
@@ -948,8 +949,80 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
948 return 0; 949 return 0;
949} 950}
950 951
952/*
953 * Because the VGA registers are not mapped linearly in its MMIO space,
954 * restrict VGA register saving and restore to x86 only, where legacy VGA IO
955 * access is legal. Consequently, we must also check if the device is the
956 * primary display.
957 */
958#ifdef CONFIG_X86
959static void save_vga_x86(struct nvidia_par *par)
960{
961 struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
962
963 if (res && res->flags & IORESOURCE_ROM_SHADOW) {
964 memset(&par->vgastate, 0, sizeof(par->vgastate));
965 par->vgastate.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS |
966 VGA_SAVE_CMAP;
967 save_vga(&par->vgastate);
968 }
969}
970
971static void restore_vga_x86(struct nvidia_par *par)
972{
973 struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE];
974
975 if (res && res->flags & IORESOURCE_ROM_SHADOW)
976 restore_vga(&par->vgastate);
977}
978#else
979#define save_vga_x86(x) do {} while (0)
980#define restore_vga_x86(x) do {} while (0)
981#endif /* X86 */
982
983static int nvidiafb_open(struct fb_info *info, int user)
984{
985 struct nvidia_par *par = info->par;
986
987 mutex_lock(&par->open_lock);
988
989 if (!par->open_count) {
990 save_vga_x86(par);
991 nvidia_save_vga(par, &par->initial_state);
992 }
993
994 par->open_count++;
995 mutex_unlock(&par->open_lock);
996 return 0;
997}
998
999static int nvidiafb_release(struct fb_info *info, int user)
1000{
1001 struct nvidia_par *par = info->par;
1002 int err = 0;
1003
1004 mutex_lock(&par->open_lock);
1005
1006 if (!par->open_count) {
1007 err = -EINVAL;
1008 goto done;
1009 }
1010
1011 if (par->open_count == 1) {
1012 nvidia_write_regs(par, &par->initial_state);
1013 restore_vga_x86(par);
1014 }
1015
1016 par->open_count--;
1017done:
1018 mutex_unlock(&par->open_lock);
1019 return err;
1020}
1021
951static struct fb_ops nvidia_fb_ops = { 1022static struct fb_ops nvidia_fb_ops = {
952 .owner = THIS_MODULE, 1023 .owner = THIS_MODULE,
1024 .fb_open = nvidiafb_open,
1025 .fb_release = nvidiafb_release,
953 .fb_check_var = nvidiafb_check_var, 1026 .fb_check_var = nvidiafb_check_var,
954 .fb_set_par = nvidiafb_set_par, 1027 .fb_set_par = nvidiafb_set_par,
955 .fb_setcolreg = nvidiafb_setcolreg, 1028 .fb_setcolreg = nvidiafb_setcolreg,
@@ -1207,7 +1280,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
1207 1280
1208 par = info->par; 1281 par = info->par;
1209 par->pci_dev = pd; 1282 par->pci_dev = pd;
1210 1283 mutex_init(&par->open_lock);
1211 info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); 1284 info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
1212 1285
1213 if (info->pixmap.addr == NULL) 1286 if (info->pixmap.addr == NULL)