diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2007-05-08 00:38:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 11:15:28 -0700 |
commit | 7dfe50b3aac2b3500139ab10a6e228d34fed9a49 (patch) | |
tree | d72efb4cccdbcc4660268ca040f6d4db614f4791 /drivers/video/nvidia/nvidia.c | |
parent | 19f3d3a5546be431f3846d8a8581e7a2f169dba3 (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>
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 c6afafcfc24..61057531944 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) return 0; } +/* + * Because the VGA registers are not mapped linearly in its MMIO space, + * restrict VGA register saving and restore to x86 only, where legacy VGA IO + * access is legal. Consequently, we must also check if the device is the + * primary display. + */ +#ifdef CONFIG_X86 +static void save_vga_x86(struct nvidia_par *par) +{ + struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE]; + + if (res && res->flags & IORESOURCE_ROM_SHADOW) { + memset(&par->vgastate, 0, sizeof(par->vgastate)); + par->vgastate.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | + VGA_SAVE_CMAP; + save_vga(&par->vgastate); + } +} + +static void restore_vga_x86(struct nvidia_par *par) +{ + struct resource *res= &par->pci_dev->resource[PCI_ROM_RESOURCE]; + + if (res && res->flags & IORESOURCE_ROM_SHADOW) + restore_vga(&par->vgastate); +} +#else +#define save_vga_x86(x) do {} while (0) +#define restore_vga_x86(x) do {} while (0) +#endif /* X86 */ + +static int nvidiafb_open(struct fb_info *info, int user) +{ + struct nvidia_par *par = info->par; + + mutex_lock(&par->open_lock); + + if (!par->open_count) { + save_vga_x86(par); + nvidia_save_vga(par, &par->initial_state); + } + + par->open_count++; + mutex_unlock(&par->open_lock); + return 0; +} + +static int nvidiafb_release(struct fb_info *info, int user) +{ + struct nvidia_par *par = info->par; + int err = 0; + + mutex_lock(&par->open_lock); + + if (!par->open_count) { + err = -EINVAL; + goto done; + } + + if (par->open_count == 1) { + nvidia_write_regs(par, &par->initial_state); + restore_vga_x86(par); + } + + par->open_count--; +done: + mutex_unlock(&par->open_lock); + return 0; +} + static struct fb_ops nvidia_fb_ops = { .owner = THIS_MODULE, + .fb_open = nvidiafb_open, + .fb_release = nvidiafb_release, .fb_check_var = nvidiafb_check_var, .fb_set_par = nvidiafb_set_par, .fb_setcolreg = nvidiafb_setcolreg, @@ -1208,7 +1280,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, par = info->par; par->pci_dev = pd; - + mutex_init(&par->open_lock); info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); if (info->pixmap.addr == NULL) |