📄 i810_main.c
字号:
* DESCRIPTION: * Based on the contents of @var, @par will be dynamically filled up. * @par contains all information necessary to modify the hardware. */static void decode_var(const struct fb_var_screeninfo *var, struct i810fb_par *par){ u32 xres, yres, vxres, vyres; xres = var->xres; yres = var->yres; vxres = var->xres_virtual; vyres = var->yres_virtual; switch (var->bits_per_pixel) { case 8: par->pixconf = PIXCONF8; par->bltcntl = 0; par->depth = 1; par->blit_bpp = BPP8; break; case 16: if (var->green.length == 5) par->pixconf = PIXCONF15; else par->pixconf = PIXCONF16; par->bltcntl = 16; par->depth = 2; par->blit_bpp = BPP16; break; case 24: par->pixconf = PIXCONF24; par->bltcntl = 32; par->depth = 3; par->blit_bpp = BPP24; break; case 32: par->pixconf = PIXCONF32; par->bltcntl = 0; par->depth = 4; par->blit_bpp = 3 << 24; break; } if (var->nonstd && var->bits_per_pixel != 8) par->pixconf |= 1 << 27; i810_calc_dclk(var->pixclock, &par->regs.M, &par->regs.N, &par->regs.P); i810fb_encode_registers(var, par, xres, yres); par->watermark = i810_get_watermark(var, par); par->pitch = get_line_length(par, vxres, var->bits_per_pixel);} /** * i810fb_getcolreg - gets red, green and blue values of the hardware DAC * @regno: DAC index * @red: red * @green: green * @blue: blue * @transp: transparency (alpha) * @info: pointer to fb_info * * DESCRIPTION: * Gets the red, green and blue values of the hardware DAC as pointed by @regno * and writes them to @red, @green and @blue respectively */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 __iomem *mmio = par->mmio_start_virtual; u8 temp; if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { if ((info->var.green.length == 5 && regno > 31) || (info->var.green.length == 6 && regno > 63)) return 1; } temp = i810_readb(PIXCONF1, mmio); i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE); if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 5) i810_read_dac(regno * 8, red, green, blue, mmio); else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 6) { u8 tmp; i810_read_dac(regno * 8, red, &tmp, blue, mmio); i810_read_dac(regno * 4, &tmp, green, &tmp, mmio); } else i810_read_dac(regno, red, green, blue, mmio); *transp = 0; i810_writeb(PIXCONF1, mmio, temp); return 0;}/****************************************************************** * Framebuffer device-specific hooks * ******************************************************************/static int i810fb_open(struct fb_info *info, int user){ struct i810fb_par *par = (struct i810fb_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 = par->mmio_start_virtual; save_vga(&par->state); i810_save_vga_state(par); } atomic_inc(&par->use_count); return 0;}static int i810fb_release(struct fb_info *info, int user){ struct i810fb_par *par = (struct i810fb_par *) info->par; u32 count; count = atomic_read(&par->use_count); if (count == 0) return -EINVAL; if (count == 1) { i810_restore_vga_state(par); restore_vga(&par->state); } atomic_dec(&par->use_count); return 0;}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 __iomem *mmio = par->mmio_start_virtual; u8 temp; int i; if (regno > 255) return 1; if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { if ((info->var.green.length == 5 && regno > 31) || (info->var.green.length == 6 && regno > 63)) return 1; } if (info->var.grayscale) red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16; temp = i810_readb(PIXCONF1, mmio); i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE); if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 5) { for (i = 0; i < 8; i++) i810_write_dac((u8) (regno * 8) + i, (u8) red, (u8) green, (u8) blue, mmio); } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && info->var.green.length == 6) { u8 r, g, b; if (regno < 32) { for (i = 0; i < 8; i++) i810_write_dac((u8) (regno * 8) + i, (u8) red, (u8) green, (u8) blue, mmio); } i810_read_dac((u8) (regno*4), &r, &g, &b, mmio); for (i = 0; i < 4; i++) i810_write_dac((u8) (regno*4) + i, r, (u8) green, b, mmio); } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { i810_write_dac((u8) regno, (u8) red, (u8) green, (u8) blue, mmio); } i810_writeb(PIXCONF1, mmio, temp); if (regno < 16) { switch (info->var.bits_per_pixel) { case 16: if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { if (info->var.green.length == 5) ((u32 *)info->pseudo_palette)[regno] = (regno << 10) | (regno << 5) | regno; else ((u32 *)info->pseudo_palette)[regno] = (regno << 11) | (regno << 5) | regno; } else { if (info->var.green.length == 5) { /* RGB 555 */ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); } else { /* RGB 565 */ ((u32 *)info->pseudo_palette)[regno] = (red & 0xf800) | ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); } } break; case 24: /* RGB 888 */ case 32: /* RGBA 8888 */ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) ((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno; else ((u32 *)info->pseudo_palette)[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | ((blue & 0xff00) >> 8); break; } } return 0;}static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct i810fb_par *par = (struct i810fb_par *) info->par; u32 total; total = var->xoffset * par->depth + var->yoffset * info->fix.line_length; i810fb_load_front(total, info); return 0;}static int i810fb_blank (int blank_mode, struct fb_info *info){ struct i810fb_par *par = (struct i810fb_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 FB_BLANK_UNBLANK: mode = POWERON; pwr |= 1; scr_off = ON; break; 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 FB_BLANK_HSYNC_SUSPEND: mode = SUSPEND; pwr |= 1; scr_off = OFF; break; case FB_BLANK_POWERDOWN: mode = POWERDOWN; pwr &= ~1; scr_off = OFF; break; 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; 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)) { info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; info->pixmap.scan_align = 2; } else { info->pixmap.scan_align = 1; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; } return 0;}static int i810fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ int err; if (IS_DVT) { var->vmode &= ~FB_VMODE_MASK; var->vmode |= FB_VMODE_NONINTERLACED; } if (var->vmode & FB_VMODE_DOUBLE) { var->vmode &= ~FB_VMODE_MASK; var->vmode |= FB_VMODE_NONINTERLACED; } i810_round_off(var); if ((err = i810_check_params(var, info))) return err; i810fb_fill_var_timings(var); set_color_bitfields(var); return 0;}static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct i810fb_par *par = (struct i810fb_par *)info->par; u8 __iomem *mmio = par->mmio_start_virtual; if (!par->dev_flags & LOCKUP) return -ENXIO; if (cursor->image.width > 64 || cursor->image.height > 64) return -ENXIO; if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) { i810_init_cursor(par); cursor->set |= FB_CUR_SETALL; } i810_enable_cursor(mmio, OFF); if (cursor->set & FB_CUR_SETPOS) { u32 tmp; 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) i810_reset_cursor_image(par); if (cursor->set & FB_CUR_SETCMAP) i810_load_cursor_colors(cursor->image.fg_color, cursor->image.bg_color, info); 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); if (data == NULL) return -ENOMEM; switch (cursor->rop) { case ROP_XOR: for (i = 0; i < size; i++) data[i] = cursor->image.data[i] ^ cursor->mask[i]; break; case ROP_COPY: default: for (i = 0; i < size; i++) data[i] = cursor->image.data[i] & cursor->mask[i]; break; } i810_load_cursor_image(cursor->image.width, cursor->image.height, data, par); kfree(data); } if (cursor->enable) i810_enable_cursor(mmio, ON); return 0;}static struct fb_ops i810fb_ops __devinitdata = { .owner = THIS_MODULE, .fb_open = i810fb_open, .fb_release = i810fb_release, .fb_check_var = i810fb_check_var, .fb_set_par = i810fb_set_par, .fb_setcolreg = i810fb_setcolreg, .fb_blank = i810fb_blank, .fb_pan_display = i810fb_pan_display, .fb_fillrect = i810fb_fillrect, .fb_copyarea = i810fb_copyarea, .fb_imageblit = i810fb_imageblit, .fb_cursor = i810fb_cursor, .fb_sync = i810fb_sync,};/*********************************************************************** * Power Management * ***********************************************************************/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; 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; } 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); } pci_save_state(dev); pci_set_power_state(dev, pci_choose_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); pci_set_power_state(dev, PCI_D0); pci_enable_device(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); info->fbops->fb_blank(VESA_NO_BLANKING, info); par->cur_state = 0; return 0;}/*********************************************************************** * AGP resource allocation * ***********************************************************************/ static void __devinit i810_fix_pointers(struct i810fb_par *par){ par->fb.physical = par->aperture.physical+(par->fb.offset << 12); par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12); par->iring.physical = par->aperture.physical + (par->iring.offset << 12); par->iring.virtual = par->aperture.virtual + (par->iring.offset << 12); par->cursor_heap.virtual = par->aperture.virtual+ (par->cursor_heap.offset << 12);}static void __devinit i810_fix_offsets(struct i810fb_par *par){ if (vram + 1 > par->aperture.size >> 20) vram = (par->aperture.size >> 20) - 1; if (v_offset_default > (par->aperture.size >> 20)) v_offset_default = (par->aperture.size >> 20); if (vram + v_offset_default + 1 > par->aperture.size >> 20) v_offset_default = (par->aperture.size >> 20) - (vram + 1); par->fb.size = vram << 20; 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->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12); par->cursor_heap.size = 4096;}static int __devinit i810_alloc_agp_mem(struct fb_info *info){ struct i810fb_par *par = (struct i810fb_par *) info->par; int size; struct agp_bridge_data *bridge; i810_fix_offsets(par); size = par->fb.size + par->iring.size; if (!(bridge = agp_backend_acquire(par->dev))) { printk("i810fb_alloc_fbmem: cannot acquire agpgart\n"); return -ENODEV; } if (!(par->i810_gtt.i810_fb_memory = agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) { printk("i810fb_alloc_fbmem: can't allocate framebuffer " "memory\n"); agp_backend_release(bridge); return -ENOMEM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -