📄 tridentfb.c
字号:
tmp = (htotal >> 8) & 0x01; tmp |= (hdispend >> 7) & 0x02; tmp |= (hsyncstart >> 5) & 0x08; tmp |= (hblankstart >> 4) & 0x10; write3X4(par, HorizOverflow, tmp); tmp = 0x40; if (vblankstart & 0x200) tmp |= 0x20;//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */ write3X4(par, VGA_CRTC_MAX_SCAN, tmp); write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF); write3X4(par, VGA_CRTC_PRESET_ROW, 0); write3X4(par, VGA_CRTC_MODE, 0xC3); write3X4(par, LinearAddReg, 0x20); /* enable linear addressing */ tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; /* enable access extended memory */ write3X4(par, CRTCModuleTest, tmp); tmp = read3CE(par, MiscIntContReg) & ~0x4; if (info->var.vmode & FB_VMODE_INTERLACED) tmp |= 0x4; write3CE(par, MiscIntContReg, tmp); /* enable GE for text acceleration */ write3X4(par, GraphEngReg, 0x80); switch (bpp) { case 8: tmp = 0x00; break; case 16: tmp = 0x05; break; case 24: tmp = 0x29; break; case 32: tmp = 0x09; break; } write3X4(par, PixelBusReg, tmp); tmp = read3X4(par, DRAMControl); if (!is_oldprotect(par->chip_id)) tmp |= 0x10; if (iscyber(par->chip_id)) tmp |= 0x20; write3X4(par, DRAMControl, tmp); /* both IO, linear enable */ write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40); if (!is_xp(par->chip_id)) write3X4(par, Performance, read3X4(par, Performance) | 0x10); /* MMIO & PCI read and write burst enable */ if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975) write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06); vga_mm_wseq(par->io_virt, 0, 3); vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */ /* enable 4 maps because needed in chain4 mode */ vga_mm_wseq(par->io_virt, 2, 0x0F); vga_mm_wseq(par->io_virt, 3, 0); vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */ /* convert from picoseconds to kHz */ vclk = PICOS2KHZ(info->var.pixclock); /* divide clock by 2 if 32bpp chain4 mode display and CPU path */ tmp = read3CE(par, MiscExtFunc) & 0xF0; if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) { tmp |= 8; vclk *= 2; } set_vclk(par, vclk); write3CE(par, MiscExtFunc, tmp | 0x12); write3CE(par, 0x5, 0x40); /* no CGA compat, allow 256 col */ write3CE(par, 0x6, 0x05); /* graphics mode */ write3CE(par, 0x7, 0x0F); /* planes? */ /* graphics mode and support 256 color modes */ writeAttr(par, 0x10, 0x41); writeAttr(par, 0x12, 0x0F); /* planes */ writeAttr(par, 0x13, 0); /* horizontal pel panning */ /* colors */ for (tmp = 0; tmp < 0x10; tmp++) writeAttr(par, tmp, tmp); fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */ t_outb(par, 0x20, VGA_ATT_W); /* enable attr */ switch (bpp) { case 8: tmp = 0; break; case 16: tmp = 0x30; break; case 24: case 32: tmp = 0xD0; break; } t_inb(par, VGA_PEL_IW); t_inb(par, VGA_PEL_MSK); t_inb(par, VGA_PEL_MSK); t_inb(par, VGA_PEL_MSK); t_inb(par, VGA_PEL_MSK); t_outb(par, tmp, VGA_PEL_MSK); t_inb(par, VGA_PEL_IW); if (par->flatpanel) set_number_of_lines(par, info->var.yres); info->fix.line_length = info->var.xres_virtual * bpp / 8; set_lwidth(par, info->fix.line_length / 8); if (!(info->flags & FBINFO_HWACCEL_DISABLED)) par->init_accel(par, info->var.xres_virtual, bpp); info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->cmap.len = (bpp == 8) ? 256 : 16; debug("exit\n"); return 0;}/* Set one color register */static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ int bpp = info->var.bits_per_pixel; struct tridentfb_par *par = info->par; if (regno >= info->cmap.len) return 1; if (bpp == 8) { t_outb(par, 0xFF, VGA_PEL_MSK); t_outb(par, regno, VGA_PEL_IW); t_outb(par, red >> 10, VGA_PEL_D); t_outb(par, green >> 10, VGA_PEL_D); t_outb(par, blue >> 10, VGA_PEL_D); } else if (regno < 16) { if (bpp == 16) { /* RGB 565 */ u32 col; col = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); col |= col << 16; ((u32 *)(info->pseudo_palette))[regno] = col; } else if (bpp == 32) /* ARGB 8888 */ ((u32 *)info->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); } return 0;}/* Try blanking the screen. For flat panels it does nothing */static int tridentfb_blank(int blank_mode, struct fb_info *info){ unsigned char PMCont, DPMSCont; struct tridentfb_par *par = info->par; debug("enter\n"); if (par->flatpanel) return 0; t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */ PMCont = t_inb(par, 0x83C6) & 0xFC; DPMSCont = read3CE(par, PowerStatus) & 0xFC; switch (blank_mode) { case FB_BLANK_UNBLANK: /* Screen: On, HSync: On, VSync: On */ case FB_BLANK_NORMAL: /* Screen: Off, HSync: On, VSync: On */ PMCont |= 0x03; DPMSCont |= 0x00; break; case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off, HSync: Off, VSync: On */ PMCont |= 0x02; DPMSCont |= 0x01; break; case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off, HSync: On, VSync: Off */ PMCont |= 0x02; DPMSCont |= 0x02; break; case FB_BLANK_POWERDOWN: /* Screen: Off, HSync: Off, VSync: Off */ PMCont |= 0x00; DPMSCont |= 0x03; break; } write3CE(par, PowerStatus, DPMSCont); t_outb(par, 4, 0x83C8); t_outb(par, PMCont, 0x83C6); debug("exit\n"); /* let fbcon do a softblank for us */ return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;}static struct fb_ops tridentfb_ops = { .owner = THIS_MODULE, .fb_setcolreg = tridentfb_setcolreg, .fb_pan_display = tridentfb_pan_display, .fb_blank = tridentfb_blank, .fb_check_var = tridentfb_check_var, .fb_set_par = tridentfb_set_par, .fb_fillrect = tridentfb_fillrect, .fb_copyarea = tridentfb_copyarea, .fb_imageblit = tridentfb_imageblit,#ifdef CONFIG_FB_TRIDENT_ACCEL .fb_sync = tridentfb_sync,#endif};static int __devinit trident_pci_probe(struct pci_dev *dev, const struct pci_device_id *id){ int err; unsigned char revision; struct fb_info *info; struct tridentfb_par *default_par; int chip3D; int chip_id; err = pci_enable_device(dev); if (err) return err; info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev); if (!info) return -ENOMEM; default_par = info->par; chip_id = id->device;#ifndef CONFIG_FB_TRIDENT_ACCEL noaccel = 1;#endif /* If PCI id is 0x9660 then further detect chip type */ if (chip_id == TGUI9660) { revision = vga_io_rseq(RevisionID); switch (revision) { case 0x21: chip_id = PROVIDIA9685; break; case 0x22: case 0x23: chip_id = CYBER9397; break; case 0x2A: chip_id = CYBER9397DVD; break; case 0x30: case 0x33: case 0x34: case 0x35: case 0x38: case 0x3A: case 0xB3: chip_id = CYBER9385; break; case 0x40 ... 0x43: chip_id = CYBER9382; break; case 0x4A: chip_id = CYBER9388; break; default: break; } } chip3D = is3Dchip(chip_id); if (is_xp(chip_id)) { default_par->init_accel = xp_init_accel; default_par->wait_engine = xp_wait_engine; default_par->fill_rect = xp_fill_rect; default_par->copy_rect = xp_copy_rect; tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP; } else if (is_blade(chip_id)) { default_par->init_accel = blade_init_accel; default_par->wait_engine = blade_wait_engine; default_par->fill_rect = blade_fill_rect; default_par->copy_rect = blade_copy_rect; default_par->image_blit = blade_image_blit; tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D; } else if (chip3D) { /* 3DImage family left */ default_par->init_accel = image_init_accel; default_par->wait_engine = image_wait_engine; default_par->fill_rect = image_fill_rect; default_par->copy_rect = image_copy_rect; tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE; } else { /* TGUI 9440/96XX family */ default_par->init_accel = tgui_init_accel; default_par->wait_engine = xp_wait_engine; default_par->fill_rect = tgui_fill_rect; default_par->copy_rect = tgui_copy_rect; tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI; } default_par->chip_id = chip_id; /* setup MMIO region */ tridentfb_fix.mmio_start = pci_resource_start(dev, 1); tridentfb_fix.mmio_len = pci_resource_len(dev, 1); if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) { debug("request_region failed!\n"); framebuffer_release(info); return -1; } default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); if (!default_par->io_virt) { debug("ioremap failed\n"); err = -1; goto out_unmap1; } enable_mmio(default_par); /* setup framebuffer memory */ tridentfb_fix.smem_start = pci_resource_start(dev, 0); tridentfb_fix.smem_len = get_memsize(default_par); if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { debug("request_mem_region failed!\n"); disable_mmio(info->par); err = -1; goto out_unmap1; } info->screen_base = ioremap_nocache(tridentfb_fix.smem_start, tridentfb_fix.smem_len); if (!info->screen_base) { debug("ioremap failed\n"); err = -1; goto out_unmap2; } default_par->flatpanel = is_flatpanel(default_par); if (default_par->flatpanel) nativex = get_nativex(default_par); info->fix = tridentfb_fix; info->fbops = &tridentfb_ops; info->pseudo_palette = default_par->pseudo_pal; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; if (!noaccel && default_par->init_accel) { info->flags &= ~FBINFO_HWACCEL_DISABLED; info->flags |= FBINFO_HWACCEL_COPYAREA; info->flags |= FBINFO_HWACCEL_FILLRECT; } else info->flags |= FBINFO_HWACCEL_DISABLED; info->pixmap.addr = kmalloc(4096, GFP_KERNEL); if (!info->pixmap.addr) { err = -ENOMEM; goto out_unmap2; } info->pixmap.size = 4096; info->pixmap.buf_align = 4; info->pixmap.scan_align = 1; info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; if (default_par->image_blit) { info->flags |= FBINFO_HWACCEL_IMAGEBLIT; info->pixmap.scan_align = 4; } if (noaccel) { printk(KERN_DEBUG "disabling acceleration\n"); info->flags |= FBINFO_HWACCEL_DISABLED; info->pixmap.scan_align = 1; } if (!fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, bpp)) { err = -EINVAL; goto out_unmap2; } err = fb_alloc_cmap(&info->cmap, 256, 0); if (err < 0) goto out_unmap2; info->var.activate |= FB_ACTIVATE_NOW; info->device = &dev->dev; if (register_framebuffer(info) < 0) { printk(KERN_ERR "tridentfb: could not register framebuffer\n"); fb_dealloc_cmap(&info->cmap); err = -EINVAL; goto out_unmap2; } output("fb%d: %s frame buffer device %dx%d-%dbpp\n", info->node, info->fix.id, info->var.xres, info->var.yres, info->var.bits_per_pixel); pci_set_drvdata(dev, info); return 0;out_unmap2: kfree(info->pixmap.addr); if (info->screen_base) iounmap(info->screen_base); release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); disable_mmio(info->par);out_unmap1: if (default_par->io_virt) iounmap(default_par->io_virt); release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); framebuffer_release(info); return err;}static void __devexit trident_pci_remove(struct pci_dev *dev){ struct fb_info *info = pci_get_drvdata(dev); struct tridentfb_par *par = info->par; unregister_framebuffer(info); iounmap(par->io_virt); iounmap(info->screen_base); release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); pci_set_drvdata(dev, NULL); kfree(info->pixmap.addr); framebuffer_release(info);}/* List of boards that we are trying to support */static struct pci_device_id trident_devices[] = { {PCI_VENDOR_ID_TRIDENT, BLADE3D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi7D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBER9320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBER9388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBER9520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBER9525DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBER9397, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBER9397DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPm8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_TRIDENT, CYBERBLADEXPm16, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0,}};MODULE_DEVICE_TABLE(pci, trident_devices);static struct pci_driver tridentfb_pci_driver = { .name = "tridentfb", .id_table = trident_devices, .probe = trident_pci_probe, .remove = __devexit_p(trident_pci_remove)};/* * Parse user specified options (`video=trident:') * example: * video=trident:800x600,bpp=16,noaccel */#ifndef MODULEstatic int __init tridentfb_setup(char *options){ char *opt; if (!options || !*options) return 0; while ((opt = strsep(&options, ",")) != NULL) { if (!*opt) continue; if (!strncmp(opt, "noaccel", 7)) noaccel = 1; else if (!strncmp(opt, "fp", 2)) fp = 1; else if (!strncmp(opt, "crt", 3)) fp = 0; else if (!strncmp(opt, "bpp=", 4)) bpp = simple_strtoul(opt + 4, NULL, 0); else if (!strncmp(opt, "center", 6)) center = 1; else if (!strncmp(opt, "stretch", 7)) stretch = 1; else if (!strncmp(opt, "memsize=", 8)) memsize = simple_strtoul(opt + 8, NULL, 0); else if (!strncmp(opt, "memdiff=", 8)) memdiff = simple_strtoul(opt + 8, NULL, 0); else if (!strncmp(opt, "nativex=", 8)) nativex = simple_strtoul(opt + 8, NULL, 0); else mode_option = opt; } return 0;}#endifstatic int __init tridentfb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("tridentfb", &option)) return -ENODEV; tridentfb_setup(option);#endif return pci_register_driver(&tridentfb_pci_driver);}static void __exit tridentfb_exit(void){ pci_unregister_driver(&tridentfb_pci_driver);}module_init(tridentfb_init);module_exit(tridentfb_exit);MODULE_AUTHOR("Jani Monoses <jani@iv.ro>");MODULE_DESCRIPTION("Framebuffer driver for Trident cards");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -