📄 fbdev.c
字号:
wait_for_idle(par); return 0;}/* ------------------------------------------------------------------------- * * * initialization helper functions * * ------------------------------------------------------------------------- *//* kernel interface */static struct fb_ops riva_fb_ops = { .owner = THIS_MODULE, .fb_open = rivafb_open, .fb_release = rivafb_release, .fb_check_var = rivafb_check_var, .fb_set_par = rivafb_set_par, .fb_setcolreg = rivafb_setcolreg, .fb_pan_display = rivafb_pan_display, .fb_blank = rivafb_blank, .fb_fillrect = rivafb_fillrect, .fb_copyarea = rivafb_copyarea, .fb_imageblit = rivafb_imageblit, .fb_cursor = rivafb_cursor, .fb_sync = rivafb_sync,};static int __devinit riva_set_fbinfo(struct fb_info *info){ unsigned int cmap_len; struct riva_par *par = (struct riva_par *) info->par; NVTRACE_ENTER(); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; /* Accel seems to not work properly on NV30 yet...*/ if ((par->riva.Architecture == NV_ARCH_30) || noaccel) { printk(KERN_DEBUG PFX "disabling acceleration\n"); info->flags |= FBINFO_HWACCEL_DISABLED; } info->var = rivafb_default_var; info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; info->pseudo_palette = par->pseudo_palette; cmap_len = riva_get_cmap_len(&info->var); fb_alloc_cmap(&info->cmap, cmap_len, 0); info->pixmap.size = 8 * 1024; info->pixmap.buf_align = 4; info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->var.yres_virtual = -1; NVTRACE_LEAVE(); return (rivafb_check_var(&info->var, info));}#ifdef CONFIG_PPC_OFstatic int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd){ struct riva_par *par = (struct riva_par *) info->par; struct device_node *dp; unsigned char *pedid = NULL; unsigned char *disptype = NULL; static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; int i; NVTRACE_ENTER(); dp = pci_device_to_OF_node(pd); for (; dp != NULL; dp = dp->child) { disptype = (unsigned char *)get_property(dp, "display-type", NULL); if (disptype == NULL) continue; if (strncmp(disptype, "LCD", 3) != 0) continue; for (i = 0; propnames[i] != NULL; ++i) { pedid = (unsigned char *) get_property(dp, propnames[i], NULL); if (pedid != NULL) { par->EDID = pedid; NVTRACE("LCD found.\n"); return 1; } } } NVTRACE_LEAVE(); return 0;}#endif /* CONFIG_PPC_OF */#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)static int __devinit riva_get_EDID_i2c(struct fb_info *info){ struct riva_par *par = (struct riva_par *) info->par; struct fb_var_screeninfo var; int i; NVTRACE_ENTER(); riva_create_i2c_busses(par); for (i = 0; i < par->bus; i++) { riva_probe_i2c_connector(par, i+1, &par->EDID); if (par->EDID && !fb_parse_edid(par->EDID, &var)) { printk(PFX "Found EDID Block from BUS %i\n", i); break; } } NVTRACE_LEAVE(); return (par->EDID) ? 1 : 0;}#endif /* CONFIG_FB_RIVA_I2C */static void __devinit riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct fb_monspecs *specs = &info->monspecs; struct fb_videomode modedb; NVTRACE_ENTER(); /* respect mode options */ if (mode_option) { fb_find_mode(var, info, mode_option, specs->modedb, specs->modedb_len, NULL, 8); } else if (specs->modedb != NULL) { /* get preferred timing */ if (info->monspecs.misc & FB_MISC_1ST_DETAIL) { int i; for (i = 0; i < specs->modedb_len; i++) { if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { modedb = specs->modedb[i]; break; } } } else { /* otherwise, get first mode in database */ modedb = specs->modedb[0]; } var->bits_per_pixel = 8; riva_update_var(var, &modedb); } NVTRACE_LEAVE();}static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev){ NVTRACE_ENTER();#ifdef CONFIG_PPC_OF if (!riva_get_EDID_OF(info, pdev)) printk(PFX "could not retrieve EDID from OF\n");#elif defined(CONFIG_FB_RIVA_I2C) if (!riva_get_EDID_i2c(info)) printk(PFX "could not retrieve EDID from DDC/I2C\n");#endif NVTRACE_LEAVE();}static void __devinit riva_get_edidinfo(struct fb_info *info){ struct fb_var_screeninfo *var = &rivafb_default_var; struct riva_par *par = (struct riva_par *) info->par; fb_edid_to_monspecs(par->EDID, &info->monspecs); fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len, &info->modelist); riva_update_default_var(var, info); /* if user specified flatpanel, we respect that */ if (info->monspecs.input & FB_DISP_DDI) par->FlatPanel = 1;}/* ------------------------------------------------------------------------- * * * PCI bus * * ------------------------------------------------------------------------- */static u32 __devinit riva_get_arch(struct pci_dev *pd){ u32 arch = 0; switch (pd->device & 0x0ff0) { case 0x0100: /* GeForce 256 */ case 0x0110: /* GeForce2 MX */ case 0x0150: /* GeForce2 */ case 0x0170: /* GeForce4 MX */ case 0x0180: /* GeForce4 MX (8x AGP) */ case 0x01A0: /* nForce */ case 0x01F0: /* nForce2 */ arch = NV_ARCH_10; break; case 0x0200: /* GeForce3 */ case 0x0250: /* GeForce4 Ti */ case 0x0280: /* GeForce4 Ti (8x AGP) */ arch = NV_ARCH_20; break; case 0x0300: /* GeForceFX 5800 */ case 0x0310: /* GeForceFX 5600 */ case 0x0320: /* GeForceFX 5200 */ case 0x0330: /* GeForceFX 5900 */ case 0x0340: /* GeForceFX 5700 */ arch = NV_ARCH_30; break; case 0x0020: /* TNT, TNT2 */ arch = NV_ARCH_04; break; case 0x0010: /* Riva128 */ arch = NV_ARCH_03; break; default: /* unknown architecture */ break; } return arch;}static int __devinit rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent){ struct riva_par *default_par; struct fb_info *info; int ret; NVTRACE_ENTER(); assert(pd != NULL); info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev); if (!info) { printk (KERN_ERR PFX "could not allocate memory\n"); ret = -ENOMEM; goto err_ret; } default_par = (struct riva_par *) info->par; default_par->pdev = pd; info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL); if (info->pixmap.addr == NULL) { ret = -ENOMEM; goto err_framebuffer_release; } memset(info->pixmap.addr, 0, 8 * 1024); ret = pci_enable_device(pd); if (ret < 0) { printk(KERN_ERR PFX "cannot enable PCI device\n"); goto err_free_pixmap; } ret = pci_request_regions(pd, "rivafb"); if (ret < 0) { printk(KERN_ERR PFX "cannot request PCI regions\n"); goto err_disable_device; } default_par->riva.Architecture = riva_get_arch(pd); default_par->Chipset = (pd->vendor << 16) | pd->device; printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset); if(default_par->riva.Architecture == 0) { printk(KERN_ERR PFX "unknown NV_ARCH\n"); ret=-ENODEV; goto err_release_region; } if(default_par->riva.Architecture == NV_ARCH_10 || default_par->riva.Architecture == NV_ARCH_20 || default_par->riva.Architecture == NV_ARCH_30) { sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4); } else { sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture); } default_par->FlatPanel = flatpanel; if (flatpanel == 1) printk(KERN_INFO PFX "flatpanel support enabled\n"); default_par->forceCRTC = forceCRTC; rivafb_fix.mmio_len = pci_resource_len(pd, 0); rivafb_fix.smem_len = 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); } rivafb_fix.mmio_start = pci_resource_start(pd, 0); rivafb_fix.smem_start = pci_resource_start(pd, 1); default_par->ctrl_base = ioremap(rivafb_fix.mmio_start, rivafb_fix.mmio_len); if (!default_par->ctrl_base) { printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); ret = -EIO; goto err_release_region; } switch (default_par->riva.Architecture) { case NV_ARCH_03: /* Riva128's PRAMIN is in the "framebuffer" space * Since these cards were never made with more than 8 megabytes * we can safely allocate this separately. */ default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000); if (!default_par->riva.PRAMIN) { printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n"); ret = -EIO; goto err_iounmap_ctrl_base; } break; case NV_ARCH_04: case NV_ARCH_10: case NV_ARCH_20: case NV_ARCH_30: default_par->riva.PCRTC0 = (u32 __iomem *)(default_par->ctrl_base + 0x00600000); default_par->riva.PRAMIN = (u32 __iomem *)(default_par->ctrl_base + 0x00710000); break; } riva_common_setup(default_par); if (default_par->riva.Architecture == NV_ARCH_03) { default_par->riva.PCRTC = default_par->riva.PCRTC0 = default_par->riva.PGRAPH; } rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024; default_par->dclk_max = riva_get_maxdclk(default_par) * 1000; info->screen_base = ioremap(rivafb_fix.smem_start, rivafb_fix.smem_len); if (!info->screen_base) { printk(KERN_ERR PFX "cannot ioremap FB base\n"); ret = -EIO; goto err_iounmap_pramin; }#ifdef CONFIG_MTRR if (!nomtrr) { default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start, rivafb_fix.smem_len, MTRR_TYPE_WRCOMB, 1); if (default_par->mtrr.vram < 0) { printk(KERN_ERR PFX "unable to setup MTRR\n"); } else { default_par->mtrr.vram_valid = 1; /* let there be speed */ printk(KERN_INFO PFX "RIVA MTRR set to ON\n"); } }#endif /* CONFIG_MTRR */ info->fbops = &riva_fb_ops; info->fix = rivafb_fix; riva_get_EDID(info, pd); riva_get_edidinfo(info); ret=riva_set_fbinfo(info); if (ret < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); goto err_iounmap_screen_base; } fb_destroy_modedb(info->monspecs.modedb); info->monspecs.modedb = NULL; ret = register_framebuffer(info); if (ret < 0) { printk(KERN_ERR PFX "error registering riva framebuffer\n"); goto err_iounmap_screen_base; } pci_set_drvdata(pd, info); printk(KERN_INFO PFX "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n", info->fix.id, RIVAFB_VERSION, info->fix.smem_len / (1024 * 1024), info->fix.smem_start);#ifdef CONFIG_PMAC_BACKLIGHT if (default_par->FlatPanel && _machine == _MACH_Pmac) register_backlight_controller(&riva_backlight_controller, default_par, "mnca");#endif NVTRACE_LEAVE(); return 0;err_iounmap_screen_base:#ifdef CONFIG_FB_RIVA_I2C riva_delete_i2c_busses((struct riva_par *) info->par);#endif iounmap(info->screen_base);err_iounmap_pramin: if (default_par->riva.Architecture == NV_ARCH_03) iounmap(default_par->riva.PRAMIN);err_iounmap_ctrl_base: iounmap(default_par->ctrl_base);err_release_region: pci_release_regions(pd);err_disable_device: pci_disable_device(pd);err_free_pixmap: kfree(info->pixmap.addr);err_framebuffer_release: framebuffer_release(info);err_ret: return ret;}static void __exit rivafb_remove(struct pci_dev *pd){ struct fb_info *info = pci_get_drvdata(pd); struct riva_par *par = (struct riva_par *) info->par; NVTRACE_ENTER(); if (!info) return;#ifdef CONFIG_FB_RIVA_I2C riva_delete_i2c_busses(par); kfree(par->EDID);#endif unregister_framebuffer(info);#ifdef CONFIG_MTRR if (par->mtrr.vram_valid) mtrr_del(par->mtrr.vram, info->fix.smem_start, info->fix.smem_len);#endif /* CONFIG_MTRR */ iounmap(par->ctrl_base); iounmap(info->screen_base); if (par->riva.Architecture == NV_ARCH_03) iounmap(par->riva.PRAMIN); pci_release_regions(pd); pci_disable_device(pd); kfree(info->pixmap.addr); framebuffer_release(info); pci_set_drvdata(pd, NULL); NVTRACE_LEAVE();}/* ------------------------------------------------------------------------- * * * initialization * * ------------------------------------------------------------------------- */#ifndef MODULEstatic int __init rivafb_setup(char *options){ char *this_opt; NVTRACE_ENTER(); if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "forceCRTC", 9)) { char *p; p = this_opt + 9; if (!*p || !*(++p)) continue; forceCRTC = *p - '0'; if (forceCRTC < 0 || forceCRTC > 1) forceCRTC = -1; } else if (!strncmp(this_opt, "flatpanel", 9)) { flatpanel = 1;#ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1;#endif } else if (!strncmp(this_opt, "strictmode", 10)) { strictmode = 1; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; } else mode_option = this_opt; } NVTRACE_LEAVE(); return 0;}#endif /* !MODULE */static struct pci_driver rivafb_driver = { .name = "rivafb", .id_table = rivafb_pci_tbl, .probe = rivafb_probe, .remove = __exit_p(rivafb_remove),};/* ------------------------------------------------------------------------- * * * modularization * * ------------------------------------------------------------------------- */static int __devinit rivafb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("rivafb", &option)) return -ENODEV; rivafb_setup(option);#endif return pci_register_driver(&rivafb_driver);}module_init(rivafb_init);#ifdef MODULEstatic void __exit rivafb_exit(void){ pci_unregister_driver(&rivafb_driver);}module_exit(rivafb_exit);#endif /* MODULE */module_param(noaccel, bool, 0);MODULE_PARM_DESC(noaccel, "bool: disable acceleration");module_param(flatpanel, int, 0);MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");module_param(forceCRTC, int, 0);MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");#ifdef CONFIG_MTRRmodule_param(nomtrr, bool, 0);MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");#endifmodule_param(strictmode, bool, 0);MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");MODULE_AUTHOR("Ani Joshi, maintainer");MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -