sstfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,724 行 · 第 1/4 页
C
1,724 行
sst_wait_idle(); sst_write(FBIINIT1, fbiinit1); sst_wait_idle(); sst_write(FBIINIT2, FBIINIT2_DEFAULT); sst_wait_idle(); sst_write(FBIINIT3, FBIINIT3_DEFAULT); sst_wait_idle(); sst_write(FBIINIT4, fbiinit4); sst_wait_idle(); if (IS_VOODOO2(par)) { sst_write(FBIINIT6, FBIINIT6_DEFAULT); sst_wait_idle(); } pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR); pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0); return 1;}static void __devexit sst_shutdown(struct fb_info *info){ struct sstfb_par *par = (struct sstfb_par *) info->par; struct pci_dev *dev = par->dev; struct pll_timing gfx_timings; int Fout; /* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING); sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH); sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET); sst_wait_idle(); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR | PCI_REMAP_DAC); /* set 20Mhz gfx clock */ sst_calc_pll(20000, &Fout, &gfx_timings); par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK); /* TODO maybe shutdown the dac, vrefresh and so on... */ pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH); pci_write_config_dword(dev, PCI_VCLK_DISABLE,0); /* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct * from start ? */ pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);}/* * Interface to the world */int __init sstfb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; f_ddprintk("option %s\n", this_opt); if (!strcmp(this_opt, "vganopass")) vgapass = 0; else if (!strcmp(this_opt, "vgapass")) vgapass = 1; else if (!strcmp(this_opt, "clipping")) clipping = 1; else if (!strcmp(this_opt, "noclipping")) clipping = 0; else if (!strcmp(this_opt, "fastpci")) slowpci = 0; else if (!strcmp(this_opt, "slowpci")) slowpci = 1; else if (!strncmp(this_opt, "mem:",4)) mem = simple_strtoul (this_opt+4, NULL, 0); else if (!strncmp(this_opt, "gfxclk:",7)) gfxclk = simple_strtoul (this_opt+7, NULL, 0); else mode_option = this_opt; } return 0;}static struct fb_ops sstfb_ops = { .owner = THIS_MODULE, .fb_check_var = sstfb_check_var, .fb_set_par = sstfb_set_par, .fb_setcolreg = sstfb_setcolreg, .fb_fillrect = cfb_fillrect, /* sstfb_fillrect */ .fb_copyarea = cfb_copyarea, /* sstfb_copyarea */ .fb_imageblit = cfb_imageblit, .fb_cursor = soft_cursor, .fb_ioctl = sstfb_ioctl,};static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id){ struct fb_info *info; struct fb_fix_screeninfo *fix; struct sstfb_par *par; struct sst_spec *spec; int err; struct all_info { struct fb_info info; struct sstfb_par par; u32 pseudo_palette[16]; } *all; /* Enable device in PCI config. */ if ((err=pci_enable_device(pdev))) { eprintk("cannot enable device\n"); return err; } /* Allocate the fb and par structures. */ all = kmalloc(sizeof(*all), GFP_KERNEL); if (!all) return -ENOMEM; memset(all, 0, sizeof(*all)); pci_set_drvdata(pdev, all); info = &all->info; par = info->par = &all->par; fix = &info->fix; par->type = id->driver_data; spec = &voodoo_spec[par->type]; f_ddprintk("found device : %s\n", spec->name); par->dev = pdev; pci_read_config_byte(pdev, PCI_REVISION_ID, &par->revision); fix->mmio_start = pci_resource_start(pdev,0); fix->mmio_len = 0x400000; fix->smem_start = fix->mmio_start + 0x400000; if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) { eprintk("cannot reserve mmio memory\n"); goto fail_mmio_mem; } if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) { eprintk("cannot reserve fb memory\n"); goto fail_fb_mem; } par->mmio_vbase = (u_long) ioremap_nocache(fix->mmio_start, fix->mmio_len); if (!par->mmio_vbase) { eprintk("cannot remap register area %#lx\n", fix->mmio_start); goto fail_mmio_remap; } info->screen_base = ioremap_nocache(fix->smem_start, 0x400000); if (!info->screen_base) { eprintk("cannot remap framebuffer %#lx\n", fix->smem_start); goto fail_fb_remap; } if (!sst_init(info, par)) { eprintk("Init failed\n"); goto fail; } sst_get_memsize(info, &fix->smem_len); strlcpy(fix->id, spec->name, sizeof(fix->id)); iprintk("%s (revision %d) with %s dac\n", fix->id, par->revision, par->dac_sw.name); iprintk("framebuffer at %#lx, mapped to 0x%p, size %dMB\n", fix->smem_start, info->screen_base, fix->smem_len >> 20); f_ddprintk("regbase_virt: %#lx\n", par->mmio_vbase); f_ddprintk("membase_phys: %#lx\n", fix->smem_start); f_ddprintk("fbbase_virt: %p\n", info->screen_base); info->flags = FBINFO_DEFAULT; info->fbops = &sstfb_ops; info->currcon = -1; info->pseudo_palette = &all->pseudo_palette; fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_TRUECOLOR; fix->accel = FB_ACCEL_NONE; /* FIXME */ /* * According to the specs, the linelength must be of 1024 *pixels* * and the 24bpp mode is in fact a 32 bpp mode. */ fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */ if ( mode_option && fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) { eprintk("can't set supplied video mode. Using default\n"); info->var = sstfb_default; } else info->var = sstfb_default; if (sstfb_check_var(&info->var, info)) { eprintk("invalid default video mode.\n"); goto fail; } if (sstfb_set_par(info)) { eprintk("can't set default video mode.\n"); goto fail; } fb_alloc_cmap(&info->cmap, 256, 0); /* register fb */ if (register_framebuffer(info) < 0) { eprintk("can't register framebuffer.\n"); goto fail; } if (1) /* set to 0 to see an initial bitmap instead */ sstfb_clear_screen(info); else sstfb_drawdebugimage(info); printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n", info->node, fix->id, info->screen_base); return 0;fail: iounmap(info->screen_base);fail_fb_remap: iounmap((void *)par->mmio_vbase);fail_mmio_remap: release_mem_region(fix->smem_start, 0x400000);fail_fb_mem: release_mem_region(fix->mmio_start, info->fix.mmio_len);fail_mmio_mem: kfree(info); return -ENXIO; /* no voodoo detected */}static void __devexit sstfb_remove(struct pci_dev *pdev){ struct sstfb_par *par; struct fb_info *info; info = pci_get_drvdata(pdev); par = (struct sstfb_par *) info->par; sst_shutdown(info); unregister_framebuffer(info); iounmap(info->screen_base); iounmap((void*)par->mmio_vbase); release_mem_region(info->fix.smem_start, 0x400000); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); kfree(info);}static struct pci_device_id sstfb_id_tbl[] = { { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 }, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 }, { 0 },};static struct pci_driver sstfb_driver = { .name = "sstfb", .id_table = sstfb_id_tbl, .probe = sstfb_probe, .remove = __devexit_p(sstfb_remove),};int __devinit sstfb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("sstfb", &option)) return -ENODEV; sstfb_setup(option);#endif return pci_module_init(&sstfb_driver);}void __devexit sstfb_exit(void){ pci_unregister_driver(&sstfb_driver);}/* * testing and debugging functions */static int sstfb_dump_regs(struct fb_info *info){#ifdef SST_DEBUG static struct { u32 reg ; const char *reg_name;} pci_regs[] = { { PCI_INIT_ENABLE, "initenable"}, { PCI_VCLK_ENABLE, "enable vclk"}, { PCI_VCLK_DISABLE, "disable vclk"}, }; static struct { u32 reg ; const char *reg_name;} sst_regs[] = { {FBIINIT0,"fbiinit0"}, {FBIINIT1,"fbiinit1"}, {FBIINIT2,"fbiinit2"}, {FBIINIT3,"fbiinit3"}, {FBIINIT4,"fbiinit4"}, {FBIINIT5,"fbiinit5"}, {FBIINIT6,"fbiinit6"}, {FBIINIT7,"fbiinit7"}, {LFBMODE,"lfbmode"}, {FBZMODE,"fbzmode"}, }; const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]); const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]); struct sstfb_par *par = (struct sstfb_par *) info->par; struct pci_dev *dev = par->dev; u32 pci_res[pci_s]; u32 sst_res[sst_s]; int i; for (i=0; i<pci_s; i++) { pci_read_config_dword(dev, pci_regs[i].reg, &pci_res[i]); } for (i=0; i<sst_s; i++) { sst_res[i] = sst_read(sst_regs[i].reg); } dprintk("hardware register dump:\n"); for (i=0; i<pci_s; i++) { dprintk("%s %0#10x\n", pci_regs[i].reg_name, pci_res[i]); } for (i=0; i<sst_s; i++) { dprintk("%s %0#10x\n", sst_regs[i].reg_name, sst_res[i]); } return 0;#else return -EINVAL;#endif}static void sstfb_fillrect_softw( struct fb_info *info, const struct fb_fillrect *rect){ unsigned long fbbase_virt = (unsigned long) info->screen_base; int x, y, w = info->var.bits_per_pixel == 16 ? 2 : 4; u32 color = rect->color, height = rect->height; unsigned long p; if (w==2) color |= color<<16; for (y=rect->dy; height; y++, height--) { p = fbbase_virt + y*info->fix.line_length + rect->dx*w; x = rect->width; if (w==2) x>>=1; while (x) { writel(color, p); p += 4; x--; } }}static void sstfb_drawrect_XY( struct fb_info *info, int x, int y, int w, int h, int color, int hwfunc){ struct fb_fillrect rect; rect.dx = x; rect.dy = y; rect.height = h; rect.width = w; rect.color = color; rect.rop = ROP_COPY; if (hwfunc) sstfb_fillrect(info, &rect); else sstfb_fillrect_softw(info, &rect);}/* print some squares on the fb */static void sstfb_drawdebugimage(struct fb_info *info){ static int idx; /* clear screen */ sstfb_clear_screen(info); idx = (idx+1) & 1; /* white rect */ sstfb_drawrect_XY(info, 0, 0, 50, 50, 0xffff, idx); /* blue rect */ sstfb_drawrect_XY(info, 50, 50, 50, 50, 0x001f, idx); /* green rect */ sstfb_drawrect_XY(info, 100, 100, 80, 80, 0x07e0, idx); /* red rect */ sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);}module_init(sstfb_init);#ifdef MODULEmodule_exit(sstfb_exit);#endifMODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");MODULE_LICENSE("GPL");MODULE_PARM(mem, "i");MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");MODULE_PARM(vgapass, "i");MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");MODULE_PARM(clipping , "i");MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");MODULE_PARM(gfxclk , "i");MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");MODULE_PARM(slowpci, "i");MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?