diff options
-rw-r--r-- | drivers/video/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_type.h | 6 | ||||
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 74 |
3 files changed, 80 insertions, 2 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 49d01eb48c7b..c8b43ebc14a8 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -32,7 +32,7 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o | |||
32 | 32 | ||
33 | obj-$(CONFIG_FB_MATROX) += matrox/ | 33 | obj-$(CONFIG_FB_MATROX) += matrox/ |
34 | obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o | 34 | obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o |
35 | obj-$(CONFIG_FB_NVIDIA) += nvidia/ | 35 | obj-$(CONFIG_FB_NVIDIA) += nvidia/ vgastate.o |
36 | obj-$(CONFIG_FB_ATY) += aty/ macmodes.o | 36 | obj-$(CONFIG_FB_ATY) += aty/ macmodes.o |
37 | obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o | 37 | obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o |
38 | obj-$(CONFIG_FB_RADEON) += aty/ | 38 | obj-$(CONFIG_FB_RADEON) += aty/ |
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index ee430af89a0d..38f7cc0a2331 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/i2c.h> | 6 | #include <linux/i2c.h> |
7 | #include <linux/i2c-algo-bit.h> | 7 | #include <linux/i2c-algo-bit.h> |
8 | #include <linux/mutex.h> | ||
9 | #include <video/vga.h> | ||
8 | 10 | ||
9 | #define NV_ARCH_04 0x04 | 11 | #define NV_ARCH_04 0x04 |
10 | #define NV_ARCH_10 0x10 | 12 | #define NV_ARCH_10 0x10 |
@@ -93,7 +95,10 @@ struct riva_regs { | |||
93 | struct nvidia_par { | 95 | struct nvidia_par { |
94 | RIVA_HW_STATE SavedReg; | 96 | RIVA_HW_STATE SavedReg; |
95 | RIVA_HW_STATE ModeReg; | 97 | RIVA_HW_STATE ModeReg; |
98 | RIVA_HW_STATE initial_state; | ||
96 | RIVA_HW_STATE *CurrentState; | 99 | RIVA_HW_STATE *CurrentState; |
100 | struct vgastate vgastate; | ||
101 | struct mutex open_lock; | ||
97 | u32 pseudo_palette[16]; | 102 | u32 pseudo_palette[16]; |
98 | struct pci_dev *pci_dev; | 103 | struct pci_dev *pci_dev; |
99 | u32 Architecture; | 104 | u32 Architecture; |
@@ -141,6 +146,7 @@ struct nvidia_par { | |||
141 | int BlendingPossible; | 146 | int BlendingPossible; |
142 | u32 paletteEnabled; | 147 | u32 paletteEnabled; |
143 | u32 forceCRTC; | 148 | u32 forceCRTC; |
149 | u32 open_count; | ||
144 | u8 DDCBase; | 150 | u8 DDCBase; |
145 | #ifdef CONFIG_MTRR | 151 | #ifdef CONFIG_MTRR |
146 | struct { | 152 | struct { |
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) |