aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2007-05-08 03:38:33 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:28 -0400
commit7dfe50b3aac2b3500139ab10a6e228d34fed9a49 (patch)
treed72efb4cccdbcc4660268ca040f6d4db614f4791
parent19f3d3a5546be431f3846d8a8581e7a2f169dba3 (diff)
nvidiafb: VGA state save and restore
Allow the saving and restoration of VGA text mode. The state is saved on the first open and restored on the last close. Because of the non-linear mapping of the VGA registers to the MMIO space, this will be done only on X86 platforms where the device is the primary display. An echo 0 > /sys/class/vtconsole/vtcon1/bind will convert the display from graphics to text mode. Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/nvidia/nv_type.h6
-rw-r--r--drivers/video/nvidia/nvidia.c74
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
33obj-$(CONFIG_FB_MATROX) += matrox/ 33obj-$(CONFIG_FB_MATROX) += matrox/
34obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o 34obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o
35obj-$(CONFIG_FB_NVIDIA) += nvidia/ 35obj-$(CONFIG_FB_NVIDIA) += nvidia/ vgastate.o
36obj-$(CONFIG_FB_ATY) += aty/ macmodes.o 36obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
37obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o 37obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
38obj-$(CONFIG_FB_RADEON) += aty/ 38obj-$(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 {
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)