📄 mb862xxfb.c
字号:
return -ENODEV; } if (!par->pre_init) { outreg(host, GC_CCF, ccf); udelay(200); outreg(host, GC_MMR, mmr); udelay(10); } /* interrupt status */ outreg(host, GC_IST, 0); outreg(host, GC_IMASK, GC_INT_EN); return 0;}static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, const struct of_device_id *id){ struct device_node *np = ofdev->node; struct device *dev = &ofdev->dev; struct mb862xxfb_par *par; struct fb_info *info; struct resource res; resource_size_t res_size; unsigned long ret = -ENODEV; if (of_address_to_resource(np, 0, &res)) { dev_err(dev, "Invalid address\n"); return -ENXIO; } info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); if (info == NULL) { dev_err(dev, "cannot allocate framebuffer\n"); return -ENOMEM; } par = info->par; par->info = info; par->dev = dev; par->irq = irq_of_parse_and_map(np, 0); if (par->irq == NO_IRQ) { dev_err(dev, "failed to map irq\n"); ret = -ENODEV; goto fbrel; } res_size = 1 + res.end - res.start; par->res = request_mem_region(res.start, res_size, DRV_NAME); if (par->res == NULL) { dev_err(dev, "Cannot claim framebuffer/mmio\n"); ret = -ENXIO; goto irqdisp; }#if defined(CONFIG_LWMON5) par->gc_mode = &lwmon5_gc_mode;#endif#if defined(CONFIG_SOCRATES) par->gc_mode = &socrates_gc_mode;#endif par->fb_base_phys = res.start; par->mmio_base_phys = res.start + MB862XX_MMIO_BASE; par->mmio_len = MB862XX_MMIO_SIZE; if (par->gc_mode) par->mapped_vram = par->gc_mode->max_vram; else par->mapped_vram = MB862XX_MEM_SIZE; par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); if (par->fb_base == NULL) { dev_err(dev, "Cannot map framebuffer\n"); goto rel_reg; } par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); if (par->mmio_base == NULL) { dev_err(dev, "Cannot map registers\n"); goto fb_unmap; } dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", (u64)par->fb_base_phys, (ulong)par->mapped_vram); dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n", (u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq); if (mb862xx_gdc_init(par)) goto io_unmap; if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, DRV_NAME, (void *)par)) { dev_err(dev, "Cannot request irq\n"); goto io_unmap; } mb862xxfb_init_fbinfo(info); if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { dev_err(dev, "Could not allocate cmap for fb_info.\n"); goto free_irq; } if ((info->fbops->fb_set_par)(info)) dev_err(dev, "set_var() failed on initial setup?\n"); if (register_framebuffer(info)) { dev_err(dev, "failed to register framebuffer\n"); goto rel_cmap; } dev_set_drvdata(dev, info); if (device_create_file(dev, &dev_attr_dispregs)) dev_err(dev, "Can't create sysfs regdump file\n"); return 0;rel_cmap: fb_dealloc_cmap(&info->cmap);free_irq: outreg(host, GC_IMASK, 0); free_irq(par->irq, (void *)par);io_unmap: iounmap(par->mmio_base);fb_unmap: iounmap(par->fb_base);rel_reg: release_mem_region(res.start, res_size);irqdisp: irq_dispose_mapping(par->irq);fbrel: dev_set_drvdata(dev, NULL); framebuffer_release(info); return ret;}static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev){ struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); struct mb862xxfb_par *par = fbi->par; resource_size_t res_size = 1 + par->res->end - par->res->start; unsigned long reg; dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); /* display off */ reg = inreg(disp, GC_DCM1); reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); outreg(disp, GC_DCM1, reg); /* disable interrupts */ outreg(host, GC_IMASK, 0); free_irq(par->irq, (void *)par); irq_dispose_mapping(par->irq); device_remove_file(&ofdev->dev, &dev_attr_dispregs); unregister_framebuffer(fbi); fb_dealloc_cmap(&fbi->cmap); iounmap(par->mmio_base); iounmap(par->fb_base); dev_set_drvdata(&ofdev->dev, NULL); release_mem_region(par->res->start, res_size); framebuffer_release(fbi); return 0;}/* * common types */static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = { { .compatible = "fujitsu,MB86276", }, { .compatible = "fujitsu,lime", }, { .compatible = "fujitsu,MB86277", }, { .compatible = "fujitsu,mint", }, { .compatible = "fujitsu,MB86293", }, { .compatible = "fujitsu,MB86294", }, { .compatible = "fujitsu,coral", }, { /* end */ }};static struct of_platform_driver of_platform_mb862xxfb_driver = { .owner = THIS_MODULE, .name = DRV_NAME, .match_table = of_platform_mb862xx_tbl, .probe = of_platform_mb862xx_probe, .remove = __devexit_p(of_platform_mb862xx_remove),};#endif#if defined(CONFIG_FB_MB862XX_PCI_GDC)static int coralp_init(struct mb862xxfb_par *par){ int cn, ver; par->host = par->mmio_base; par->i2c = par->mmio_base + MB862XX_I2C_BASE; par->disp = par->mmio_base + MB862XX_DISP_BASE; par->cap = par->mmio_base + MB862XX_CAP_BASE; par->draw = par->mmio_base + MB862XX_DRAW_BASE; par->geo = par->mmio_base + MB862XX_GEO_BASE; par->pio = par->mmio_base + MB862XX_PIO_BASE; par->refclk = GC_DISP_REFCLK_400; ver = inreg(host, GC_CID); cn = (ver & GC_CID_CNAME_MSK) >> 8; ver = ver & GC_CID_VERSION_MSK; if (cn == 3) { dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", par->pdev->revision); outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); udelay(200); outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); udelay(10); /* Clear interrupt status */ outreg(host, GC_IST, 0); } else { return -ENODEV; } return 0;}static int init_dram_ctrl(struct mb862xxfb_par *par){ unsigned long i = 0; /* * Set io mode first! Spec. says IC may be destroyed * if not set to SSTL2/LVCMOS before init. */ outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0); /* DRAM init */ outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD); outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE); outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2, GC_EVB_DCTL_REFRESH_SETTIME2); outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1); outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1); outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES); /* DLL reset done? */ while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) { udelay(GC_DCTL_INIT_WAIT_INTERVAL); if (i++ > GC_DCTL_INIT_WAIT_CNT) { dev_err(par->dev, "VRAM init failed.\n"); return -EINVAL; } } outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST); outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST); return 0;}static int carmine_init(struct mb862xxfb_par *par){ unsigned long reg; par->ctrl = par->mmio_base + MB86297_CTRL_BASE; par->i2c = par->mmio_base + MB86297_I2C_BASE; par->disp = par->mmio_base + MB86297_DISP0_BASE; par->disp1 = par->mmio_base + MB86297_DISP1_BASE; par->cap = par->mmio_base + MB86297_CAP0_BASE; par->cap1 = par->mmio_base + MB86297_CAP1_BASE; par->draw = par->mmio_base + MB86297_DRAW_BASE; par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE; par->wrback = par->mmio_base + MB86297_WRBACK_BASE; par->refclk = GC_DISP_REFCLK_533; /* warm up */ reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0; outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); /* check for engine module revision */ if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION) dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n", par->pdev->revision); else goto err_init; reg &= ~GC_CTRL_CLK_EN_2D3D; outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); /* set up vram */ if (init_dram_ctrl(par) < 0) goto err_init; outreg(ctrl, GC_CTRL_INT_MASK, 0); return 0;err_init: outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); return -EINVAL;}static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par){ switch (par->type) { case BT_CORALP: return coralp_init(par); case BT_CARMINE: return carmine_init(par); default: return -ENODEV; }}#define CHIP_ID(id) \ { PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) }static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = { /* MB86295/MB86296 */ CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP), CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA), /* MB86297 */ CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE), { 0, }};MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl);static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ struct mb862xxfb_par *par; struct fb_info *info; struct device *dev = &pdev->dev; int ret; ret = pci_enable_device(pdev); if (ret < 0) { dev_err(dev, "Cannot enable PCI device\n"); goto out; } info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); if (!info) { dev_err(dev, "framebuffer alloc failed\n"); ret = -ENOMEM; goto dis_dev; } par = info->par; par->info = info; par->dev = dev; par->pdev = pdev; par->irq = pdev->irq; ret = pci_request_regions(pdev, DRV_NAME); if (ret < 0) { dev_err(dev, "Cannot reserve region(s) for PCI device\n"); goto rel_fb; } switch (pdev->device) { case PCI_DEVICE_ID_FUJITSU_CORALP: case PCI_DEVICE_ID_FUJITSU_CORALPA: par->fb_base_phys = pci_resource_start(par->pdev, 0); par->mapped_vram = CORALP_MEM_SIZE; par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; par->mmio_len = MB862XX_MMIO_SIZE; par->type = BT_CORALP; break; case PCI_DEVICE_ID_FUJITSU_CARMINE: par->fb_base_phys = pci_resource_start(par->pdev, 2); par->mmio_base_phys = pci_resource_start(par->pdev, 3); par->mmio_len = pci_resource_len(par->pdev, 3); par->mapped_vram = CARMINE_MEM_SIZE; par->type = BT_CARMINE; break; default: /* should never occur */ goto rel_reg; } par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); if (par->fb_base == NULL) { dev_err(dev, "Cannot map framebuffer\n"); goto rel_reg; } par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); if (par->mmio_base == NULL) { dev_err(dev, "Cannot map registers\n"); ret = -EIO; goto fb_unmap; } dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", (unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram); dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n", (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len); if (mb862xx_pci_gdc_init(par)) goto io_unmap; if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, DRV_NAME, (void *)par)) { dev_err(dev, "Cannot request irq\n"); goto io_unmap; } mb862xxfb_init_fbinfo(info); if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { dev_err(dev, "Could not allocate cmap for fb_info.\n"); ret = -ENOMEM; goto free_irq; } if ((info->fbops->fb_set_par)(info)) dev_err(dev, "set_var() failed on initial setup?\n"); ret = register_framebuffer(info); if (ret < 0) { dev_err(dev, "failed to register framebuffer\n"); goto rel_cmap; } pci_set_drvdata(pdev, info); if (device_create_file(dev, &dev_attr_dispregs)) dev_err(dev, "Can't create sysfs regdump file\n"); if (par->type == BT_CARMINE) outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN); else outreg(host, GC_IMASK, GC_INT_EN); return 0;rel_cmap: fb_dealloc_cmap(&info->cmap);free_irq: free_irq(par->irq, (void *)par);io_unmap: iounmap(par->mmio_base);fb_unmap: iounmap(par->fb_base);rel_reg: pci_release_regions(pdev);rel_fb: framebuffer_release(info);dis_dev: pci_disable_device(pdev);out: return ret;}static void __devexit mb862xx_pci_remove(struct pci_dev *pdev){ struct fb_info *fbi = pci_get_drvdata(pdev); struct mb862xxfb_par *par = fbi->par; unsigned long reg; dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); /* display off */ reg = inreg(disp, GC_DCM1); reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); outreg(disp, GC_DCM1, reg); if (par->type == BT_CARMINE) { outreg(ctrl, GC_CTRL_INT_MASK, 0); outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); } else { outreg(host, GC_IMASK, 0); } device_remove_file(&pdev->dev, &dev_attr_dispregs); pci_set_drvdata(pdev, NULL); unregister_framebuffer(fbi); fb_dealloc_cmap(&fbi->cmap); free_irq(par->irq, (void *)par); iounmap(par->mmio_base); iounmap(par->fb_base); pci_release_regions(pdev); framebuffer_release(fbi); pci_disable_device(pdev);}static struct pci_driver mb862xxfb_pci_driver = { .name = DRV_NAME, .id_table = mb862xx_pci_tbl, .probe = mb862xx_pci_probe, .remove = __devexit_p(mb862xx_pci_remove),};#endifstatic int __devinit mb862xxfb_init(void){ int ret = -ENODEV;#if defined(CONFIG_FB_MB862XX_LIME) ret = of_register_platform_driver(&of_platform_mb862xxfb_driver);#endif#if defined(CONFIG_FB_MB862XX_PCI_GDC) ret = pci_register_driver(&mb862xxfb_pci_driver);#endif return ret;}static void __exit mb862xxfb_exit(void){#if defined(CONFIG_FB_MB862XX_LIME) of_unregister_platform_driver(&of_platform_mb862xxfb_driver);#endif#if defined(CONFIG_FB_MB862XX_PCI_GDC) pci_unregister_driver(&mb862xxfb_pci_driver);#endif}module_init(mb862xxfb_init);module_exit(mb862xxfb_exit);MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver");MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");MODULE_LICENSE("GPL v2");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -