📄 fbdev.c
字号:
static void rivafb_blank(int blank, struct fb_info *info){ unsigned char tmp, vesa; struct rivafb_info *rinfo = (struct rivafb_info *)info; DPRINTK("ENTER\n"); assert(rinfo != NULL); tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */ vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */ if (blank) { tmp |= 0x20; switch (blank - 1) { case VESA_NO_BLANKING: break; case VESA_VSYNC_SUSPEND: vesa |= 0x80; break; case VESA_HSYNC_SUSPEND: vesa |= 0x40; break; case VESA_POWERDOWN: vesa |= 0xc0; break; } } SEQout(rinfo, 0x01, tmp); CRTCout(rinfo, 0x1a, vesa); DPRINTK("EXIT\n");}/* ------------------------------------------------------------------------- * * * initialization helper functions * * ------------------------------------------------------------------------- *//* kernel interface */static struct fb_ops riva_fb_ops = { owner: THIS_MODULE, fb_get_fix: rivafb_get_fix, fb_get_var: rivafb_get_var, fb_set_var: rivafb_set_var, fb_get_cmap: rivafb_get_cmap, fb_set_cmap: rivafb_set_cmap, fb_pan_display: rivafb_pan_display, fb_ioctl: rivafb_ioctl, fb_rasterimg: rivafb_rasterimg,};static int __devinit riva_init_disp_var(struct rivafb_info *rinfo){#ifndef MODULE if (mode_option) fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option, NULL, 0, NULL, 8);#endif if (rinfo->use_default_var) /* We will use the modified default var */ rinfo->disp.var = rivafb_default_var; return 0;}static int __devinit riva_init_disp(struct rivafb_info *rinfo){ struct fb_info *info; struct display *disp; DPRINTK("ENTER\n"); assert(rinfo != NULL); info = &rinfo->info; disp = &rinfo->disp; disp->var = rivafb_default_var; if (noaccel) disp->var.accel_flags &= ~FB_ACCELF_TEXT; else disp->var.accel_flags |= FB_ACCELF_TEXT; info->disp = disp; /* FIXME: assure that disp->cmap is completely filled out */ rinfo->currcon_display = disp; if ((riva_init_disp_var(rinfo)) < 0) { DPRINTK("EXIT, returning -1\n"); return -1; } riva_set_dispsw(rinfo, disp); DPRINTK("EXIT, returning 0\n"); return 0;}static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo){ struct fb_info *info; assert(rinfo != NULL); info = &rinfo->info; strcpy(info->modename, rinfo->drvr_name); info->node = -1; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &riva_fb_ops; /* FIXME: set monspecs to what??? */ info->display_fg = NULL; strncpy(info->fontname, fontname, sizeof(info->fontname)); info->fontname[sizeof(info->fontname) - 1] = 0; info->changevar = NULL; info->switch_con = rivafb_switch; info->updatevar = rivafb_updatevar; info->blank = rivafb_blank; if (riva_init_disp(rinfo) < 0) /* must be done last */ return -1; return 0;}#ifdef CONFIG_ALL_PPCstatic int riva_get_EDID_OF(struct rivafb_info *rinfo){ struct device_node *dp; unsigned char *pedid = NULL; dp = pci_device_to_OF_node(rinfo->pd); pedid = (unsigned char *)get_property(dp, "EDID,B", 0); if (pedid) { rinfo->EDID = pedid; return 1; } else return 0;}#endif /* CONFIG_ALL_PPC */static int riva_dfp_parse_EDID(struct rivafb_info *rinfo){ unsigned char *block = rinfo->EDID; if (!block) return 0; /* jump to detailed timing block section */ block += 54; rinfo->clock = (block[0] + (block[1] << 8)); rinfo->panel_xres = (block[2] + ((block[4] & 0xf0) << 4)); rinfo->hblank = (block[3] + ((block[4] & 0x0f) << 8)); rinfo->panel_yres = (block[5] + ((block[7] & 0xf0) << 4)); rinfo->vblank = (block[6] + ((block[7] & 0x0f) << 8)); rinfo->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2)); rinfo->hSync_width = (block[9] + ((block[11] & 0x30) << 4)); rinfo->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2)); rinfo->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4)); rinfo->interlaced = ((block[17] & 0x80) >> 7); rinfo->synct = ((block[17] & 0x18) >> 3); rinfo->misc = ((block[17] & 0x06) >> 1); rinfo->hAct_high = rinfo->vAct_high = 0; if (rinfo->synct == 3) { if (rinfo->misc & 2) rinfo->hAct_high = 1; if (rinfo->misc & 1) rinfo->vAct_high = 1; } printk("rivafb: detected DFP panel size from EDID: %dx%d\n", rinfo->panel_xres, rinfo->panel_yres); rinfo->got_dfpinfo = 1; return 1;}static void riva_update_default_var(struct rivafb_info *rinfo){ struct fb_var_screeninfo *var = &rivafb_default_var; var->xres = rinfo->panel_xres; var->yres = rinfo->panel_yres; var->xres_virtual = rinfo->panel_xres; var->yres_virtual = rinfo->panel_yres; var->xoffset = var->yoffset = 0; var->bits_per_pixel = 8; var->pixclock = 100000000 / rinfo->clock; var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width); var->right_margin = rinfo->hOver_plus; var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - rinfo->vSync_width); var->lower_margin = rinfo->vOver_plus; var->hsync_len = rinfo->hSync_width; var->vsync_len = rinfo->vSync_width; var->sync = 0; if (rinfo->synct == 3) { if (rinfo->hAct_high) var->sync |= FB_SYNC_HOR_HIGH_ACT; if (rinfo->vAct_high) var->sync |= FB_SYNC_VERT_HIGH_ACT; } var->vmode = 0; if (rinfo->interlaced) var->vmode |= FB_VMODE_INTERLACED; if (!noaccel) var->accel_flags |= FB_ACCELF_TEXT; rinfo->use_default_var = 1;}static void riva_get_EDID(struct rivafb_info *rinfo){#ifdef CONFIG_ALL_PPC if (!riva_get_EDID_OF(rinfo)) printk("rivafb: could not retrieve EDID from OF\n");#else /* XXX use other methods later */#endif}static void riva_get_dfpinfo(struct rivafb_info *rinfo){ if (riva_dfp_parse_EDID(rinfo)) riva_update_default_var(rinfo); rinfo->riva.flatPanel = rinfo->got_dfpinfo;}/* ------------------------------------------------------------------------- * * * PCI bus * * ------------------------------------------------------------------------- */static int __devinit rivafb_init_one(struct pci_dev *pd, const struct pci_device_id *ent){ struct rivafb_info *rinfo; struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; assert(pd != NULL); assert(rci != NULL); rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL); if (!rinfo) goto err_out; memset(rinfo, 0, sizeof(struct rivafb_info)); rinfo->drvr_name = rci->name; rinfo->riva.Architecture = rci->arch_rev; rinfo->pd = pd; rinfo->base0_region_size = pci_resource_len(pd, 0); rinfo->base1_region_size = pci_resource_len(pd, 1); { /* enable IO and mem if not already done */ unsigned short cmd; pci_read_config_word(pd, PCI_COMMAND, &cmd); cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); pci_write_config_word(pd, PCI_COMMAND, cmd); } rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0); rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1); rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys, rinfo->base0_region_size); if (!rinfo->ctrl_base) { printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); goto err_out_free_base1; } riva_get_EDID(rinfo); riva_get_dfpinfo(rinfo); rinfo->riva.EnableIRQ = 0; rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000); rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000); rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000); rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000); rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000); rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000); rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000); rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000); rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000); rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000); rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000); rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0; if (rinfo->riva.Architecture == NV_ARCH_03) { /* * We have to map the full BASE_1 aperture for Riva128's * because they use the PRAMIN set in "framebuffer" space */ if (!request_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size, "rivafb")) { printk(KERN_ERR PFX "cannot reserve FB region\n"); goto err_out_free_base0; } rinfo->fb_base = ioremap(rinfo->fb_base_phys, rinfo->base1_region_size); if (!rinfo->fb_base) { printk(KERN_ERR PFX "cannot ioremap FB base\n"); goto err_out_iounmap_ctrl; } } switch (rinfo->riva.Architecture) { case NV_ARCH_03: rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000); break; case NV_ARCH_04: case NV_ARCH_10: case NV_ARCH_20: rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000); rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000); break; }#if defined(__powerpc__) /* * XXX Mac cards use the second DAC for the panel */ if (rinfo->riva.flatPanel) { printk("rivafb: using second CRTC\n"); rinfo->riva.PCIO = rinfo->riva.PCIO + 0x2000; rinfo->riva.PCRTC = rinfo->riva.PCRTC + 0x800; rinfo->riva.PRAMDAC = rinfo->riva.PRAMDAC + 0x800; rinfo->riva.PDIO = rinfo->riva.PDIO + 0x2000; }#endif RivaGetConfig(&rinfo->riva); rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024; rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000; if (rinfo->riva.Architecture != NV_ARCH_03) { /* * Now the _normal_ chipsets can just map the amount of * real physical ram instead of the whole aperture */ if (!request_mem_region(rinfo->fb_base_phys, rinfo->ram_amount, "rivafb")) { printk(KERN_ERR PFX "cannot reserve FB region\n"); goto err_out_free_base0; } rinfo->fb_base = ioremap(rinfo->fb_base_phys, rinfo->ram_amount); if (!rinfo->fb_base) { printk(KERN_ERR PFX "cannot ioremap FB base\n"); goto err_out_iounmap_ctrl; } }#ifdef CONFIG_MTRR if (!nomtrr) { rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys, rinfo->ram_amount, MTRR_TYPE_WRCOMB, 1); if (rinfo->mtrr.vram < 0) { printk(KERN_ERR PFX "unable to setup MTRR\n"); } else { rinfo->mtrr.vram_valid = 1; /* let there be speed */ printk(KERN_INFO PFX "RIVA MTRR set to ON\n"); } }#endif /* CONFIG_MTRR */ /* unlock io */ CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */ rinfo->riva.LockUnlock(&rinfo->riva, 0); riva_save_state(rinfo, &rinfo->initial_state); if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo); if (riva_set_fbinfo(rinfo) < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); goto err_out_cursor; } if (register_framebuffer((struct fb_info *)rinfo) < 0) { printk(KERN_ERR PFX "error registering riva framebuffer\n"); goto err_out_load_state; } riva_boards = riva_board_list_add(riva_boards, rinfo); pci_set_drvdata(pd, rinfo); printk(KERN_INFO PFX "PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n", rinfo->riva.Architecture, RIVAFB_VERSION, rinfo->drvr_name, rinfo->ram_amount / (1024 * 1024), rinfo->fb_base_phys); return 0;err_out_load_state: riva_load_state(rinfo, &rinfo->initial_state);err_out_cursor: rivafb_exit_cursor(rinfo);/* err_out_iounmap_fb: */ iounmap(rinfo->fb_base);err_out_iounmap_ctrl: iounmap(rinfo->ctrl_base);err_out_free_base1: release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);err_out_free_base0: release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size); kfree(rinfo);err_out: return -ENODEV;}static void __devexit rivafb_remove_one(struct pci_dev *pd){ struct rivafb_info *board = pci_get_drvdata(pd); if (!board) return; riva_boards = riva_board_list_del(riva_boards, board); riva_load_state(board, &board->initial_state); unregister_framebuffer((struct fb_info *)board); rivafb_exit_cursor(board);#ifdef CONFIG_MTRR if (board->mtrr.vram_valid) mtrr_del(board->mtrr.vram, board->fb_base_phys, board->ram_amount);#endif /* CONFIG_MTRR */ iounmap(board->ctrl_base); iounmap(board->fb_base); release_mem_region(board->ctrl_base_phys, board->base0_region_size); release_mem_region(board->fb_base_phys, board->ram_amount); kfree(board); pci_set_drvdata(pd, NULL);}/* ------------------------------------------------------------------------- * * * initialization * * ------------------------------------------------------------------------- */#ifndef MODULEint __init rivafb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; if (!strncmp(this_opt, "font:", 5)) { char *p; int i; p = this_opt + 5; for (i = 0; i < sizeof(fontname) - 1; i++) if (!*p || *p == ' ' || *p == ',') break; memcpy(fontname, this_opt + 5, i); fontname[i] = 0; } else if (!strncmp(this_opt, "noblink", 7)) { noblink = 1; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; } else if (!strncmp(this_opt, "nomove", 6)) { nomove = 1;#ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1;#endif } else if (!strncmp(this_opt, "nohwcursor", 10)) { nohwcursor = 1; } else mode_option = this_opt; } return 0;}#endif /* !MODULE */static struct pci_driver rivafb_driver = { name: "rivafb", id_table: rivafb_pci_tbl, probe: rivafb_init_one, remove: __devexit_p(rivafb_remove_one),};/* ------------------------------------------------------------------------- * * * modularization * * ------------------------------------------------------------------------- */int __init rivafb_init(void){ int err;#ifdef MODULE if (font) strncpy(fontname, font, sizeof(fontname)-1);#endif err = pci_module_init(&rivafb_driver); if (err) return err; return 0;}#ifdef MODULEstatic void __exit rivafb_exit(void){ pci_unregister_driver(&rivafb_driver);}module_init(rivafb_init);module_exit(rivafb_exit);MODULE_PARM(font, "s");MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)");MODULE_PARM(noaccel, "i");MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");MODULE_PARM(nomove, "i");MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)");MODULE_PARM(nohwcursor, "i");MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)");MODULE_PARM(noblink, "i");MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)");#ifdef CONFIG_MTRRMODULE_PARM(nomtrr, "i");MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");#endif#endif /* MODULE */MODULE_AUTHOR("Ani Joshi, maintainer");MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -