X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fi810%2Fi810_main.c;h=b55a12d95eb22ebe641add5c6c9e9602803b2793;hb=refs%2Fheads%2Fvserver;hp=6acde2569975b05fe8e0f8c5ef8dea69707171ed;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 6acde2569..b55a12d95 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -29,12 +29,10 @@ */ #include -#include #include #include #include #include -#include #include #include #include @@ -42,20 +40,62 @@ #include #include #include +#include #include #include - -#ifdef CONFIG_MTRR -#include -#endif - #include #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 __devinitdata; /* For 32 MiB Aper size, 8 should be the default */ +static u32 voffset __devinitdata; + +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" , @@ -92,20 +132,22 @@ static struct pci_driver i810fb_driver = { .resume = i810fb_resume, }; -static int vram __initdata = 4; -static int bpp __initdata = 8; -static int mtrr __initdata = 0; -static int accel __initdata = 0; -static int hsync1 __initdata = 0; -static int hsync2 __initdata = 0; -static int vsync1 __initdata = 0; -static int vsync2 __initdata = 0; -static int xres __initdata = 640; -static int yres __initdata = 480; -static int vyres __initdata = 0; -static int sync __initdata = 0; -static int ext_vga __initdata = 0; -static int dcolor __initdata = 0; +static char *mode_option __devinitdata = NULL; +static int vram __devinitdata = 4; +static int bpp __devinitdata = 8; +static int mtrr __devinitdata; +static int accel __devinitdata; +static int hsync1 __devinitdata; +static int hsync2 __devinitdata; +static int vsync1 __devinitdata; +static int vsync2 __devinitdata; +static int xres __devinitdata; +static int yres __devinitdata; +static int vyres __devinitdata; +static int sync __devinitdata; +static int extvga __devinitdata; +static int dcolor __devinitdata; +static int ddc3 __devinitdata = 2; /*------------------------------------------------------------*/ @@ -121,7 +163,7 @@ static int dcolor __initdata = 0; * DESCRIPTION: * Blanks/unblanks the display */ -static void i810_screen_off(u8 *mmio, u8 mode) +static void i810_screen_off(u8 __iomem *mmio, u8 mode) { u32 count = WAIT_COUNT; u8 val; @@ -145,7 +187,7 @@ static void i810_screen_off(u8 *mmio, u8 mode) * Turns off DRAM refresh. Must be off for only 2 vsyncs * before data becomes corrupt */ -static void i810_dram_off(u8 *mmio, u8 mode) +static void i810_dram_off(u8 __iomem *mmio, u8 mode) { u8 val; @@ -164,7 +206,7 @@ static void i810_dram_off(u8 *mmio, u8 mode) * The IBM VGA standard allows protection of certain VGA registers. * This will protect or unprotect them. */ -static void i810_protect_regs(u8 *mmio, int mode) +static void i810_protect_regs(u8 __iomem *mmio, int mode) { u8 reg; @@ -187,7 +229,7 @@ static void i810_protect_regs(u8 *mmio, int mode) static void i810_load_pll(struct i810fb_par *par) { u32 tmp1, tmp2; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; tmp1 = par->regs.M | par->regs.N << 16; tmp2 = i810_readl(DCLK_2D, mmio); @@ -212,7 +254,7 @@ static void i810_load_pll(struct i810fb_par *par) */ static void i810_load_vga(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; /* interlace */ i810_writeb(CR_INDEX_CGA, mmio, CR70); @@ -255,7 +297,7 @@ static void i810_load_vga(struct i810fb_par *par) */ static void i810_load_vgax(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writeb(CR_INDEX_CGA, mmio, CR30); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30); @@ -281,7 +323,8 @@ static void i810_load_vgax(struct i810fb_par *par) static void i810_load_2d(struct i810fb_par *par) { u32 tmp; - u8 tmp8, *mmio = par->mmio_start_virtual; + u8 tmp8; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(FW_BLC, mmio, par->watermark); tmp = i810_readl(PIXCONF, mmio); @@ -301,7 +344,7 @@ static void i810_load_2d(struct i810fb_par *par) * i810_hires - enables high resolution mode * @mmio: address of register space */ -static void i810_hires(u8 *mmio) +static void i810_hires(u8 __iomem *mmio) { u8 val; @@ -309,6 +352,8 @@ static void i810_hires(u8 *mmio) val = i810_readb(CR_DATA_CGA, mmio); i810_writeb(CR_INDEX_CGA, mmio, CR80); i810_writeb(CR_DATA_CGA, mmio, val | 1); + /* Stop LCD displays from flickering */ + i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4); } /** @@ -321,7 +366,8 @@ static void i810_hires(u8 *mmio) static void i810_load_pitch(struct i810fb_par *par) { u32 tmp, pitch; - u8 val, *mmio = par->mmio_start_virtual; + u8 val; + u8 __iomem *mmio = par->mmio_start_virtual; pitch = par->pitch >> 3; i810_writeb(SR_INDEX, mmio, SR01); @@ -351,9 +397,10 @@ static void i810_load_pitch(struct i810fb_par *par) */ static void i810_load_color(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; u32 reg1; u16 reg2; + reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27); reg2 = i810_readw(BLTCNTL, mmio) & ~0x30; @@ -372,7 +419,7 @@ static void i810_load_color(struct i810fb_par *par) */ static void i810_load_regs(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_screen_off(mmio, OFF); i810_protect_regs(mmio, OFF); @@ -390,7 +437,7 @@ static void i810_load_regs(struct i810fb_par *par) } static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue, - u8 *mmio) + u8 __iomem *mmio) { i810_writeb(CLUT_INDEX_WRITE, mmio, regno); i810_writeb(CLUT_DATA, mmio, red); @@ -399,7 +446,7 @@ static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue, } static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue, - u8 *mmio) + u8 __iomem *mmio) { i810_writeb(CLUT_INDEX_READ, mmio, regno); *red = i810_readb(CLUT_DATA, mmio); @@ -413,7 +460,7 @@ static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue, static void i810_restore_pll(struct i810fb_par *par) { u32 tmp1, tmp2; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; tmp1 = par->hw_state.dclk_2d; tmp2 = i810_readl(DCLK_2D, mmio); @@ -433,7 +480,7 @@ static void i810_restore_pll(struct i810fb_par *par) static void i810_restore_dac(struct i810fb_par *par) { u32 tmp1, tmp2; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; tmp1 = par->hw_state.pixconf; tmp2 = i810_readl(PIXCONF, mmio); @@ -444,7 +491,8 @@ static void i810_restore_dac(struct i810fb_par *par) static void i810_restore_vgax(struct i810fb_par *par) { - u8 i, j, *mmio = par->mmio_start_virtual; + u8 i, j; + u8 __iomem *mmio = par->mmio_start_virtual; for (i = 0; i < 4; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR30+i); @@ -477,7 +525,8 @@ static void i810_restore_vgax(struct i810fb_par *par) static void i810_restore_vga(struct i810fb_par *par) { - u8 i, *mmio = par->mmio_start_virtual; + u8 i; + u8 __iomem *mmio = par->mmio_start_virtual; for (i = 0; i < 10; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR00 + i); @@ -491,7 +540,8 @@ static void i810_restore_vga(struct i810fb_par *par) static void i810_restore_addr_map(struct i810fb_par *par) { - u8 tmp, *mmio = par->mmio_start_virtual; + u8 tmp; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writeb(GR_INDEX, mmio, GR10); tmp = i810_readb(GR_DATA, mmio); @@ -505,7 +555,7 @@ static void i810_restore_2d(struct i810fb_par *par) { u32 tmp_long; u16 tmp_word; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; tmp_word = i810_readw(BLTCNTL, mmio); tmp_word &= ~(3 << 4); @@ -534,7 +584,7 @@ static void i810_restore_2d(struct i810fb_par *par) static void i810_restore_vga_state(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_screen_off(mmio, OFF); i810_protect_regs(mmio, OFF); @@ -556,7 +606,8 @@ static void i810_restore_vga_state(struct i810fb_par *par) static void i810_save_vgax(struct i810fb_par *par) { - u8 i, *mmio = par->mmio_start_virtual; + u8 i; + u8 __iomem *mmio = par->mmio_start_virtual; for (i = 0; i < 4; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR30 + i); @@ -579,7 +630,8 @@ static void i810_save_vgax(struct i810fb_par *par) static void i810_save_vga(struct i810fb_par *par) { - u8 i, *mmio = par->mmio_start_virtual; + u8 i; + u8 __iomem *mmio = par->mmio_start_virtual; for (i = 0; i < 10; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR00 + i); @@ -593,7 +645,7 @@ static void i810_save_vga(struct i810fb_par *par) static void i810_save_2d(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio); par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio); @@ -627,7 +679,7 @@ static void i810_save_vga_state(struct i810fb_par *par) * DESCRIPTION: * Calculates buffer pitch in bytes. */ -u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp) +static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp) { u32 length; @@ -716,7 +768,7 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p) * Description: * Shows or hides the hardware cursor */ -void i810_enable_cursor(u8 *mmio, int mode) +static void i810_enable_cursor(u8 __iomem *mmio, int mode) { u32 temp; @@ -729,7 +781,7 @@ void i810_enable_cursor(u8 *mmio, int mode) static void i810_reset_cursor_image(struct i810fb_par *par) { - u8 *addr = par->cursor_heap.virtual; + u8 __iomem *addr = par->cursor_heap.virtual; int i, j; for (i = 64; i--; ) { @@ -744,7 +796,7 @@ static void i810_reset_cursor_image(struct i810fb_par *par) static void i810_load_cursor_image(int width, int height, u8 *data, struct i810fb_par *par) { - u8 *addr = par->cursor_heap.virtual; + u8 __iomem *addr = par->cursor_heap.virtual; int i, j, w = width/8; int mod = width % 8, t_mask, d_mask; @@ -765,9 +817,9 @@ 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; - u8 *mmio = par->mmio_start_virtual, temp; - u8 red, green, blue, trans; + struct i810fb_par *par = info->par; + u8 __iomem *mmio = par->mmio_start_virtual; + u8 red, green, blue, trans, temp; i810fb_getcolreg(bg, &red, &green, &blue, &trans, info); @@ -796,7 +848,7 @@ static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info) */ static void i810_init_cursor(struct i810fb_par *par) { - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_enable_cursor(mmio, OFF); i810_writel(CURBASE, mmio, par->cursor_heap.physical); @@ -938,32 +990,25 @@ 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; - int line_length, vidmem; - u32 xres, yres, vxres, vyres; - - xres = var->xres; - yres = var->yres; - vxres = var->xres_virtual; - vyres = var->yres_virtual; - + struct i810fb_par *par = info->par; + int line_length, vidmem, mode_valid = 0, retval = 0; + u32 vyres = var->yres_virtual, vxres = var->xres_virtual; /* * Memory limit */ - line_length = get_line_length(par, vxres, - var->bits_per_pixel); - + line_length = get_line_length(par, vxres, var->bits_per_pixel); vidmem = line_length*vyres; + if (vidmem > par->fb.size) { vyres = par->fb.size/line_length; - if (vyres < yres) { + if (vyres < var->yres) { vyres = yres; vxres = par->fb.size/vyres; vxres /= var->bits_per_pixel >> 3; line_length = get_line_length(par, vxres, var->bits_per_pixel); vidmem = line_length * yres; - if (vxres < xres) { + if (vxres < var->xres) { printk("i810fb: required video memory, " "%d bytes, for %dx%d-%d (virtual) " "is out of range\n", @@ -973,6 +1018,10 @@ static int i810_check_params(struct fb_var_screeninfo *var, } } } + + var->xres_virtual = vxres; + var->yres_virtual = vyres; + /* * Monitor limit */ @@ -988,18 +1037,41 @@ static int i810_check_params(struct fb_var_screeninfo *var, info->monspecs.dclkmax = 204000000; break; } + info->monspecs.dclkmin = 15000000; - if (fb_validate_mode(var, info)) { - if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) - return -EINVAL; + if (!fb_validate_mode(var, info)) + mode_valid = 1; + +#ifdef CONFIG_FB_I810_I2C + if (!mode_valid && info->monspecs.gtf && + !fb_get_mode(FB_MAXTIMINGS, 0, var, info)) + mode_valid = 1; + + if (!mode_valid && info->monspecs.modedb_len) { + struct fb_videomode *mode; + + mode = fb_find_best_mode(var, &info->modelist); + if (mode) { + fb_videomode_to_var(var, mode); + mode_valid = 1; + } } - - var->xres = xres; - var->yres = yres; - var->xres_virtual = vxres; - var->yres_virtual = vyres; - return 0; +#endif + if (!mode_valid && info->monspecs.modedb_len == 0) { + if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) { + int default_sync = (info->monspecs.hfmin-HFMIN) + |(info->monspecs.hfmax-HFMAX) + |(info->monspecs.vfmin-VFMIN) + |(info->monspecs.vfmax-VFMAX); + printk("i810fb: invalid video mode%s\n", + default_sync ? "" : ". Specifying " + "vsyncN/hsyncN parameters may help"); + retval = -EINVAL; + } + } + + return retval; } /** @@ -1012,7 +1084,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)); @@ -1123,8 +1195,9 @@ 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; - u8 *mmio = par->mmio_start_virtual, temp; + struct i810fb_par *par = info->par; + u8 __iomem *mmio = par->mmio_start_virtual; + u8 temp; if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { if ((info->var.green.length == 5 && regno > 31) || @@ -1161,13 +1234,13 @@ 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) { memset(&par->state, 0, sizeof(struct vgastate)); par->state.flags = VGA_SAVE_CMAP; - par->state.vgabase = (caddr_t) par->mmio_start_virtual; + par->state.vgabase = par->mmio_start_virtual; save_vga(&par->state); i810_save_vga_state(par); @@ -1180,7 +1253,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); @@ -1202,8 +1275,9 @@ 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; - u8 *mmio = par->mmio_start_virtual, temp; + struct i810fb_par *par = info->par; + u8 __iomem *mmio = par->mmio_start_virtual; + u8 temp; int i; if (regno > 255) return 1; @@ -1295,7 +1369,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 + @@ -1307,29 +1381,34 @@ 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; - u8 *mmio = par->mmio_start_virtual; + struct i810fb_par *par = info->par; + u8 __iomem *mmio = par->mmio_start_virtual; int mode = 0, pwr, scr_off = 0; pwr = i810_readl(PWR_CLKC, mmio); - switch(blank_mode) { - case VESA_NO_BLANKING: + switch (blank_mode) { + case FB_BLANK_UNBLANK: mode = POWERON; pwr |= 1; scr_off = ON; break; - case VESA_VSYNC_SUSPEND: + case FB_BLANK_NORMAL: + mode = POWERON; + pwr |= 1; + scr_off = OFF; + break; + case FB_BLANK_VSYNC_SUSPEND: mode = STANDBY; pwr |= 1; scr_off = OFF; break; - case VESA_HSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: mode = SUSPEND; pwr |= 1; scr_off = OFF; break; - case VESA_POWERDOWN: + case FB_BLANK_POWERDOWN: mode = POWERDOWN; pwr &= ~1; scr_off = OFF; @@ -1337,20 +1416,21 @@ static int i810fb_blank (int blank_mode, struct fb_info *info) default: return -EINVAL; } + i810_screen_off(mmio, scr_off); i810_writel(HVSYNC, mmio, mode); i810_writel(PWR_CLKC, mmio, pwr); + return 0; } 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); i810_init_cursor(par); - encode_fix(&info->fix, info); if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) { @@ -1390,11 +1470,11 @@ 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; - u8 *mmio = par->mmio_start_virtual; + struct i810fb_par *par = info->par; + u8 __iomem *mmio = par->mmio_start_virtual; - if (!info->var.accel_flags || par->dev_flags & LOCKUP) - return soft_cursor(info, cursor); + if (!par->dev_flags & LOCKUP) + return -ENXIO; if (cursor->image.width > 64 || cursor->image.height > 64) return -ENXIO; @@ -1406,62 +1486,50 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) i810_enable_cursor(mmio, OFF); - if (cursor->set & FB_CUR_SETHOT) - info->cursor.hot = cursor->hot; - if (cursor->set & FB_CUR_SETPOS) { u32 tmp; - info->cursor.image.dx = cursor->image.dx; - info->cursor.image.dy = cursor->image.dy; - tmp = (info->cursor.image.dx - info->var.xoffset) & 0xffff; - tmp |= (info->cursor.image.dy - info->var.yoffset) << 16; + tmp = (cursor->image.dx - info->var.xoffset) & 0xffff; + tmp |= (cursor->image.dy - info->var.yoffset) << 16; i810_writel(CURPOS, mmio, tmp); } - if (cursor->set & FB_CUR_SETSIZE) { + if (cursor->set & FB_CUR_SETSIZE) i810_reset_cursor_image(par); - info->cursor.image.height = cursor->image.height; - info->cursor.image.width = cursor->image.width; - } - if (cursor->set & FB_CUR_SETCMAP) { + if (cursor->set & FB_CUR_SETCMAP) i810_load_cursor_colors(cursor->image.fg_color, cursor->image.bg_color, info); - info->cursor.image.fg_color = cursor->image.fg_color; - info->cursor.image.bg_color = cursor->image.bg_color; - - } - if (cursor->set & (FB_CUR_SETSHAPE)) { - int size = ((info->cursor.image.width + 7) >> 3) * - info->cursor.image.height; + if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { + int size = ((cursor->image.width + 7) >> 3) * + cursor->image.height; int i; - u8 *data = kmalloc(64 * 8, GFP_KERNEL); + u8 *data = kmalloc(64 * 8, GFP_ATOMIC); if (data == NULL) return -ENOMEM; - info->cursor.image.data = cursor->image.data; - switch (info->cursor.rop) { + switch (cursor->rop) { case ROP_XOR: for (i = 0; i < size; i++) - data[i] = info->cursor.image.data[i] ^ info->cursor.mask[i]; + data[i] = cursor->image.data[i] ^ cursor->mask[i]; break; case ROP_COPY: default: for (i = 0; i < size; i++) - data[i] = info->cursor.image.data[i] & info->cursor.mask[i]; + data[i] = cursor->image.data[i] & cursor->mask[i]; break; } - i810_load_cursor_image(info->cursor.image.width, - info->cursor.image.height, data, + + i810_load_cursor_image(cursor->image.width, + cursor->image.height, data, par); kfree(data); } - if (info->cursor.enable) + if (cursor->enable) i810_enable_cursor(mmio, ON); return 0; @@ -1486,39 +1554,34 @@ static struct fb_ops i810fb_ops __devinitdata = { /*********************************************************************** * Power Management * ***********************************************************************/ -static int i810fb_suspend(struct pci_dev *dev, u32 state) +static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg) { 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; + struct i810fb_par *par = info->par; - if (state == prev_state) + par->cur_state = mesg.event; + + switch (mesg.event) { + case PM_EVENT_FREEZE: + case PM_EVENT_PRETHAW: + dev->dev.power.power_state = mesg; return 0; + } - par->cur_state = state; + acquire_console_sem(); + fb_set_suspend(info, 1); - switch (state) { - case 1: - blank = VESA_VSYNC_SUSPEND; - break; - case 2: - blank = VESA_HSYNC_SUSPEND; - break; - case 3: - blank = VESA_POWERDOWN; - break; - default: - return -EINVAL; - } - info->fbops->fb_blank(blank, info); + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); - if (!prev_state) { - par->drm_agp->unbind_memory(par->i810_gtt.i810_fb_memory); - par->drm_agp->unbind_memory(par->i810_gtt.i810_cursor_memory); - pci_disable_device(dev); - } - pci_save_state(dev, par->pci_state); - pci_set_power_state(dev, state); + 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, mesg)); + release_console_sem(); return 0; } @@ -1526,23 +1589,33 @@ static int i810fb_suspend(struct pci_dev *dev, u32 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; - if (par->cur_state == 0) - return 0; + par->cur_state = PM_EVENT_ON; - pci_restore_state(dev, par->pci_state); - pci_set_power_state(dev, 0); - pci_enable_device(dev); - par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory, - par->fb.offset); - par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory, - par->cursor_heap.offset); + if (cur_state == PM_EVENT_FREEZE) { + pci_set_power_state(dev, PCI_D0); + return 0; + } - info->fbops->fb_blank(VESA_NO_BLANKING, info); + acquire_console_sem(); + pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); - par->cur_state = 0; + if (pci_enable_device(dev)) + goto fail; + 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); +fail: + release_console_sem(); return 0; } /*********************************************************************** @@ -1583,45 +1656,43 @@ 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; i810_fix_offsets(par); size = par->fb.size + par->iring.size; - par->drm_agp = (drm_agp_t *) inter_module_get("drm_agp"); - if (!par->drm_agp) { - printk("i810fb: cannot acquire agp\n"); + if (!(bridge = agp_backend_acquire(par->dev))) { + printk("i810fb_alloc_fbmem: cannot acquire agpgart\n"); return -ENODEV; } - par->drm_agp->acquire(); - if (!(par->i810_gtt.i810_fb_memory = - par->drm_agp->allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) { + agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) { printk("i810fb_alloc_fbmem: can't allocate framebuffer " "memory\n"); - par->drm_agp->release(); + agp_backend_release(bridge); return -ENOMEM; } - if (par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory, - par->fb.offset)) { + if (agp_bind_memory(par->i810_gtt.i810_fb_memory, + par->fb.offset)) { printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n"); - par->drm_agp->release(); + agp_backend_release(bridge); return -EBUSY; } if (!(par->i810_gtt.i810_cursor_memory = - par->drm_agp->allocate_memory(par->cursor_heap.size >> 12, - AGP_PHYSICAL_MEMORY))) { + agp_allocate_memory(bridge, par->cursor_heap.size >> 12, + AGP_PHYSICAL_MEMORY))) { printk("i810fb_alloc_cursormem: can't allocate" "cursor memory\n"); - par->drm_agp->release(); + agp_backend_release(bridge); return -ENOMEM; } - if (par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory, + if (agp_bind_memory(par->i810_gtt.i810_cursor_memory, par->cursor_heap.offset)) { printk("i810fb_alloc_cursormem: cannot bind cursor memory\n"); - par->drm_agp->release(); + agp_backend_release(bridge); return -EBUSY; } @@ -1629,7 +1700,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info) i810_fix_pointers(par); - par->drm_agp->release(); + agp_backend_release(bridge); return 0; } @@ -1697,15 +1768,26 @@ static void __devinit i810_init_defaults(struct i810fb_par *par, if (sync) par->dev_flags |= ALWAYS_SYNC; + par->ddc_num = ddc3; + if (bpp < 8) bpp = 8; + par->i810fb_ops = i810fb_ops; + + if (xres) + info->var.xres = xres; + else + info->var.xres = 640; + + if (yres) + info->var.yres = yres; + else + info->var.yres = 480; + if (!vyres) - vyres = (vram << 20)/(xres*bpp >> 3); + vyres = (vram << 20)/(info->var.xres*bpp >> 3); - par->i810fb_ops = i810fb_ops; - info->var.xres = xres; - info->var.yres = yres; info->var.yres_virtual = vyres; info->var.bits_per_pixel = bpp; @@ -1724,14 +1806,15 @@ static void __devinit i810_init_defaults(struct i810fb_par *par, */ static void __devinit i810_init_device(struct i810fb_par *par) { - u8 reg, *mmio = par->mmio_start_virtual; + u8 reg; + u8 __iomem *mmio = par->mmio_start_virtual; if (mtrr) set_mtrr(par); i810_init_cursor(par); /* mvo: enable external vga-connector (for laptops) */ - if (ext_vga) { + if (extvga) { i810_writel(HVSYNC, mmio, 0); i810_writel(PWR_CLKC, mmio, 3); } @@ -1800,8 +1883,72 @@ i810_allocate_pci_resource(struct i810fb_par *par, return 0; } - -int __init i810fb_setup(char *options) + +static void __devinit i810fb_find_init_mode(struct fb_info *info) +{ + struct fb_videomode mode; + struct fb_var_screeninfo var; + struct fb_monspecs *specs = &info->monspecs; + int found = 0; +#ifdef CONFIG_FB_I810_I2C + int i; + int err = 1; + struct i810fb_par *par = info->par; +#endif + + INIT_LIST_HEAD(&info->modelist); + memset(&mode, 0, sizeof(struct fb_videomode)); + var = info->var; +#ifdef CONFIG_FB_I810_I2C + i810_create_i2c_busses(par); + + for (i = 0; i < par->ddc_num + 1; i++) { + err = i810_probe_i2c_connector(info, &par->edid, i); + if (!err) + break; + } + + if (!err) + printk("i810fb_init_pci: DDC probe successful\n"); + + fb_edid_to_monspecs(par->edid, specs); + + if (specs->modedb == NULL) + printk("i810fb_init_pci: Unable to get Mode Database\n"); + + fb_videomode_to_modelist(specs->modedb, specs->modedb_len, + &info->modelist); + if (specs->modedb != NULL) { + struct fb_videomode *m; + + if (xres && yres) { + if ((m = fb_find_best_mode(&var, &info->modelist))) { + mode = *m; + found = 1; + } + } + + if (!found) { + m = fb_find_best_display(&info->monspecs, &info->modelist); + mode = *m; + found = 1; + } + + fb_videomode_to_var(&var, &mode); + } +#endif + if (mode_option) + fb_find_mode(&var, info, mode_option, specs->modedb, + specs->modedb_len, (found) ? &mode : NULL, + info->var.bits_per_pixel); + + info->var = var; + fb_destroy_modedb(specs->modedb); + specs->modedb = NULL; +} + +#ifndef MODULE +static int __devinit i810fb_setup(char *options) { char *this_opt, *suffix = NULL; @@ -1813,8 +1960,8 @@ int __init i810fb_setup(char *options) mtrr = 1; else if (!strncmp(this_opt, "accel", 5)) accel = 1; - else if (!strncmp(this_opt, "ext_vga", 7)) - ext_vga = 1; + else if (!strncmp(this_opt, "extvga", 6)) + extvga = 1; else if (!strncmp(this_opt, "sync", 4)) sync = 1; else if (!strncmp(this_opt, "vram:", 5)) @@ -1843,40 +1990,40 @@ int __init i810fb_setup(char *options) vsync2 = simple_strtoul(this_opt+7, NULL, 0); else if (!strncmp(this_opt, "dcolor", 6)) dcolor = 1; + else if (!strncmp(this_opt, "ddc3", 4)) + ddc3 = 3; + else + mode_option = this_opt; } return 0; } +#endif static int __devinit i810fb_init_pci (struct pci_dev *dev, const struct pci_device_id *entry) { struct fb_info *info; struct i810fb_par *par = NULL; + struct fb_videomode mode; int i, err = -1, vfreq, hfreq, pixclock; i = 0; - if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) { - i810fb_release_resource(info, par); - return -ENOMEM; - } - memset(info, 0, sizeof(struct fb_info)); - if(!(par = kmalloc(sizeof(struct i810fb_par), GFP_KERNEL))) { - i810fb_release_resource(info, par); + info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev); + if (!info) return -ENOMEM; - } - memset(par, 0, sizeof(struct i810fb_par)); + par = info->par; par->dev = dev; - info->par = par; - if (!(info->pixmap.addr = kmalloc(64*1024, GFP_KERNEL))) { + if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) { i810fb_release_resource(info, par); return -ENOMEM; } - memset(info->pixmap.addr, 0, 64*1024); - info->pixmap.size = 64*1024; + memset(info->pixmap.addr, 0, 8*1024); + info->pixmap.size = 8*1024; info->pixmap.buf_align = 8; + info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; if ((err = i810_allocate_pci_resource(par, entry))) { @@ -1897,15 +2044,20 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, info->fbops = &par->i810fb_ops; info->pseudo_palette = par->pseudo_palette; fb_alloc_cmap(&info->cmap, 256, 0); + i810fb_find_init_mode(info); if ((err = info->fbops->fb_check_var(&info->var, info))) { i810fb_release_resource(info, par); return err; } + + fb_var_to_videomode(&mode, &info->var); + fb_add_videomode(&mode, &info->modelist); encode_fix(&info->fix, info); i810fb_init_ringbuffer(info); err = register_framebuffer(info); + if (err < 0) { i810fb_release_resource(info, par); printk("i810fb_init: cannot register framebuffer device\n"); @@ -1941,44 +2093,35 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, static void i810fb_release_resource(struct fb_info *info, struct i810fb_par *par) { - if (par) { - unset_mtrr(par); - if (par->drm_agp) { - drm_agp_t *agp = par->drm_agp; - struct gtt_data *gtt = &par->i810_gtt; - - if (par->i810_gtt.i810_cursor_memory) - agp->free_memory(gtt->i810_cursor_memory); - if (par->i810_gtt.i810_fb_memory) - agp->free_memory(gtt->i810_fb_memory); - - inter_module_put("drm_agp"); - par->drm_agp = NULL; - } + struct gtt_data *gtt = &par->i810_gtt; + unset_mtrr(par); - if (par->mmio_start_virtual) - iounmap(par->mmio_start_virtual); - if (par->aperture.virtual) - iounmap(par->aperture.virtual); + i810_delete_i2c_busses(par); - if (par->res_flags & FRAMEBUFFER_REQ) - release_mem_region(par->aperture.physical, - par->aperture.size); - if (par->res_flags & MMIO_REQ) - release_mem_region(par->mmio_start_phys, MMIO_SIZE); + if (par->i810_gtt.i810_cursor_memory) + agp_free_memory(gtt->i810_cursor_memory); + if (par->i810_gtt.i810_fb_memory) + agp_free_memory(gtt->i810_fb_memory); - if (par->res_flags & PCI_DEVICE_ENABLED) - pci_disable_device(par->dev); + if (par->mmio_start_virtual) + iounmap(par->mmio_start_virtual); + if (par->aperture.virtual) + iounmap(par->aperture.virtual); + kfree(par->edid); + if (par->res_flags & FRAMEBUFFER_REQ) + release_mem_region(par->aperture.physical, + par->aperture.size); + if (par->res_flags & MMIO_REQ) + release_mem_region(par->mmio_start_phys, MMIO_SIZE); + + framebuffer_release(info); - kfree(par); - } - kfree(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); @@ -1987,7 +2130,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev) } #ifndef MODULE -int __init i810fb_init(void) +static int __devinit i810fb_init(void) { char *option = NULL; @@ -1995,10 +2138,7 @@ int __init i810fb_init(void) return -ENODEV; i810fb_setup(option); - if (pci_register_driver(&i810fb_driver) > 0) - return 0; - pci_unregister_driver(&i810fb_driver); - return -ENODEV; + return pci_register_driver(&i810fb_driver); } #endif @@ -2008,57 +2148,58 @@ int __init i810fb_init(void) #ifdef MODULE -int __init i810fb_init(void) +static int __devinit i810fb_init(void) { hsync1 *= 1000; hsync2 *= 1000; - if (pci_register_driver(&i810fb_driver) > 0) - return 0; - pci_unregister_driver(&i810fb_driver); - return -ENODEV; + return pci_register_driver(&i810fb_driver); } -MODULE_PARM(vram, "i"); +module_param(vram, int, 0); MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" " (default=4)"); -MODULE_PARM(voffset, "i"); +module_param(voffset, int, 0); MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer " "memory (0 to maximum aperture size), in MiB (default = 48)"); -MODULE_PARM(bpp, "i"); +module_param(bpp, int, 0); MODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel" " (default = 8)"); -MODULE_PARM(xres, "i"); +module_param(xres, int, 0); MODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)"); -MODULE_PARM(yres, "i"); +module_param(yres, int, 0); MODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)"); -MODULE_PARM(vyres, "i"); +module_param(vyres,int, 0); MODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines" " (default = 480)"); -MODULE_PARM(hsync1, "i"); +module_param(hsync1, int, 0); MODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz" - " (default = 31)"); -MODULE_PARM(hsync2, "i"); + " (default = 29)"); +module_param(hsync2, int, 0); MODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz" - " (default = 31)"); -MODULE_PARM(vsync1, "i"); + " (default = 30)"); +module_param(vsync1, int, 0); MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz" " (default = 50)"); -MODULE_PARM(vsync2, "i"); +module_param(vsync2, int, 0); MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" " (default = 60)"); -MODULE_PARM(accel, "i"); +module_param(accel, bool, 0); MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)"); -MODULE_PARM(mtrr, "i"); +module_param(mtrr, bool, 0); MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)"); -MODULE_PARM(ext_vga, "i"); -MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)"); -MODULE_PARM(sync, "i"); +module_param(extvga, bool, 0); +MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)"); +module_param(sync, bool, 0); MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing" " (default = 0)"); -MODULE_PARM(dcolor, "i"); +module_param(dcolor, bool, 0); MODULE_PARM_DESC(dcolor, "use DirectColor visuals" " (default = 0 = TrueColor)"); +module_param(ddc3, bool, 0); +MODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "Specify initial video mode"); MODULE_AUTHOR("Tony A. Daplas"); MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"