diff options
Diffstat (limited to 'drivers/video/nvidia/nvidia.c')
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index c6afafcfc24b..610575319444 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -949,8 +949,80 @@ static int nvidiafb_blank(int blank, struct fb_info *info) | |||
949 | return 0; | 949 | return 0; |
950 | } | 950 | } |
951 | 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 0; | ||
1020 | } | ||
1021 | |||
952 | static struct fb_ops nvidia_fb_ops = { | 1022 | static struct fb_ops nvidia_fb_ops = { |
953 | .owner = THIS_MODULE, | 1023 | .owner = THIS_MODULE, |
1024 | .fb_open = nvidiafb_open, | ||
1025 | .fb_release = nvidiafb_release, | ||
954 | .fb_check_var = nvidiafb_check_var, | 1026 | .fb_check_var = nvidiafb_check_var, |
955 | .fb_set_par = nvidiafb_set_par, | 1027 | .fb_set_par = nvidiafb_set_par, |
956 | .fb_setcolreg = nvidiafb_setcolreg, | 1028 | .fb_setcolreg = nvidiafb_setcolreg, |
@@ -1208,7 +1280,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, | |||
1208 | 1280 | ||
1209 | par = info->par; | 1281 | par = info->par; |
1210 | par->pci_dev = pd; | 1282 | par->pci_dev = pd; |
1211 | 1283 | mutex_init(&par->open_lock); | |
1212 | info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); | 1284 | info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); |
1213 | 1285 | ||
1214 | if (info->pixmap.addr == NULL) | 1286 | if (info->pixmap.addr == NULL) |