diff options
Diffstat (limited to 'drivers/video/savage')
-rw-r--r-- | drivers/video/savage/savagefb-i2c.c | 22 | ||||
-rw-r--r-- | drivers/video/savage/savagefb.h | 10 | ||||
-rw-r--r-- | drivers/video/savage/savagefb_driver.c | 39 |
3 files changed, 55 insertions, 16 deletions
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 8db066ccca6..35c1ce62b21 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -41,10 +41,6 @@ #define SAVAGE4_I2C_SCL_IN 0x00000008 #define SAVAGE4_I2C_SDA_IN 0x00000010 -#define SET_CR_IX(base, val) writeb((val), base + 0x8000 + VGA_CR_IX) -#define SET_CR_DATA(base, val) writeb((val), base + 0x8000 + VGA_CR_DATA) -#define GET_CR_DATA(base) readb(base + 0x8000 + VGA_CR_DATA) - static void savage4_gpio_setscl(void *data, int val) { struct savagefb_i2c_chan *chan = data; @@ -92,15 +88,15 @@ static void prosavage_gpio_setscl(void* data, int val) struct savagefb_i2c_chan *chan = data; u32 r; - SET_CR_IX(chan->ioaddr, chan->reg); - r = GET_CR_DATA(chan->ioaddr); + r = VGArCR(chan->reg, chan->par); r |= PROSAVAGE_I2C_ENAB; if (val) { r |= PROSAVAGE_I2C_SCL_OUT; } else { r &= ~PROSAVAGE_I2C_SCL_OUT; } - SET_CR_DATA(chan->ioaddr, r); + + VGAwCR(chan->reg, r, chan->par); } static void prosavage_gpio_setsda(void* data, int val) @@ -108,31 +104,29 @@ static void prosavage_gpio_setsda(void* data, int val) struct savagefb_i2c_chan *chan = data; unsigned int r; - SET_CR_IX(chan->ioaddr, chan->reg); - r = GET_CR_DATA(chan->ioaddr); + r = VGArCR(chan->reg, chan->par); r |= PROSAVAGE_I2C_ENAB; if (val) { r |= PROSAVAGE_I2C_SDA_OUT; } else { r &= ~PROSAVAGE_I2C_SDA_OUT; } - SET_CR_DATA(chan->ioaddr, r); + + VGAwCR(chan->reg, r, chan->par); } static int prosavage_gpio_getscl(void* data) { struct savagefb_i2c_chan *chan = data; - SET_CR_IX(chan->ioaddr, chan->reg); - return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN)); + return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0; } static int prosavage_gpio_getsda(void* data) { struct savagefb_i2c_chan *chan = data; - SET_CR_IX(chan->ioaddr, chan->reg); - return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN)); + return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0; } static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index e648a6c0f6d..8bfdfc3c523 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h @@ -15,6 +15,8 @@ #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/i2c-algo-bit.h> +#include <linux/mutex.h> +#include <video/vga.h> #include "../edid.h" #ifdef SAVAGEFB_DEBUG @@ -189,8 +191,12 @@ struct savagefb_par { struct savagefb_i2c_chan chan; struct savage_reg state; struct savage_reg save; + struct savage_reg initial; + struct vgastate vgastate; + struct mutex open_lock; unsigned char *edid; u32 pseudo_palette[16]; + u32 open_count; int paletteEnabled; int pm_state; int display_type; @@ -203,7 +209,7 @@ struct savagefb_par { int clock[4]; int MCLK, REFCLK, LCDclk; struct { - u8 __iomem *vbase; + void __iomem *vbase; u32 pbase; u32 len; #ifdef CONFIG_MTRR @@ -212,7 +218,7 @@ struct savagefb_par { } video; struct { - volatile u8 __iomem *vbase; + void __iomem *vbase; u32 pbase; u32 len; } mmio; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 0166ec2ccf3..3d7507ad55f 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1623,8 +1623,46 @@ static void savagefb_restore_state(struct fb_info *info) savagefb_blank(FB_BLANK_UNBLANK, info); } +static int savagefb_open(struct fb_info *info, int user) +{ + struct savagefb_par *par = info->par; + + mutex_lock(&par->open_lock); + + if (!par->open_count) { + memset(&par->vgastate, 0, sizeof(par->vgastate)); + par->vgastate.flags = VGA_SAVE_CMAP | VGA_SAVE_FONTS | + VGA_SAVE_MODE; + par->vgastate.vgabase = par->mmio.vbase + 0x8000; + save_vga(&par->vgastate); + savage_get_default_par(par, &par->initial); + } + + par->open_count++; + mutex_unlock(&par->open_lock); + return 0; +} + +static int savagefb_release(struct fb_info *info, int user) +{ + struct savagefb_par *par = info->par; + + mutex_lock(&par->open_lock); + + if (par->open_count == 1) { + savage_set_default_par(par, &par->initial); + restore_vga(&par->vgastate); + } + + par->open_count--; + mutex_unlock(&par->open_lock); + return 0; +} + static struct fb_ops savagefb_ops = { .owner = THIS_MODULE, + .fb_open = savagefb_open, + .fb_release = savagefb_release, .fb_check_var = savagefb_check_var, .fb_set_par = savagefb_set_par, .fb_setcolreg = savagefb_setcolreg, @@ -2173,6 +2211,7 @@ static int __devinit savagefb_probe(struct pci_dev* dev, if (!info) return -ENOMEM; par = info->par; + mutex_init(&par->open_lock); err = pci_enable_device(dev); if (err) goto failed_enable; |