📄 sstfb.c
字号:
/* TODO maybe shutdown the dac, vrefresh and so on... */ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH); pci_write_config_dword(sst_dev, PCI_VCLK_DISABLE,0);/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct at the beginining ? */ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, 0);}/* * Interface to the world */int __init sstfb_setup(char *options){ char *this_opt; f_dprintk("sstfb_setup\n"); if (!options || !*options) return 0; for(this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { //XXX//XXX while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; f_ddprintk("option %s\n", this_opt); if (!strcmp(this_opt, "inverse")) { inverse = 1; fb_invert_cmaps(); } else 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 if (!strncmp(this_opt, "dev:",4)) dev=simple_strtoul (this_opt+4, NULL, 0); else mode_option=this_opt; } return 0;}int __devinit sstfb_init(void){ f_dprintk("sstfb_init\n"); dprintk("Compile date: "__DATE__" "__TIME__"\n"); return pci_module_init(&sstfb_driver);}void __devexit sstfb_exit(void){ f_dprintk("sstfb_exit\n"); pci_unregister_driver(&sstfb_driver);}#ifdef MODULEmodule_init(sstfb_init);module_exit(sstfb_exit);#endifstatic int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id){ struct fb_var_screeninfo var; struct sstfb_info * sst_info; struct sst_spec * spec; int tmp,err; f_dprintk("sstfb_probe\n"); /* dev > 0 the device is not the one asked for. skip */ /* dev == 0 this is the device the user asked. init */ /* dev == -1 we already inited the asked device. skip */ /* dev < -1 init all devices. including this one. init */ if ((dev == -1 ) || (dev-- > 0)) return -1; if ((err=pci_enable_device(pdev))) { eprintk("cannot enable device\n"); return err; } sst_info = (struct sstfb_info*)kmalloc(sizeof(*sst_info), GFP_KERNEL); if (!sst_info) goto fail_kmalloc; pci_set_drvdata(pdev, sst_info); sst_info->type = id->driver_data; spec = &voodoo_spec[sst_info->type]; f_ddprintk("found device : %s\n", spec->name); sst_info->dev = pdev; pci_read_config_byte(pdev, PCI_REVISION_ID, &sst_info->revision); sst_info->mmio.base = pci_resource_start(pdev,0); sst_info->video.base = sst_info->mmio.base+0x400000; if (!request_mem_region(sst_info->mmio.base,0x400000,"sstfb MMIO")) { eprintk ("cannot reserve mmio memory\n"); goto fail_mmio_mem; } if (!request_mem_region(sst_info->video.base,0x400000,"sstfb FB")) { eprintk ("cannot reserve fb memory\n"); goto fail_fb_mem; } sst_info->mmio.vbase = (u_long) ioremap_nocache(sst_info->mmio.base, 0x400000); if (!sst_info->mmio.vbase) { eprintk("cannot remap register area %#lx\n", sst_info->mmio.base); goto fail_mmio_remap; } sst_info->video.vbase = (u_long) ioremap_nocache(sst_info->video.base, 0x400000); if (!sst_info->video.vbase) { eprintk("cannot remap framebuffer %#lx\n", sst_info->video.base); goto fail_fb_remap; } if(!sst_init(sst_info)) { eprintk("Init failed\n"); goto fail; } sst_get_memsize(sst_info, &sst_info->video.len); strncpy(sst_info->info.modename, spec->name, 16); iprintk("%s with %s dac\n", sst_info->info.modename, sst_info->dac_sw.name); iprintk("framebuffer at %#lx, mapped to %#lx," " size %ldMb\n", sst_info->video.base, sst_info->video.vbase, sst_info->video.len >> 20); f_ddprintk("revision: %d\n", sst_info->revision); f_ddprintk("regbase_virt: %#lx\n", sst_info->mmio.vbase); f_ddprintk("membase_phys: %#lx\n", sst_info->video.base); f_ddprintk("fbbase_virt: %#lx\n", sst_info->video.vbase); sst_info->info.node = -1 ; sst_info->info.flags = FBINFO_FLAG_DEFAULT; sst_info->info.fbops = &sstfb_ops; sst_info->info.disp = &sst_info->disp; sst_info->info.changevar = NULL; sst_info->info.switch_con = &sstfbcon_switch; sst_info->info.updatevar = &sstfbcon_updatevar; sst_info->info.blank = &sstfbcon_blank; tmp=0; var = sstfb_default; if ( mode_option && fb_find_mode(&var, &sst_info->info, mode_option, NULL, 0, NULL, 16)) { if (sstfb_set_var(&var, -1, &sst_info->info)) { eprintk("can't set supplied video mode. Using default\n"); var = sstfb_default; } else { /* set the new default */ sstfb_default = var; tmp=1; /* no need to set the mode. */ } } if (!tmp && sstfb_set_var(&var, -1, &sst_info->info)) { eprintk("can't set default video mode.\n"); goto fail; } /*clear fb */ memset_io(sst_info->video.vbase, 0, sst_info->video.len); /* print some squares ... */ sstfb_test16(sst_info); /* FIXME this is only for 16bpp */ /* register fb */ if (register_framebuffer(&sst_info->info) < 0) { eprintk("can't register framebuffer.\n"); goto fail; } printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(sst_info->info.node),sst_info->info.modename); return 0;fail: iounmap((void *)sst_info->video.base);fail_fb_remap: iounmap((void *)sst_info->mmio.base);fail_mmio_remap: release_mem_region(sst_info->video.base,0x400000);fail_fb_mem: release_mem_region(sst_info->mmio.base,0x400000);fail_mmio_mem: kfree(sst_info);fail_kmalloc: return -ENXIO; /* no voodoo detected */}static void __devexit sstfb_remove(struct pci_dev *pdev){ struct sstfb_info * sst_info; f_dprintk("sstfb_remove\n"); sst_info=pci_get_drvdata(pdev); sst_shutdown(sst_info); unregister_framebuffer(&sst_info->info); iounmap((void*)sst_info->video.vbase); iounmap((void*)sst_info->mmio.vbase); release_mem_region(sst_info->video.base,0x400000); release_mem_region(sst_info->mmio.base,0x400000); kfree(sst_info);}/* * console driver */static int sstfbcon_switch(int con, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) struct sstfb_par par; f_dprintk("sstfbcon_switch(con: %d)\n",con); f_ddprintk("currcon: %d\n", sst_info->currcon); v_dprintk("currcon: %d\n", sst_info->currcon); if (sst_info->currcon >= 0) { if (fb_display[sst_info->currcon].cmap.len) fb_get_cmap(&fb_display[sst_info->currcon].cmap, 1, sstfb_getcolreg, info); } sst_info->currcon = con; fb_display[con].var.activate = FB_ACTIVATE_NOW; print_var(&fb_display[con].var, "&fb_display[con: %d].var",con); sstfb_decode_var(&fb_display[con].var, &par, sst_info); if (memcmp(&par,&(sst_info->current_par),sizeof(par))) { sstfb_set_par(&par, sst_info); } sstfb_install_cmap(con, info); return 0;#undef sst_info}static int sstfbcon_updatevar(int con, struct fb_info *info){ f_dprintk("sstfbcon_updatevar\n"); return -EINVAL;}static void sstfbcon_blank(int blank, struct fb_info *info){ f_dprintk("sstfbcon_blank(level %d)\n", blank);}/* print some squares on the fb (presuming 16bpp) */static void sstfb_test16(struct sstfb_info *sst_info){ int i,j; u_long p; u_long fbbase_virt = sst_info->video.vbase; f_dprintk("sstfb_test16\n"); /* white rectangle 20x100+200+0 */ for (i=0 ; i< 100; i++) { p = fbbase_virt + 2048 *i+400; for (j=0; j < 10; j++) { writel(0xffffffff, p); p+=4; } } /* blue rectangle 180x200+0+0 */ for (i=0 ; i< 200; i++) { p = fbbase_virt + 2048 *i; for (j=0; j < 90; j++) { writel(0x001f001f, p); p+=4; } } /* green rectangle 40x40+100+0 */ for (i=0 ; i< 40 ; i++) { p = fbbase_virt + 2048 *i + 200; for (j=0; j <20; j++) { writel(0x07e007e0, p); p+=4; } } /* red rectangle 40x40+100+40 */ for (i=0; i<40; i++) { p = fbbase_virt + 2048 * (i+40) + 200; for (j=0; j <20; j++) { writel( 0xf800f800, p); p+=4; } }}/* print some squares on the fb (24/32bpp) */#ifdef EN_24_32_BPPstatic void sstfb_test32(struct sstfb_info *sst_info){ int i,j; u_long p; u_long fbbase_virt = sst_info->video.vbase; f_dprintk("sstfb_test32\n"); /* rect blanc 20x100+200+0 */ for (i=0 ; i< 100; i++) { p = fbbase_virt + 4096*i + 800; for (j=0 ; j < 20 ; j++) { writel(0x00ffffff, p); p+=4; } } /* rect bleu 180x200+0+0 */ for (i=0 ; i< 200; i++) { p = fbbase_virt + 4096 * i; for (j=0 ; j < 180; j++) { writel(0x000000ff, p); p+=4; } } /* carre vert 40x40+100+0 */ for (i=0 ; i< 40 ; i++) { p = fbbase_virt + 4096 *i + 400; for (j=0; j <40; j++) { writel(0x0000ff00, p); p+=4; } } /*carre rouge 40x40+100+10 */ for (i=0; i<40; i++) { p = fbbase_virt + 4096 * (i+40) + 400; for (j=0; j <40; j++) { writel(0x00ff0000, p); p+=4; } }}#endif /* EN_24_32_BPP */MODULE_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 MiB (1, 2, 4 Mb, default=autodetect)");MODULE_PARM(vgapass, "i");MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough cable (0 or 1) (default=0)");MODULE_PARM(inverse, "i");MODULE_PARM_DESC(inverse, "Inverse colormap (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)");MODULE_PARM(dev,"i");MODULE_PARM_DESC(dev , "Attach to device ID (0..n) (default=1st device)");/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */#if 0void __Dump_regs (struct sstfb_info * sst_info){ struct { u32 reg ; char * reg_name;} pci_regs [] = { { PCI_INIT_ENABLE, "initenable"}, { PCI_VCLK_ENABLE, "enable vclk"}, { PCI_VCLK_DISABLE, "disable vclk"}, }; struct { u32 reg ; 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"}, }; int pci_s = sizeof(pci_regs)/sizeof(*pci_regs); int sst_s = sizeof(sst_regs)/sizeof(*sst_regs); u32 pci_res[pci_s]; u32 sst_res[sst_s]; struct pci_dev * dev = sst_info->dev; 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 ("Dump regs\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]) ; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -