📄 lxfb_core.c
字号:
if (ret) return ret; ret = pci_request_region(dev, 0, "lxfb-framebuffer"); if (ret) return ret; ret = pci_request_region(dev, 1, "lxfb-gp"); if (ret) return ret; ret = pci_request_region(dev, 2, "lxfb-vg"); if (ret) return ret; ret = pci_request_region(dev, 3, "lxfb-vp"); if (ret) return ret; info->fix.smem_start = pci_resource_start(dev, 0); info->fix.smem_len = vram ? vram : lx_framebuffer_size(); info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); ret = -ENOMEM; if (info->screen_base == NULL) return ret; par->gp_regs = pci_ioremap_bar(dev, 1); if (par->gp_regs == NULL) return ret; par->dc_regs = pci_ioremap_bar(dev, 2); if (par->dc_regs == NULL) return ret; par->vp_regs = pci_ioremap_bar(dev, 3); if (par->vp_regs == NULL) return ret; write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); write_dc(par, DC_GLIU0_MEM_OFFSET, info->fix.smem_start & 0xFF000000); write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK); dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n", info->fix.smem_len / 1024, info->fix.smem_start); return 0;}static struct fb_ops lxfb_ops = { .owner = THIS_MODULE, .fb_check_var = lxfb_check_var, .fb_set_par = lxfb_set_par, .fb_setcolreg = lxfb_setcolreg, .fb_blank = lxfb_blank, /* No HW acceleration for now. */ .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit,};static struct fb_info * __init lxfb_init_fbinfo(struct device *dev){ struct lxfb_par *par; struct fb_info *info; /* Alloc enough space for the pseudo palette. */ info = framebuffer_alloc(sizeof(struct lxfb_par) + sizeof(u32) * 16, dev); if (!info) return NULL; par = info->par; strcpy(info->fix.id, "Geode LX"); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.type_aux = 0; info->fix.xpanstep = 0; info->fix.ypanstep = 0; info->fix.ywrapstep = 0; info->fix.accel = FB_ACCEL_NONE; info->var.nonstd = 0; info->var.activate = FB_ACTIVATE_NOW; info->var.height = -1; info->var.width = -1; info->var.accel_flags = 0; info->var.vmode = FB_VMODE_NONINTERLACED; info->fbops = &lxfb_ops; info->flags = FBINFO_DEFAULT; info->node = -1; info->pseudo_palette = (void *)par + sizeof(struct lxfb_par); if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { framebuffer_release(info); return NULL; } info->var.grayscale = 0; return info;}#ifdef CONFIG_PMstatic int lxfb_suspend(struct pci_dev *pdev, pm_message_t state){ struct fb_info *info = pci_get_drvdata(pdev); if (state.event == PM_EVENT_SUSPEND) { acquire_console_sem(); lx_powerdown(info); fb_set_suspend(info, 1); release_console_sem(); } /* there's no point in setting PCI states; we emulate PCI, so * we don't end up getting power savings anyways */ return 0;}static int lxfb_resume(struct pci_dev *pdev){ struct fb_info *info = pci_get_drvdata(pdev); int ret; acquire_console_sem(); ret = lx_powerup(info); if (ret) { printk(KERN_ERR "lxfb: power up failed!\n"); return ret; } fb_set_suspend(info, 0); release_console_sem(); return 0;}#else#define lxfb_suspend NULL#define lxfb_resume NULL#endifstatic int __init lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id){ struct lxfb_par *par; struct fb_info *info; int ret; struct fb_videomode *modedb_ptr; unsigned int modedb_size; info = lxfb_init_fbinfo(&pdev->dev); if (info == NULL) return -ENOMEM; par = info->par; ret = lxfb_map_video_memory(info, pdev); if (ret < 0) { dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n"); goto err; } /* Set up the desired outputs */ par->output = 0; par->output |= (nopanel) ? 0 : OUTPUT_PANEL; par->output |= (nocrt) ? 0 : OUTPUT_CRT; /* Set up the mode database */ get_modedb(&modedb_ptr, &modedb_size); ret = fb_find_mode(&info->var, info, mode_option, modedb_ptr, modedb_size, NULL, 16); if (ret == 0 || ret == 4) { dev_err(&pdev->dev, "could not find valid video mode\n"); ret = -EINVAL; goto err; } /* Clear the screen of garbage, unless noclear was specified, * in which case we assume the user knows what he is doing */ if (!noclear) memset_io(info->screen_base, 0, info->fix.smem_len); /* Set the mode */ lxfb_check_var(&info->var, info); lxfb_set_par(info); pm_set_vt_switch(vt_switch); if (register_framebuffer(info) < 0) { ret = -EINVAL; goto err; } pci_set_drvdata(pdev, info); printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); return 0;err: if (info->screen_base) { iounmap(info->screen_base); pci_release_region(pdev, 0); } if (par->gp_regs) { iounmap(par->gp_regs); pci_release_region(pdev, 1); } if (par->dc_regs) { iounmap(par->dc_regs); pci_release_region(pdev, 2); } if (par->vp_regs) { iounmap(par->vp_regs); pci_release_region(pdev, 3); } if (info) { fb_dealloc_cmap(&info->cmap); framebuffer_release(info); } return ret;}static void lxfb_remove(struct pci_dev *pdev){ struct fb_info *info = pci_get_drvdata(pdev); struct lxfb_par *par = info->par; unregister_framebuffer(info); iounmap(info->screen_base); pci_release_region(pdev, 0); iounmap(par->gp_regs); pci_release_region(pdev, 1); iounmap(par->dc_regs); pci_release_region(pdev, 2); iounmap(par->vp_regs); pci_release_region(pdev, 3); fb_dealloc_cmap(&info->cmap); pci_set_drvdata(pdev, NULL); framebuffer_release(info);}static struct pci_device_id lxfb_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO) }, { 0, }};MODULE_DEVICE_TABLE(pci, lxfb_id_table);static struct pci_driver lxfb_driver = { .name = "lxfb", .id_table = lxfb_id_table, .probe = lxfb_probe, .remove = lxfb_remove, .suspend = lxfb_suspend, .resume = lxfb_resume,};#ifndef MODULEstatic int __init lxfb_setup(char *options){ char *opt; if (!options || !*options) return 0; while ((opt = strsep(&options, ",")) != NULL) { if (!*opt) continue; if (!strcmp(opt, "noclear")) noclear = 1; else if (!strcmp(opt, "nopanel")) nopanel = 1; else if (!strcmp(opt, "nocrt")) nocrt = 1; else mode_option = opt; } return 0;}#endifstatic int __init lxfb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("lxfb", &option)) return -ENODEV; lxfb_setup(option);#endif return pci_register_driver(&lxfb_driver);}static void __exit lxfb_cleanup(void){ pci_unregister_driver(&lxfb_driver);}module_init(lxfb_init);module_exit(lxfb_cleanup);module_param(mode_option, charp, 0);MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");module_param(vram, int, 0);MODULE_PARM_DESC(vram, "video memory size");module_param(vt_switch, int, 0);MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -