diff options
Diffstat (limited to 'drivers/video/nvidia/nvidia.c')
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 81 |
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 | ||
203 | static void nvidia_vga_protect(struct nvidia_par *par, int on) | 203 | static 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 | ||
959 | static 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 | |||
971 | static 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 | |||
983 | static 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 | |||
999 | static 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--; | ||
1017 | done: | ||
1018 | mutex_unlock(&par->open_lock); | ||
1019 | return err; | ||
1020 | } | ||
1021 | |||
951 | static struct fb_ops nvidia_fb_ops = { | 1022 | static 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) |