Skip to content

Commit

Permalink
nvidiafb: VGA state save and restore
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
adaplas authored and Linus Torvalds committed May 8, 2007
1 parent 19f3d3a commit 7dfe50b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 2 deletions.
2 changes: 1 addition & 1 deletion drivers/video/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o

obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o
obj-$(CONFIG_FB_NVIDIA) += nvidia/
obj-$(CONFIG_FB_NVIDIA) += nvidia/ vgastate.o
obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
obj-$(CONFIG_FB_RADEON) += aty/
Expand Down
6 changes: 6 additions & 0 deletions drivers/video/nvidia/nv_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/mutex.h>
#include <video/vga.h>

#define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10
Expand Down Expand Up @@ -93,7 +95,10 @@ struct riva_regs {
struct nvidia_par {
RIVA_HW_STATE SavedReg;
RIVA_HW_STATE ModeReg;
RIVA_HW_STATE initial_state;
RIVA_HW_STATE *CurrentState;
struct vgastate vgastate;
struct mutex open_lock;
u32 pseudo_palette[16];
struct pci_dev *pci_dev;
u32 Architecture;
Expand Down Expand Up @@ -141,6 +146,7 @@ struct nvidia_par {
int BlendingPossible;
u32 paletteEnabled;
u32 forceCRTC;
u32 open_count;
u8 DDCBase;
#ifdef CONFIG_MTRR
struct {
Expand Down
74 changes: 73 additions & 1 deletion drivers/video/nvidia/nvidia.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 7dfe50b

Please sign in to comment.