Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Antonino A. Daplas and committed by
Linus Torvalds
7dfe50b3 19f3d3a5

+80 -2
+1 -1
drivers/video/Makefile
··· 32 32 33 33 obj-$(CONFIG_FB_MATROX) += matrox/ 34 34 obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o 35 - obj-$(CONFIG_FB_NVIDIA) += nvidia/ 35 + obj-$(CONFIG_FB_NVIDIA) += nvidia/ vgastate.o 36 36 obj-$(CONFIG_FB_ATY) += aty/ macmodes.o 37 37 obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o 38 38 obj-$(CONFIG_FB_RADEON) += aty/
+6
drivers/video/nvidia/nv_type.h
··· 5 5 #include <linux/types.h> 6 6 #include <linux/i2c.h> 7 7 #include <linux/i2c-algo-bit.h> 8 + #include <linux/mutex.h> 9 + #include <video/vga.h> 8 10 9 11 #define NV_ARCH_04 0x04 10 12 #define NV_ARCH_10 0x10 ··· 95 93 struct nvidia_par { 96 94 RIVA_HW_STATE SavedReg; 97 95 RIVA_HW_STATE ModeReg; 96 + RIVA_HW_STATE initial_state; 98 97 RIVA_HW_STATE *CurrentState; 98 + struct vgastate vgastate; 99 + struct mutex open_lock; 99 100 u32 pseudo_palette[16]; 100 101 struct pci_dev *pci_dev; 101 102 u32 Architecture; ··· 146 141 int BlendingPossible; 147 142 u32 paletteEnabled; 148 143 u32 forceCRTC; 144 + u32 open_count; 149 145 u8 DDCBase; 150 146 #ifdef CONFIG_MTRR 151 147 struct {
+73 -1
drivers/video/nvidia/nvidia.c
··· 949 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 1022 static struct fb_ops nvidia_fb_ops = { 953 1023 .owner = THIS_MODULE, 1024 + .fb_open = nvidiafb_open, 1025 + .fb_release = nvidiafb_release, 954 1026 .fb_check_var = nvidiafb_check_var, 955 1027 .fb_set_par = nvidiafb_set_par, 956 1028 .fb_setcolreg = nvidiafb_setcolreg, ··· 1280 1208 1281 1209 par = info->par; 1282 1210 par->pci_dev = pd; 1283 - 1211 + mutex_init(&par->open_lock); 1284 1212 info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); 1285 1213 1286 1214 if (info->pixmap.addr == NULL)