aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/nvidia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/nvidia')
-rw-r--r--drivers/video/nvidia/nv_type.h6
-rw-r--r--drivers/video/nvidia/nvidia.c74
2 files changed, 79 insertions, 1 deletions
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 {
93struct nvidia_par { 95struct 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
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 0;
1020}
1021
952static struct fb_ops nvidia_fb_ops = { 1022static 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)