📄 tridentfb.c
字号:
if (p->vdispend & 0x200) tmp |= 0x40; if (p->vsyncstart & 0x200) tmp |= 0x80; write3X4(CRTOverflow, tmp); tmp = read3X4(CRTHiOrd) | 0x08; //line compare bit 10 if (p->vtotal & 0x400) tmp |= 0x80; if (p->vblankstart & 0x400) tmp |= 0x40; if (p->vsyncstart & 0x400) tmp |= 0x20; if (p->vdispend & 0x400) tmp |= 0x10; write3X4(CRTHiOrd, tmp); write3X4(HorizOverflow, 0); tmp = 0x40; if (p->vblankstart & 0x200) tmp |= 0x20; if (p->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; //double scan for 200 line modes write3X4(CRTMaxScanLine, tmp); write3X4(CRTLineCompare,0xFF); write3X4(CRTPRowScan,0); write3X4(CRTModeControl,0xC3); write3X4(LinearAddReg,0x20); //enable linear addressing tmp = (p->var.vmode & FB_VMODE_INTERLACED) ? 0x84:0x80; write3X4(CRTCModuleTest,tmp); //enable access extended memory write3X4(GraphEngReg, 0x80); //enable GE for text acceleration if (p->var.accel_flags & FB_ACCELF_TEXT) acc->init_accel(p->hres,p->bpp); switch (p->bpp) { case 8:tmp=0;break; case 16:tmp=5;break; case 24: /* tmp=0x29;break; */ /* seems like 24bpp is same as 32bpp when using vesafb */ case 32:tmp=9;break; } write3X4(PixelBusReg, tmp); write3X4(InterfaceSel, 0x5B); //32bit internal data path write3X4(DRAMControl, 0x30); //both IO,linear enable write3X4(Performance, 0xBF); write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable set_vclk(p->vclk); write3C4(0,3); write3C4(1,1); //set char clock 8 dots wide write3C4(2,0x0F); //enable 4 maps because needed in chain4 mode write3C4(3,0); write3C4(4,0x0E); //memory mode enable bitmaps ?? write3CE(MiscExtFunc,(p->bpp==32)?0x1A:0x12); //divide clock by 2 if 32bpp //chain4 mode display and CPU path write3CE(0x5,0x40); //no CGA compat,allow 256 col write3CE(0x6,0x05); //graphics mode write3CE(0x7,0x0F); //planes? writeAttr(0x10,0x41); //graphics mode and support 256 color modes writeAttr(0x12,0x0F); //planes writeAttr(0x13,0); //horizontal pel panning //colors for(tmp = 0;tmp < 0x10;tmp++) writeAttr(tmp,tmp); readb(fb_info.io_virt + CRT + 0x0A); //flip-flop to index t_outb(0x20, 0x3C0); //enable attr switch (p->bpp) { case 8: tmp = 0;break; //256 colors case 15: tmp = 0x10;break; case 16: tmp = 0x30;break; //hicolor case 24: //truecolor case 32: tmp = 0xD0;break; } t_inb(0x3C8); t_inb(0x3C6); t_inb(0x3C6); t_inb(0x3C6); t_inb(0x3C6); t_outb(tmp,0x3C6); t_inb(0x3C8); if (flatpanel) set_number_of_lines(p->vres); set_lwidth(p->hres*p->bpp/(4*16)); trident_pan_display(&p->var,info); debug("exit\n");}/* Get value of one color register */static int trident_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){ struct tridentfb_info * i = (struct tridentfb_info *)info; int m = i->currentmode.bpp==8?256:16; debug("enter %d\n",regno); if (regno >= m) return 1; *red = palette[regno].red; *green = palette[regno].green; *blue = palette[regno].blue; *transp = palette[regno].transp; debug("exit\n"); return 0;}/* Set one color register */static int trident_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct tridentfb_info * i = (struct tridentfb_info *)info; int bpp = i->currentmode.bpp; int m = bpp==8?256:16; debug("enter %d\n",regno); if (regno >= m) return 1; palette[regno].red = red; palette[regno].green = green; palette[regno].blue = blue; palette[regno].transp = transp; if (bpp==8) { t_outb(0xFF,0x3C6); t_outb(regno,0x3C8); t_outb(red>>10,0x3C9); t_outb(green>>10,0x3C9); t_outb(blue>>10,0x3C9); } else if (bpp == 16) /* RGB 565 */ ((u16*)info->pseudo_palette)[regno] = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); else if (bpp == 32) /* ARGB 8888 */ ((u32*)info->pseudo_palette)[regno] = ((transp & 0xFF00) <<16) | ((red & 0xFF00) << 8) | ((green & 0xFF00)) | ((blue & 0xFF00)>>8); debug("exit\n"); return 0;}/* Try blanking the screen.For flat panels it does nothing */static int trident_blank(int blank_mode, struct fb_info_gen *info){ unsigned char PMCont,DPMSCont; debug("enter\n"); if (flatpanel) return 0; t_outb(0x04,0x83C8); /* Read DPMS Control */ PMCont = t_inb(0x83C6) & 0xFC; DPMSCont = read3CE(PowerStatus) & 0xFC; switch (blank_mode) { case VESA_NO_BLANKING: /* Screen: On, HSync: On, VSync: On */ PMCont |= 0x03; DPMSCont |= 0x00; break; case VESA_HSYNC_SUSPEND: /* Screen: Off, HSync: Off, VSync: On */ PMCont |= 0x02; DPMSCont |= 0x01; break; case VESA_VSYNC_SUSPEND: /* Screen: Off, HSync: On, VSync: Off */ PMCont |= 0x02; DPMSCont |= 0x02; break; case VESA_POWERDOWN: /* Screen: Off, HSync: Off, VSync: Off */ PMCont |= 0x00; DPMSCont |= 0x03; break; } write3CE(PowerStatus,DPMSCont); t_outb(4,0x83C8); t_outb(PMCont,0x83C6); debug("exit\n"); return 0;}/* Set display switch used by console */static void trident_set_disp(const void *par, struct display *disp, struct fb_info_gen *info){ struct tridentfb_info * i = (struct tridentfb_info *)info; struct fb_info * ii = (struct fb_info *)info; struct tridentfb_par * p = (struct tridentfb_par *)par; int isaccel = p->var.accel_flags & FB_ACCELF_TEXT; disp->screen_base = (char *)i->fbmem_virt; debug("enter\n");#ifdef FBCON_HAS_CFB8 if (p->bpp == 8 ) { if (isaccel) disp->dispsw = &trident_8bpp; else disp->dispsw = &fbcon_cfb8; } else#endif#ifdef FBCON_HAS_CFB16 if (p->bpp == 16) { if (isaccel) disp->dispsw = &trident_16bpp; else disp->dispsw = &fbcon_cfb16; disp->dispsw_data =ii->pseudo_palette; /* console palette */ } else#endif#ifdef FBCON_HAS_CFB32 if (p->bpp == 32) { if (isaccel) disp->dispsw = &trident_32bpp; else disp->dispsw = &fbcon_cfb32; disp->dispsw_data =ii->pseudo_palette; /* console palette */ } else#endif disp->dispsw = &fbcon_dummy; debug("exit\n");}static struct fbgen_hwswitch trident_hwswitch = { NULL, /* detect not needed */ trident_encode_fix, trident_decode_var, trident_encode_var, trident_get_par, trident_set_par, trident_getcolreg, trident_setcolreg, trident_pan_display, trident_blank, trident_set_disp};static int trident_iosize;static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_device_id * id){ int err; unsigned char revision; err = pci_enable_device(dev); if (err) return err; chip_id = id->device; /* If PCI id is 0x9660 then further detect chip type */ if (chip_id == TGUI9660) { outb(RevisionID,0x3C4); revision = inb(0x3C5); switch (revision) { 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)) { acc = &accel_xp; } else if (is_blade(chip_id)) { acc = &accel_blade; } else { acc = &accel_image; } /* acceleration is on by default for 3D chips */ defaultaccel = chip3D && !noaccel; fb_info.io = pci_resource_start(dev,1); fb_info.fbmem = pci_resource_start(dev,0); trident_iosize = chip3D ? 0x20000:0x10000; if (!request_mem_region(fb_info.io, trident_iosize, "tridentfb")) { debug("request_region failed!\n"); return -1; } fb_info.io_virt = (unsigned long)ioremap_nocache(fb_info.io, trident_iosize); if (!fb_info.io_virt) { release_region(fb_info.io, trident_iosize); debug("ioremap failed\n"); return -1; } enable_mmio(); fb_info.memsize = get_memsize(); if (!request_mem_region(fb_info.fbmem, fb_info.memsize, "tridentfb")) { debug("request_mem_region failed!\n"); return -1; } fb_info.fbmem_virt = (unsigned long)ioremap_nocache(fb_info.fbmem, fb_info.memsize); if (!fb_info.fbmem_virt) { release_mem_region(fb_info.fbmem, fb_info.memsize); debug("ioremap failed\n"); return -1; } output("%s board found\n", dev->name); debug("Trident board found : mem = %X,io = %X, mem_v = %X, io_v = %X\n", fb_info.fbmem, fb_info.io, fb_info.fbmem_virt, fb_info.io_virt); fb_info.gen.parsize = sizeof (struct tridentfb_par); fb_info.gen.fbhw = &trident_hwswitch; strcpy(fb_info.gen.info.modename, tridentfb_name); displaytype = get_displaytype(); if(flatpanel) fb_info.nativex = get_nativex(); fb_info.gen.info.changevar = NULL; fb_info.gen.info.node = NODEV; fb_info.gen.info.fbops = &tridentfb_ops; fb_info.gen.info.disp = &disp; fb_info.gen.info.switch_con = &fbgen_switch; fb_info.gen.info.updatevar = &fbgen_update_var; fb_info.gen.info.blank = &fbgen_blank; fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; fb_info.gen.info.fontname[0] = '\0'; fb_info.gen.info.pseudo_palette = pseudo_pal; /* This should give a reasonable default video mode */ fb_find_mode(&default_var,&fb_info.gen.info,mode,NULL,0,NULL,bpp); if (defaultaccel && acc) default_var.accel_flags |= FB_ACCELF_TEXT; else default_var.accel_flags &= ~FB_ACCELF_TEXT; trident_decode_var(&default_var, &fb_info.currentmode, &fb_info.gen); fbgen_get_var(&disp.var, -1, &fb_info.gen.info); default_var.activate |= FB_ACTIVATE_NOW; fbgen_set_disp(-1, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) { printk("Could not register Trident framebuffer\n"); return -EINVAL; } output("fb%d: %s frame buffer device %dx%d-%dbpp\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,default_var.xres, default_var.yres,default_var.bits_per_pixel); return 0;}static void __devexit trident_pci_remove(struct pci_dev * dev){ unregister_framebuffer(&fb_info.gen.info); iounmap((void *)fb_info.io_virt); iounmap((void *)fb_info.fbmem_virt); release_mem_region(fb_info.fbmem, fb_info.memsize); release_region(fb_info.io, trident_iosize);}/* List of boards that we are trying to support */static struct pci_device_id trident_devices[] __devinitdata = { {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, 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),};int __init tridentfb_init(void){ output("Trident framebuffer %s initializing\n", VERSION); return pci_module_init(&tridentfb_pci_driver);}void __exit tridentfb_exit(void){ pci_unregister_driver(&tridentfb_pci_driver);}/* * Parse user specified options (`video=trident:') * example: * video=trident:800x600,bpp=16,noaccel */int 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)) displaytype = DISPLAY_FP; else if (!strncmp(opt,"crt",3)) displaytype = DISPLAY_CRT; 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 = opt; } return 0;}static struct fb_ops tridentfb_ops = { fb_get_fix:fbgen_get_fix, fb_get_var:fbgen_get_var, fb_set_var:fbgen_set_var, fb_get_cmap:fbgen_get_cmap, fb_set_cmap:fbgen_set_cmap, fb_pan_display:fbgen_pan_display,};#ifdef MODULEmodule_init(tridentfb_init);#endifmodule_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 + -