diff options
Diffstat (limited to 'drivers/video/i810/i810_main.c')
-rw-r--r-- | drivers/video/i810/i810_main.c | 137 |
1 files changed, 89 insertions, 48 deletions
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index c0c974b1afa..266d0ab9266 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -42,20 +42,62 @@ #include <linux/pci_ids.h> #include <linux/resource.h> #include <linux/unistd.h> +#include <linux/console.h> #include <asm/io.h> #include <asm/div64.h> - -#ifdef CONFIG_MTRR -#include <asm/mtrr.h> -#endif - #include <asm/page.h> #include "i810_regs.h" #include "i810.h" #include "i810_main.h" +/* + * voffset - framebuffer offset in MiB from aperture start address. In order for + * the driver to work with X, we must try to use memory holes left untouched by X. The + * following table lists where X's different surfaces start at. + * + * --------------------------------------------- + * : : 64 MiB : 32 MiB : + * ---------------------------------------------- + * : FrontBuffer : 0 : 0 : + * : DepthBuffer : 48 : 16 : + * : BackBuffer : 56 : 24 : + * ---------------------------------------------- + * + * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to + * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should + * work, allowing 7 + 1 MiB of Framebuffer memory. + * Note, the size of the hole may change depending on how much memory you allocate to X, + * and how the memory is split up between these surfaces. + * + * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with + * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load. + * + * Experiment with v_offset to find out which works best for you. + */ +static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */ +static u32 voffset __initdata = 0; + +static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); +static int __devinit i810fb_init_pci (struct pci_dev *dev, + const struct pci_device_id *entry); +static void __exit i810fb_remove_pci(struct pci_dev *dev); +static int i810fb_resume(struct pci_dev *dev); +static int i810fb_suspend(struct pci_dev *dev, pm_message_t state); + +/* Chipset Specific Functions */ +static int i810fb_set_par (struct fb_info *info); +static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue, + u8 *transp, struct fb_info *info); +static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info); +static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); +static int i810fb_blank (int blank_mode, struct fb_info *info); + +/* Initialization */ +static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); + /* PCI */ static const char *i810_pci_list[] __devinitdata = { "Intel(R) 810 Framebuffer Device" , @@ -776,7 +818,7 @@ static void i810_load_cursor_image(int width, int height, u8 *data, static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; u8 red, green, blue, trans, temp; @@ -949,7 +991,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var) static int i810_check_params(struct fb_var_screeninfo *var, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; int line_length, vidmem, mode_valid = 0, retval = 0; u32 vyres = var->yres_virtual, vxres = var->xres_virtual; /* @@ -1043,7 +1085,7 @@ static int i810_check_params(struct fb_var_screeninfo *var, */ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); @@ -1154,7 +1196,7 @@ static void decode_var(const struct fb_var_screeninfo *var, static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, u8 *transp, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; u8 temp; @@ -1193,7 +1235,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, static int i810fb_open(struct fb_info *info, int user) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 count = atomic_read(&par->use_count); if (count == 0) { @@ -1212,7 +1254,7 @@ static int i810fb_open(struct fb_info *info, int user) static int i810fb_release(struct fb_info *info, int user) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 count; count = atomic_read(&par->use_count); @@ -1234,7 +1276,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; u8 temp; int i; @@ -1328,7 +1370,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u32 total; total = var->xoffset * par->depth + @@ -1340,7 +1382,7 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var, static int i810fb_blank (int blank_mode, struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; int mode = 0, pwr, scr_off = 0; @@ -1385,7 +1427,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info) static int i810fb_set_par(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; decode_var(&info->var, par); i810_load_regs(par); @@ -1429,7 +1471,7 @@ static int i810fb_check_var(struct fb_var_screeninfo *var, static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct i810fb_par *par = (struct i810fb_par *)info->par; + struct i810fb_par *par = info->par; u8 __iomem *mmio = par->mmio_start_virtual; if (!par->dev_flags & LOCKUP) @@ -1516,36 +1558,29 @@ static struct fb_ops i810fb_ops __devinitdata = { static int i810fb_suspend(struct pci_dev *dev, pm_message_t state) { struct fb_info *info = pci_get_drvdata(dev); - struct i810fb_par *par = (struct i810fb_par *) info->par; - int blank = 0, prev_state = par->cur_state; - - if (state.event == prev_state) - return 0; + struct i810fb_par *par = info->par; par->cur_state = state.event; - switch (state.event) { - case 1: - blank = VESA_VSYNC_SUSPEND; - break; - case 2: - blank = VESA_HSYNC_SUSPEND; - break; - case 3: - blank = VESA_POWERDOWN; - break; - default: - return -EINVAL; + if (state.event == PM_EVENT_FREEZE) { + dev->dev.power.power_state = state; + return 0; } - info->fbops->fb_blank(blank, info); - if (!prev_state) { - agp_unbind_memory(par->i810_gtt.i810_fb_memory); - agp_unbind_memory(par->i810_gtt.i810_cursor_memory); - pci_disable_device(dev); - } + acquire_console_sem(); + fb_set_suspend(info, 1); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + i810fb_blank(FB_BLANK_POWERDOWN, info); + agp_unbind_memory(par->i810_gtt.i810_fb_memory); + agp_unbind_memory(par->i810_gtt.i810_cursor_memory); + pci_save_state(dev); + pci_disable_device(dev); pci_set_power_state(dev, pci_choose_state(dev, state)); + release_console_sem(); return 0; } @@ -1553,23 +1588,29 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state) static int i810fb_resume(struct pci_dev *dev) { struct fb_info *info = pci_get_drvdata(dev); - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; + int cur_state = par->cur_state; + + par->cur_state = PM_EVENT_ON; - if (par->cur_state == 0) + if (cur_state == PM_EVENT_FREEZE) { + pci_set_power_state(dev, PCI_D0); return 0; + } - pci_restore_state(dev); + acquire_console_sem(); pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); pci_enable_device(dev); + pci_set_master(dev); agp_bind_memory(par->i810_gtt.i810_fb_memory, par->fb.offset); agp_bind_memory(par->i810_gtt.i810_cursor_memory, par->cursor_heap.offset); - + i810fb_set_par(info); + fb_set_suspend (info, 0); info->fbops->fb_blank(VESA_NO_BLANKING, info); - - par->cur_state = 0; - + release_console_sem(); return 0; } /*********************************************************************** @@ -1610,7 +1651,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par) static int __devinit i810_alloc_agp_mem(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; int size; struct agp_bridge_data *bridge; @@ -2074,7 +2115,7 @@ static void i810fb_release_resource(struct fb_info *info, static void __exit i810fb_remove_pci(struct pci_dev *dev) { struct fb_info *info = pci_get_drvdata(dev); - struct i810fb_par *par = (struct i810fb_par *) info->par; + struct i810fb_par *par = info->par; unregister_framebuffer(info); i810fb_release_resource(info, par); |