📄 sstfb.c
字号:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp); break; }}static int __init sst_init(void){ struct pll_timing gfx_timings; int Fout; int dac_ok; u32 fbiinit0, fbiinit1, fbiinit4; struct pci_dev * sst_dev = fb_info.dev; /* or define a macro ?*/ f_dprintk("sst_init\n"); f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 " " fbiinit6\n"); f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n", sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2), sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6)); /* disable video clock */ pci_write_config_dword(sst_dev, PCI_VCLK_DISABLE,0); /* enable writing to init registers ,disable pci fifo*/ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); /* reset video */ sst_set_bits(FBIINIT1, VIDEO_RESET); sst_wait_idle(); /* reset gfx + pci fifo */ sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET); sst_wait_idle(); /* unreset fifo */ /*sst_unset_bits(FBIINIT0, FIFO_RESET); sst_wait_idle();*/ /* unreset FBI */ /*sst_unset_bits(FBIINIT0, FBI_RESET); sst_wait_idle();*/ /* disable dram refresh */ sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH); sst_wait_idle(); /* remap fbinit2/3 to dac */ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR | PCI_REMAP_DAC ); /* detect dac type */ dac_ok = sst_detect_dactype(); if (!dac_ok) { eprintk("Unknown dac type\n"); return 0; } /* set graphic clock */ if (dac_ok) { fb_info.gfx_clock = fb_info.spec->default_gfx_clock; if ((gfxclk >10 ) && (gfxclk < fb_info.spec->max_gfxclk)) { iprintk ("Using supplied graphic freq : %dMHz\n", gfxclk); fb_info.gfx_clock = gfxclk *1000; } else if (gfxclk) { wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk); } sst_calc_pll(fb_info.gfx_clock, &Fout, &gfx_timings); fb_info.dac_sw->set_pll(&gfx_timings, GFX_CLOCK); } /* disable fbiinit remap */ pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR| PCI_EN_FIFO_WR ); /* defaults init registers */ /* FbiInit0: unreset gfx, unreset fifo */ fbiinit0 = FBIINIT0_DEFAULT; fbiinit1 = FBIINIT1_DEFAULT; fbiinit4 = FBIINIT4_DEFAULT; if (vgapass) fbiinit0 &= ~EN_VGA_PASSTHROUGH; else fbiinit0 |= EN_VGA_PASSTHROUGH; if (slowpci) { fbiinit1 |= SLOW_PCI_WRITES; fbiinit4 |= SLOW_PCI_READS; } else { fbiinit1 &= ~SLOW_PCI_WRITES; fbiinit4 &= ~SLOW_PCI_READS; } sst_write(FBIINIT0, fbiinit0); 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 (fb_info.is_voodoo2) { sst_write(FBIINIT6, FBIINIT6_DEFAULT); sst_wait_idle(); } pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR ); pci_write_config_dword(sst_dev, PCI_VCLK_ENABLE, 0); return dac_ok;}#ifdef MODULEstatic void __exit sst_shutdown(void){ struct pll_timing gfx_timings; int Fout; struct pci_dev * sst_dev = fb_info.dev; f_dprintk("sst_shutdown\n"); /* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */ pci_write_config_dword(sst_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(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR | PCI_REMAP_DAC ); /*set 20Mhz gfx clock */ sst_calc_pll(20000, &Fout, &gfx_timings); fb_info.dac_sw->set_pll(&gfx_timings, GFX_CLOCK); /* 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);}#endif /* MODULE *//* * Interface to the world */int __init sstfb_setup(char *options){ char *this_opt; f_dprintk("sstfb_setup\n"); 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, "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 __init sstfb_init(void){ struct pci_dev * pdev; struct fb_var_screeninfo var;#define sst_dev (fb_info.dev) f_dprintk("sstfb_init\n"); dprintk("Compile date: "__DATE__" "__TIME__"\n"); memset (&fb_info, 0, sizeof(fb_info)); pci_for_each_dev(pdev) { if (pdev->vendor != PCI_VENDOR_ID_3DFX) continue; if (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO) { fb_info.is_voodoo2=0; fb_info.spec=&voodoo1_spec; } else if (pdev->device == PCI_DEVICE_ID_3DFX_VOODOO2) { fb_info.is_voodoo2=1; fb_info.spec=&voodoo2_spec; } else continue; if (dev > 0) { dev--; continue; } f_ddprintk("found device : %s\n", fb_info.spec->name); fb_info.dev = pdev; fb_info.mmio.base = sst_dev->resource[0].start; pci_read_config_byte(sst_dev, PCI_REVISION_ID, &fb_info.revision); fb_info.mmio.vbase = (u32) ioremap_nocache(fb_info.mmio.base, 0x400000); if (!fb_info.mmio.vbase) { eprintk("cannot remap register area %#lx\n", fb_info.mmio.base); return -ENXIO; } fb_info.video.base = fb_info.mmio.base+0x400000; fb_info.video.vbase = (u32) ioremap_nocache(fb_info.video.base, 0x400000); if (!fb_info.video.vbase) { eprintk("cannot remap framebuffer %#lx\n", fb_info.video.base); iounmap((void*) fb_info.mmio.vbase); return -ENXIO; } if(!sst_init()) { eprintk("Init failed\n"); iounmap((void*)fb_info.mmio.vbase); iounmap((void*)fb_info.video.vbase); return -ENXIO; } sst_get_memsize(&fb_info.video.len); fb_info.configured = 1; strncpy(fb_info.info.modename, fb_info.spec->name, 16); iprintk("%s with %s dac\n", fb_info.info.modename, fb_info.dac_sw->name); iprintk("framebuffer at %#lx, mapped to %#lx," " size %ldMb\n", fb_info.video.base, fb_info.video.vbase, fb_info.video.len >> 20); f_ddprintk("revision: %d\n", fb_info.revision); f_ddprintk("regbase_virt: %#lx\n", fb_info.mmio.vbase); f_ddprintk("membase_phys: %#lx\n", fb_info.video.base); f_ddprintk("fbbase_virt: %#lx\n", fb_info.video.vbase); fb_info.info.node = -1 ; fb_info.info.flags = FBINFO_FLAG_DEFAULT; fb_info.info.fbops = &sstfb_ops; fb_info.info.disp = &disp; fb_info.info.changevar = NULL; fb_info.info.switch_con = &sstfbcon_switch; fb_info.info.updatevar = &sstfbcon_updatevar; fb_info.info.blank = &sstfbcon_blank; if ( !mode_option && !fb_find_mode(&var, &fb_info.info, mode_option, NULL, 0, NULL, 16)) { var = sstfb_default; } if (sstfb_set_var(&var, -1, &fb_info.info)) { eprintk("can't set supplied video mode. Using default\n"); var = sstfb_default; if (sstfb_set_var(&var, -1, &fb_info.info)) { eprintk("can't set default video mode.\n"); return -ENXIO; } } /*clear fb */ memset_io(fb_info.video.vbase, 0, fb_info.video.len); /* print some squares ... */ sstfb_test16(&fb_info); /* FIXME this is only for 16bpp */ /* register fb */ if (register_framebuffer(&fb_info.info) < 0) { eprintk("can't register framebuffer.\n"); return -ENXIO; } printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.info.node),fb_info.info.modename); num_sst++; if (dev <= 0) /* we use the first card only for now (==0) */ return 0; } return -ENXIO; /* no voodoo detected */#undef sst_dev}/* * 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", currcon); v_dprintk("currcon: %d\n", currcon); if (currcon >= 0) { if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, sstfb_getcolreg, 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"); /* rect blanc 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; } } /* rect bleu 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; } } /* carre vert 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; } } /*carre rouge 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; u32 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 */#ifdef MODULEint init_module(void){ f_dprintk("init_module\n"); sstfb_init(); if (num_sst == 0 ) return -ENXIO; return 0;}void cleanup_module(void){ f_dprintk("cleanup_module\n"); f_ddprintk("conf %d\n",fb_info.configured); if (fb_info.configured) { sst_shutdown(); iounmap((void*)fb_info.mmio.vbase); iounmap((void*)fb_info.video.vbase); unregister_framebuffer(&fb_info.info); }}MODULE_AUTHOR("(c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr>");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)");#endif /* MODULE *//* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */#if 0void Dump_regs ( void){ 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"}, }; u32 pci_res[sizeof(pci_regs)/sizeof(pci_regs[0])]; u32 sst_res[sizeof(sst_regs)/sizeof(sst_regs[0])]; struct pci_dev * dev = fb_info.dev; int i; for (i=0; i<(sizeof(pci_regs)/sizeof(pci_regs[0])) ; i++ ) { pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ; } for (i=0; i<(sizeof(sst_regs)/sizeof(sst_regs[0])) ; i++ ) { sst_res[i]=sst_read(sst_regs[i].reg); } dprintk ("Dump regs\n"); for (i=0; i<(sizeof(pci_regs)/sizeof(pci_regs[0])) ; i++ ) { dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ; } for (i=0; i<(sizeof(sst_regs)/sizeof(sst_regs[0])) ; 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 + -