tridentfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,298 行 · 第 1/3 页
C
1,298 行
if (vsyncstart & 0x400) tmp |= 0x20; if (vdispend & 0x400) tmp |= 0x10; write3X4(CRTHiOrd, tmp); tmp = 0; if (htotal & 0x800) tmp |= 0x800 >> 11; if (hblankstart & 0x800) tmp |= 0x800 >> 7; write3X4(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(CRTMaxScanLine, tmp); write3X4(CRTLineCompare,0xFF); write3X4(CRTPRowScan,0); write3X4(CRTModeControl,0xC3); write3X4(LinearAddReg,0x20); //enable linear addressing tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84:0x80; write3X4(CRTCModuleTest,tmp); //enable access extended memory write3X4(GraphEngReg, 0x80); //enable GE for text acceleration// if (info->var.accel_flags & FB_ACCELF_TEXT)//FIXME acc->init_accel(info->var.xres,bpp); switch (bpp) { case 8: tmp = 0x00; break; case 16: tmp = 0x05; break; case 24: tmp = 0x29; break; case 32: tmp = 0x09; } write3X4(PixelBusReg, tmp); tmp = 0x10; if (chipcyber) tmp |= 0x20; write3X4(DRAMControl, tmp); //both IO,linear enable write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); write3X4(Performance,0x20); write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable /* convert from picoseconds to MHz */ par->vclk = 1000000/info->var.pixclock; if (bpp == 32) par->vclk *=2; set_vclk(par->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,(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? if (chip_id == CYBERBLADEXPAi1) { /* This fixes snow-effect in 32 bpp */ write3X4(CRTHSyncStart,0x84); } 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(par->io_virt + CRT + 0x0A); //flip-flop to index t_outb(0x20, 0x3C0); //enable attr switch (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(info->var.yres); set_lwidth(info->var.xres * bpp/(4*16)); info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->fix.line_length = info->var.xres * (bpp >> 3); 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; if (regno >= info->cmap.len) return 1; 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 tridentfb_blank(int blank_mode, struct fb_info *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;}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); chipcyber = iscyber(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.par = &default_par; /* setup MMIO region */ tridentfb_fix.mmio_start = pci_resource_start(dev,1); tridentfb_fix.mmio_len = chip3D ? 0x20000:0x10000; if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) { debug("request_region failed!\n"); return -1; } default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); if (!default_par.io_virt) { release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); debug("ioremap failed\n"); return -1; } enable_mmio(); /* setup framebuffer memory */ tridentfb_fix.smem_start = pci_resource_start(dev,0); tridentfb_fix.smem_len = get_memsize(); if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { debug("request_mem_region failed!\n"); return -1; } fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start, tridentfb_fix.smem_len); if (!fb_info.screen_base) { release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); debug("ioremap failed\n"); return -1; } output("%s board found\n", pci_name(dev));#if 0 output("Trident board found : mem = %X,io = %X, mem_v = %X, io_v = %X\n", tridentfb_fix.smem_start, tridentfb_fix.mmio_start, fb_info.screen_base, default_par.io_virt);#endif displaytype = get_displaytype(); if(flatpanel) nativex = get_nativex(); fb_info.fix = tridentfb_fix; fb_info.fbops = &tridentfb_ops; fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;#ifdef CONFIG_FB_TRIDENT_ACCEL fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;#endif fb_info.pseudo_palette = pseudo_pal; if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp)) return -EINVAL; fb_alloc_cmap(&fb_info.cmap,256,0); if (defaultaccel && acc) default_var.accel_flags |= FB_ACCELF_TEXT; else default_var.accel_flags &= ~FB_ACCELF_TEXT; default_var.activate |= FB_ACTIVATE_NOW; fb_info.var = default_var; if (register_framebuffer(&fb_info) < 0) { output("Could not register Trident framebuffer\n"); return -EINVAL; } output("fb%d: %s frame buffer device %dx%d-%dbpp\n", fb_info.node, fb_info.fix.id,default_var.xres, default_var.yres,default_var.bits_per_pixel); return 0;}static void __devexit trident_pci_remove(struct pci_dev * dev){ struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par; unregister_framebuffer(&fb_info); iounmap(par->io_virt); iounmap(fb_info.screen_base); release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);}/* 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, 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 tridentfb_setup(char *options);int __init tridentfb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("tridentfb", &option)) return -ENODEV; tridentfb_setup(option);#endif 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 = { .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 = cfb_imageblit, .fb_cursor = soft_cursor,};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 + =
减小字号Ctrl + -
显示快捷键?