diff -Naur linux-2.5.61-fbdev/drivers/video/i810/i810.h linux-2.5.61-ad/drivers/video/i810/i810.h --- linux-2.5.61-fbdev/drivers/video/i810/i810.h 2003-02-16 00:55:52.000000000 +0000 +++ linux-2.5.61-ad/drivers/video/i810/i810.h 2003-02-16 04:50:15.000000000 +0000 @@ -256,6 +256,7 @@ drm_agp_t *drm_agp; atomic_t use_count; u32 pseudo_palette[17]; + u32 pci_state[16]; unsigned long mmio_start_phys; u8 *mmio_start_virtual; u32 cursor_reset; @@ -273,6 +274,7 @@ u32 depth; u32 blit_bpp; u32 ovract; + u32 cur_state; int mtrr_reg; u16 bltcntl; u8 interlace; diff -Naur linux-2.5.61-fbdev/drivers/video/i810/i810_accel.c linux-2.5.61-ad/drivers/video/i810/i810_accel.c --- linux-2.5.61-fbdev/drivers/video/i810/i810_accel.c 2003-02-16 00:55:52.000000000 +0000 +++ linux-2.5.61-ad/drivers/video/i810/i810_accel.c 2003-02-16 04:50:11.000000000 +0000 @@ -315,19 +315,19 @@ i810_writel(IRING + 12, mmio, tmp); } -void i810fb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct i810fb_par *par = (struct i810fb_par *) p->par; + struct i810fb_par *par = (struct i810fb_par *) info->par; u32 dx, dy, width, height, dest, rop = 0, color = 0; - if (!p->var.accel_flags || par->dev_flags & LOCKUP || + if (!info->var.accel_flags || par->dev_flags & LOCKUP || par->depth == 4) - return cfb_fillrect(p, rect); + return cfb_fillrect(info, rect); if (par->depth == 1) color = rect->color; else - color = ((u32 *) (p->pseudo_palette))[rect->color]; + color = ((u32 *) (info->pseudo_palette))[rect->color]; rop = i810fb_rop[rect->rop]; @@ -336,19 +336,19 @@ dy = rect->dy; height = rect->height; - dest = p->fix.smem_start + (dy * p->fix.line_length) + dx; - color_blit(width, height, p->fix.line_length, dest, rop, color, + dest = info->fix.smem_start + (dy * info->fix.line_length) + dx; + color_blit(width, height, info->fix.line_length, dest, rop, color, par->blit_bpp, par); } -void i810fb_copyarea(struct fb_info *p, struct fb_copyarea *region) +void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) { - struct i810fb_par *par = (struct i810fb_par *) p->par; + struct i810fb_par *par = (struct i810fb_par *) info->par; u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir; - if (!p->var.accel_flags || par->dev_flags & LOCKUP || + if (!info->var.accel_flags || par->dev_flags & LOCKUP || par->depth == 4) - return cfb_copyarea(p, region); + return cfb_copyarea(info, region); dx = region->dx * par->depth; sx = region->sx * par->depth; @@ -366,66 +366,68 @@ dx += width - 1; } if (dy <= sy) { - pitch = p->fix.line_length; + pitch = info->fix.line_length; } else { - pitch = (-(p->fix.line_length)) & 0xFFFF; + pitch = (-(info->fix.line_length)) & 0xFFFF; sy += height - 1; dy += height - 1; } - src = p->fix.smem_start + (sy * p->fix.line_length) + sx; - dest = p->fix.smem_start + (dy * p->fix.line_length) + dx; + src = info->fix.smem_start + (sy * info->fix.line_length) + sx; + dest = info->fix.smem_start + (dy * info->fix.line_length) + dx; source_copy_blit(width, height, pitch, xdir, src, dest, PAT_COPY_ROP, par->blit_bpp, par); } -void i810fb_imageblit(struct fb_info *p, struct fb_image *image) +void i810fb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct i810fb_par *par = (struct i810fb_par *) p->par; + struct i810fb_par *par = (struct i810fb_par *) info->par; u32 fg = 0, bg = 0, s_pitch, d_pitch, size, offset, dst, i, j; u8 *s_addr, *d_addr; - if (!p->var.accel_flags || par->dev_flags & LOCKUP || - par->depth == 4 || image->depth != 1) - return cfb_imageblit(p, image); + if (!info->var.accel_flags || par->dev_flags & LOCKUP || + par->depth == 4 || image->depth != 0) + return cfb_imageblit(info, image); - switch (p->var.bits_per_pixel) { + switch (info->var.bits_per_pixel) { case 8: fg = image->fg_color; bg = image->bg_color; break; case 16: case 24: - fg = ((u32 *)(p->pseudo_palette))[image->fg_color]; - bg = ((u32 *)(p->pseudo_palette))[image->bg_color]; + fg = ((u32 *)(info->pseudo_palette))[image->fg_color]; + bg = ((u32 *)(info->pseudo_palette))[image->bg_color]; break; } - dst = p->fix.smem_start + (image->dy * p->fix.line_length) + + dst = info->fix.smem_start + (image->dy * info->fix.line_length) + (image->dx * par->depth); s_pitch = (image->width+7)/8; d_pitch = (s_pitch + 1) & ~1; - - size = (d_pitch * image->height) + 7; - size &= ~7; - - if (image->width & 15) { + size = d_pitch * image->height; + if (s_pitch != d_pitch || size & 7) { + size += 7; + size &= ~7; offset = get_buffer_offset(size, par); d_addr = par->pixmap.virtual + offset; - s_addr = image->data; + s_addr = (u8 *) image->data; - for (i = image->height; i--; ) { - for (j = 0; j < s_pitch; j++) - i810_writeb(j, d_addr, s_addr[j]); - s_addr += s_pitch; - d_addr += d_pitch; + if (s_pitch == d_pitch) { + memcpy_toio(d_addr, s_addr, s_pitch * image->height); + } else { + for (i = image->height; i--; ) { + for (j = 0; j < s_pitch; j++) + i810_writeb(j, d_addr, s_addr[j]); + s_addr += s_pitch; + d_addr += d_pitch; + } } - mono_src_copy_blit(image->width * par->depth, image->height, - p->fix.line_length, size/8, par->blit_bpp, - PAT_COPY_ROP, dst, + info->fix.line_length, size/8, + par->blit_bpp, PAT_COPY_ROP, dst, par->pixmap.physical + offset, bg, fg, par); } @@ -434,18 +436,18 @@ */ else { mono_src_copy_imm_blit(image->width * par->depth, - image->height, p->fix.line_length, + image->height, info->fix.line_length, size/4, par->blit_bpp, PAT_COPY_ROP, dst, (u32 *) image->data, bg, fg, par); } } -int i810fb_sync(struct fb_info *p) +int i810fb_sync(struct fb_info *info) { - struct i810fb_par *par = (struct i810fb_par *) p->par; + struct i810fb_par *par = (struct i810fb_par *) info->par; - if (!p->var.accel_flags || par->dev_flags & LOCKUP) + if (!info->var.accel_flags || par->dev_flags & LOCKUP) return 0; return wait_for_engine_idle(par); diff -Naur linux-2.5.61-fbdev/drivers/video/i810/i810_main.c linux-2.5.61-ad/drivers/video/i810/i810_main.c --- linux-2.5.61-fbdev/drivers/video/i810/i810_main.c 2003-02-16 00:55:52.000000000 +0000 +++ linux-2.5.61-ad/drivers/video/i810/i810_main.c 2003-02-16 04:50:11.000000000 +0000 @@ -1437,6 +1437,68 @@ }; /*********************************************************************** + * Power Management * + ***********************************************************************/ +static int i810fb_suspend(struct pci_dev *dev, u32 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 == prev_state) + return 0; + + par->cur_state = state; + + 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 (!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); + + return 0; +} + +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; + + if (par->cur_state == 0) + return 0; + + 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); + + info->fbops->fb_blank(VESA_NO_BLANKING, info); + + par->cur_state = 0; + + return 0; +} +/*********************************************************************** * AGP resource allocation * ***********************************************************************/ @@ -1469,13 +1531,13 @@ par->fb.offset = v_offset_default << 20; par->fb.offset >>= 12; - par->iring.offset = par->fb.offset + (par->fb.size >> 12); - par->iring.size = RINGBUFFER_SIZE; - - par->pixmap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12); + par->pixmap.offset = par->fb.offset + (par->fb.size >> 12); par->pixmap.size = PIXMAP_SIZE; - par->cursor_heap.offset = par->pixmap.offset + (PIXMAP_SIZE >> 12); + par->iring.offset = par->pixmap.offset + (PIXMAP_SIZE >> 12); + par->iring.size = RINGBUFFER_SIZE; + + par->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12); par->cursor_heap.size = 4096; } @@ -1817,12 +1879,16 @@ vfreq = hfreq/(info->var.yres + info->var.upper_margin + info->var.vsync_len + info->var.lower_margin); - printk("fb: %s v%d.%d.%d%s, (c) Tony Daplas\n" - " Video RAM : %dK\n" - " Mode : %dx%d-%dbpp@%dHz\n", + printk("I810FB: fb%d : %s v%d.%d.%d%s\n" + "I810FB: Video RAM : %dK\n" + "I810FB: Monitor : H: %d-%d KHz V: %d-%d Hz\n" + "I810FB: Mode : %dx%d-%dbpp@%dHz\n", + minor(info->node), i810_pci_list[entry->driver_data], VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION, - (int) par->fb.size>>10, info->var.xres, + (int) par->fb.size>>10, info->monspecs.hfmin/1000, + info->monspecs.hfmax/1000, info->monspecs.vfmin, + info->monspecs.vfmax, info->var.xres, info->var.yres, info->var.bits_per_pixel, vfreq); return 0; } @@ -1893,7 +1959,10 @@ return -ENODEV; } - return (pci_module_init(&i810fb_driver)); + if (pci_register_driver(&i810fb_driver) > 0) + return 0; + pci_unregister_driver(&i810fb_driver); + return -ENODEV; } #endif @@ -1909,7 +1978,10 @@ hsync1 *= 1000; hsync2 *= 1000; - return (pci_module_init(&i810fb_driver)); + if (pci_register_driver(&i810fb_driver) > 0) + return 0; + pci_unregister_driver(&i810fb_driver); + return -ENODEV; } MODULE_PARM(vram, "i"); diff -Naur linux-2.5.61-fbdev/drivers/video/i810/i810_main.h linux-2.5.61-ad/drivers/video/i810/i810_main.h --- linux-2.5.61-fbdev/drivers/video/i810/i810_main.h 2003-02-16 00:55:52.000000000 +0000 +++ linux-2.5.61-ad/drivers/video/i810/i810_main.h 2003-02-16 04:50:15.000000000 +0000 @@ -43,12 +43,16 @@ static int __init 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, u32 state); static struct pci_driver i810fb_driver = { .name = "i810fb", .id_table = i810fb_pci_tbl, .probe = i810fb_init_pci, .remove = __exit_p(i810fb_remove_pci), + .suspend = i810fb_suspend, + .resume = i810fb_resume, }; static int i810_init __initdata = 0; @@ -121,9 +125,11 @@ extern void i810fb_fill_var_timings(struct fb_var_screeninfo *var); /* Accelerated Functions */ -extern void i810fb_fillrect (struct fb_info *p, const struct fb_fillrect *rect); -extern void i810fb_copyarea (struct fb_info *p, struct fb_copyarea *region); -extern void i810fb_imageblit(struct fb_info *p, struct fb_image *image); +extern void i810fb_fillrect (struct fb_info *p, + const struct fb_fillrect *rect); +extern void i810fb_copyarea (struct fb_info *p, + const struct fb_copyarea *region); +extern void i810fb_imageblit(struct fb_info *p, const struct fb_image *image); extern int i810fb_sync (struct fb_info *p); extern void i810fb_init_ringbuffer (struct i810fb_par *par);