fbdev.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,214 行 · 第 1/4 页
C
2,214 行
u16 fg, bg; int i; par->riva.ShowHideCursor(&par->riva, 0); if (cursor->set & FB_CUR_SETPOS) { u32 xx, yy, temp; info->cursor.image.dx = cursor->image.dx; info->cursor.image.dy = cursor->image.dy; yy = cursor->image.dy - info->var.yoffset; xx = cursor->image.dx - info->var.xoffset; temp = xx & 0xFFFF; temp |= yy << 16; par->riva.PRAMDAC[0x0000300/4] = temp; } if (cursor->set & FB_CUR_SETSIZE) { info->cursor.image.height = cursor->image.height; info->cursor.image.width = cursor->image.width; memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2); } if (cursor->set & FB_CUR_SETCMAP) { info->cursor.image.bg_color = cursor->image.bg_color; info->cursor.image.fg_color = cursor->image.fg_color; } if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) { u32 bg_idx = info->cursor.image.bg_color; u32 fg_idx = info->cursor.image.fg_color; u32 s_pitch = (info->cursor.image.width+7) >> 3; u32 d_pitch = MAX_CURS/8; u8 *dat = (u8 *) cursor->image.data; u8 *msk = (u8 *) info->cursor.mask; u8 src[64]; info->cursor.image.data = cursor->image.data; switch (info->cursor.rop) { case ROP_XOR: for (i = 0; i < s_pitch * info->cursor.image.height; i++) src[i] = dat[i] ^ msk[i]; break; case ROP_COPY: default: for (i = 0; i < s_pitch * info->cursor.image.height; i++) src[i] = dat[i] & msk[i]; break; } fb_sysmove_buf_aligned(info, &info->sprite, data, d_pitch, src, s_pitch, info->cursor.image.height); bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) | ((info->cmap.green[bg_idx] & 0xf8) << 2) | ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15; fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | ((info->cmap.green[fg_idx] & 0xf8) << 2) | ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15; par->riva.LockUnlock(&par->riva, 0); rivafb_load_cursor_image(par, data, bg, fg, info->cursor.image.width, info->cursor.image.height); } if (info->cursor.enable) par->riva.ShowHideCursor(&par->riva, 1); return 0;}static int rivafb_sync(struct fb_info *info){ struct riva_par *par = (struct riva_par *)info->par; 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; NVTRACE_ENTER(); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_MISC_MODESWITCHLATE; info->var = rivafb_default_var; info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; info->pseudo_palette = pseudo_palette; cmap_len = riva_get_cmap_len(&info->var); fb_alloc_cmap(&info->cmap, cmap_len, 0); info->pixmap.size = 64 * 1024; info->pixmap.buf_align = 4; info->pixmap.scan_align = 4; 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 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; return 1; } } } NVTRACE_LEAVE(); return 0;}#endif /* CONFIG_PPC_OF */static void 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); } var->accel_flags |= FB_ACCELF_TEXT; NVTRACE_LEAVE();}static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev){ struct riva_par *par; int i; NVTRACE_ENTER();#ifdef CONFIG_PPC_OF if (!riva_get_EDID_OF(info, pdev)) printk("rivafb: could not retrieve EDID from OF\n");#else /* XXX use other methods later */#ifdef CONFIG_FB_RIVA_I2C par = (struct riva_par *) info->par; riva_create_i2c_busses(par); for (i = par->bus; i >= 1; i--) { riva_probe_i2c_connector(par, i, &par->EDID); if (par->EDID) { printk("rivafb: Found EDID Block from BUS %i\n", i); break; } } riva_delete_i2c_busses(par);#endif#endif NVTRACE_LEAVE();}static void 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); 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 int __devinit rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent){ struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; struct riva_par *default_par; struct fb_info *info; NVTRACE_ENTER(); assert(pd != NULL); assert(rci != NULL); info = kmalloc(sizeof(struct fb_info), GFP_KERNEL); if (!info) goto err_out; default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL); if (!default_par) goto err_out_kfree; memset(info, 0, sizeof(struct fb_info)); memset(default_par, 0, sizeof(struct riva_par)); default_par->pdev = pd; info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL); if (info->pixmap.addr == NULL) goto err_out_kfree1; memset(info->pixmap.addr, 0, 64 * 1024); if (pci_enable_device(pd)) { printk(KERN_ERR PFX "cannot enable PCI device\n"); goto err_out_enable; } if (pci_request_regions(pd, "rivafb")) { printk(KERN_ERR PFX "cannot request PCI regions\n"); goto err_out_request; } strcat(rivafb_fix.id, rci->name); default_par->riva.Architecture = rci->arch_rev; default_par->Chipset = (pd->vendor << 16) | pd->device; printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset); 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"); goto err_out_free_base0; } info->par = default_par; 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"); goto err_out_free_nv3_pramin; } rivafb_fix.accel = FB_ACCEL_NV3; default_par->bus = 1; break; case NV_ARCH_04: case NV_ARCH_10: case NV_ARCH_20: default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000); default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000); rivafb_fix.accel = FB_ACCEL_NV4; default_par->bus = 2; 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"); goto err_out_free_base1; }#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); if (riva_set_fbinfo(info) < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); goto err_out_iounmap_fb; } if (register_framebuffer(info) < 0) { printk(KERN_ERR PFX "error registering riva framebuffer\n"); goto err_out_iounmap_fb; } pci_set_drvdata(pd, info); printk(KERN_INFO PFX "PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n", default_par->riva.Architecture, RIVAFB_VERSION, info->fix.id, 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_out_iounmap_fb: iounmap(info->screen_base);err_out_free_base1: if (default_par->riva.Architecture == NV_ARCH_03) iounmap((caddr_t)default_par->riva.PRAMIN);err_out_free_nv3_pramin: iounmap(default_par->ctrl_base);err_out_free_base0: pci_release_regions(pd);err_out_request: pci_disable_device(pd);err_out_enable: kfree(info->pixmap.addr);err_out_kfree1: kfree(default_par);err_out_kfree: kfree(info);err_out: return -ENODEV;}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; 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((caddr_t)par->riva.PRAMIN); pci_release_regions(pd); pci_disable_device(pd); fb_destroy_modedb(info->monspecs.modedb); kfree(info->pixmap.addr); kfree(par); kfree(info); pci_set_drvdata(pd, NULL); NVTRACE_LEAVE();}/* ------------------------------------------------------------------------- * * * initialization * * ------------------------------------------------------------------------- */#ifndef MODULEint __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 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 * * ------------------------------------------------------------------------- */int __init rivafb_init(void){ if (pci_register_driver(&rivafb_driver) > 0) return 0; pci_unregister_driver(&rivafb_driver); return -ENODEV;}#ifdef MODULEstatic void __exit rivafb_exit(void){ pci_unregister_driver(&rivafb_driver);}module_init(rivafb_init);module_exit(rivafb_exit);MODULE_PARM(flatpanel, "i");MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");MODULE_PARM(forceCRTC, "i");MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");#ifdef CONFIG_MTRRMODULE_PARM(nomtrr, "i");MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");MODULE_PARM(strictmode, "i");MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");#endif#endif /* MODULE */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 + =
减小字号Ctrl + -
显示快捷键?