📄 tmiofb.c
字号:
case FBIO_TMIO_ACC_SYNC: tmiofb_sync(fbi); return 0; case FBIO_TMIO_ACC_WRITE: { u32 __user *argp = (void __user *) arg; u32 len; u32 acc[16]; if (get_user(len, argp)) return -EFAULT; if (len > ARRAY_SIZE(acc)) return -EINVAL; if (copy_from_user(acc, argp + 1, sizeof(u32) * len)) return -EFAULT; return tmiofb_acc_write(fbi, acc, len); }#endif } return -ENOTTY;}/*--------------------------------------------------------------------------*//* Select the smallest mode that allows the desired resolution to be * displayed. If desired, the x and y parameters can be rounded up to * match the selected mode. */static struct fb_videomode *tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var){ struct mfd_cell *cell = info->device->platform_data; struct tmio_fb_data *data = cell->driver_data; struct fb_videomode *best = NULL; int i; for (i = 0; i < data->num_modes; i++) { struct fb_videomode *mode = data->modes + i; if (mode->xres >= var->xres && mode->yres >= var->yres && (!best || (mode->xres < best->xres && mode->yres < best->yres))) best = mode; } return best;}static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct fb_videomode *mode; struct mfd_cell *cell = info->device->platform_data; struct tmio_fb_data *data = cell->driver_data; mode = tmiofb_find_mode(info, var); if (!mode || var->bits_per_pixel > 16) return -EINVAL; fb_videomode_to_var(var, mode); var->xres_virtual = mode->xres; var->yres_virtual = info->screen_size / (mode->xres * 2); if (var->yres_virtual < var->yres) return -EINVAL; var->xoffset = 0; var->yoffset = 0; var->bits_per_pixel = 16; var->grayscale = 0; var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; var->nonstd = 0; var->height = data->height; /* mm */ var->width = data->width; /* mm */ var->rotate = 0; return 0;}static int tmiofb_set_par(struct fb_info *info){ struct fb_var_screeninfo *var = &info->var; struct fb_videomode *mode; mode = tmiofb_find_mode(info, var); if (!mode) return -EINVAL; info->mode = mode; info->fix.line_length = info->mode->xres * var->bits_per_pixel / 8; tmiofb_hw_mode(to_platform_device(info->device)); tmiofb_clearscreen(info); return 0;}static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct tmiofb_par *par = info->par; if (regno < ARRAY_SIZE(par->pseudo_palette)) { par->pseudo_palette[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); return 0; } return -EINVAL;}static int tmiofb_blank(int blank, struct fb_info *info){ /* * everything is done in lcd/bl drivers. * this is purely to make sysfs happy and work. */ return 0;}static struct fb_ops tmiofb_ops = { .owner = THIS_MODULE, .fb_ioctl = tmiofb_ioctl, .fb_check_var = tmiofb_check_var, .fb_set_par = tmiofb_set_par, .fb_setcolreg = tmiofb_setcolreg, .fb_blank = tmiofb_blank, .fb_imageblit = cfb_imageblit,#ifdef CONFIG_FB_TMIO_ACCELL .fb_sync = tmiofb_sync, .fb_fillrect = tmiofb_fillrect, .fb_copyarea = tmiofb_copyarea,#else .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea,#endif};/*--------------------------------------------------------------------------*/static int __devinit tmiofb_probe(struct platform_device *dev){ struct mfd_cell *cell = dev->dev.platform_data; struct tmio_fb_data *data = cell->driver_data; struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1); struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0); struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2); int irq = platform_get_irq(dev, 0); struct fb_info *info; struct tmiofb_par *par; int retval; /* * This is the only way ATM to disable the fb */ if (data == NULL) { dev_err(&dev->dev, "NULL platform data!\n"); return -EINVAL; } info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev); if (!info) return -ENOMEM; par = info->par;#ifdef CONFIG_FB_TMIO_ACCELL init_waitqueue_head(&par->wait_acc); par->use_polling = true; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;#else info->flags = FBINFO_DEFAULT;#endif info->fbops = &tmiofb_ops; strcpy(info->fix.id, "tmio-fb"); info->fix.smem_start = vram->start; info->fix.smem_len = resource_size(vram); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.mmio_start = lcr->start; info->fix.mmio_len = resource_size(lcr); info->fix.accel = FB_ACCEL_NONE; info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE); info->pseudo_palette = par->pseudo_palette; par->ccr = ioremap(ccr->start, resource_size(ccr)); if (!par->ccr) { retval = -ENOMEM; goto err_ioremap_ccr; } par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len); if (!par->lcr) { retval = -ENOMEM; goto err_ioremap_lcr; } info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { retval = -ENOMEM; goto err_ioremap_vram; } retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, dev->dev.bus_id, info); if (retval) goto err_request_irq; platform_set_drvdata(dev, info); retval = fb_find_mode(&info->var, info, mode_option, data->modes, data->num_modes, data->modes, 16); if (!retval) { retval = -EINVAL; goto err_find_mode; } if (cell->enable) { retval = cell->enable(dev); if (retval) goto err_enable; } retval = tmiofb_hw_init(dev); if (retval) goto err_hw_init; fb_videomode_to_modelist(data->modes, data->num_modes, &info->modelist); retval = register_framebuffer(info); if (retval < 0) goto err_register_framebuffer; printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); return 0;err_register_framebuffer:/*err_set_par:*/ tmiofb_hw_stop(dev);err_hw_init: if (cell->disable) cell->disable(dev);err_enable:err_find_mode: platform_set_drvdata(dev, NULL); free_irq(irq, info);err_request_irq: iounmap(info->screen_base);err_ioremap_vram: iounmap(par->lcr);err_ioremap_lcr: iounmap(par->ccr);err_ioremap_ccr: framebuffer_release(info); return retval;}static int __devexit tmiofb_remove(struct platform_device *dev){ struct mfd_cell *cell = dev->dev.platform_data; struct fb_info *info = platform_get_drvdata(dev); int irq = platform_get_irq(dev, 0); struct tmiofb_par *par; if (info) { par = info->par; unregister_framebuffer(info); tmiofb_hw_stop(dev); if (cell->disable) cell->disable(dev); platform_set_drvdata(dev, NULL); free_irq(irq, info); iounmap(info->screen_base); iounmap(par->lcr); iounmap(par->ccr); framebuffer_release(info); } return 0;}#ifdef DEBUGstatic void tmiofb_dump_regs(struct platform_device *dev){ struct fb_info *info = platform_get_drvdata(dev); struct tmiofb_par *par = info->par; printk(KERN_DEBUG "lhccr:\n");#define CCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\ tmio_ioread16(par->ccr + CCR_ ## n)); CCR_PR(CMD); CCR_PR(REVID); CCR_PR(BASEL); CCR_PR(BASEH); CCR_PR(UGCC); CCR_PR(GCC); CCR_PR(USC); CCR_PR(VRAMRTC); CCR_PR(VRAMSAC); CCR_PR(VRAMBC);#undef CCR_PR printk(KERN_DEBUG "lcr: \n");#define LCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\ tmio_ioread16(par->lcr + LCR_ ## n)); LCR_PR(UIS); LCR_PR(VHPN); LCR_PR(CFSAL); LCR_PR(CFSAH); LCR_PR(CFS); LCR_PR(CFWS); LCR_PR(BBIE); LCR_PR(BBISC); LCR_PR(CCS); LCR_PR(BBES); LCR_PR(CMDL); LCR_PR(CMDH); LCR_PR(CFC); LCR_PR(CCIFC); LCR_PR(HWT); LCR_PR(LCDCCRC); LCR_PR(LCDCC); LCR_PR(LCDCOPC); LCR_PR(LCDIS); LCR_PR(LCDIM); LCR_PR(LCDIE); LCR_PR(GDSAL); LCR_PR(GDSAH); LCR_PR(VHPCL); LCR_PR(VHPCH); LCR_PR(GM); LCR_PR(HT); LCR_PR(HDS); LCR_PR(HSS); LCR_PR(HSE); LCR_PR(HNP); LCR_PR(VT); LCR_PR(VDS); LCR_PR(VSS); LCR_PR(VSE); LCR_PR(CDLN); LCR_PR(ILN); LCR_PR(SP); LCR_PR(MISC); LCR_PR(VIHSS); LCR_PR(VIVS); LCR_PR(VIVE); LCR_PR(VIVSS); LCR_PR(VCCIS); LCR_PR(VIDWSAL); LCR_PR(VIDWSAH); LCR_PR(VIDRSAL); LCR_PR(VIDRSAH); LCR_PR(VIPDDST); LCR_PR(VIPDDET); LCR_PR(VIE); LCR_PR(VCS); LCR_PR(VPHWC); LCR_PR(VPHS); LCR_PR(VPVWC); LCR_PR(VPVS); LCR_PR(PLHPIX); LCR_PR(XS); LCR_PR(XCKHW); LCR_PR(STHS); LCR_PR(VT2); LCR_PR(YCKSW); LCR_PR(YSTS); LCR_PR(PPOLS); LCR_PR(PRECW); LCR_PR(VCLKHW); LCR_PR(OC);#undef LCR_PR}#endif#ifdef CONFIG_PMstatic int tmiofb_suspend(struct platform_device *dev, pm_message_t state){ struct fb_info *info = platform_get_drvdata(dev);#ifdef CONFIG_FB_TMIO_ACCELL struct tmiofb_par *par = info->par;#endif struct mfd_cell *cell = dev->dev.platform_data; int retval = 0; acquire_console_sem(); fb_set_suspend(info, 1); if (info->fbops->fb_sync) info->fbops->fb_sync(info);#ifdef CONFIG_FB_TMIO_ACCELL /* * The fb should be usable even if interrupts are disabled (and they are * during suspend/resume). Switch temporary to forced polling. */ printk(KERN_INFO "tmiofb: switching to polling\n"); par->use_polling = true;#endif tmiofb_hw_stop(dev); if (cell->suspend) retval = cell->suspend(dev); release_console_sem(); return retval;}static int tmiofb_resume(struct platform_device *dev){ struct fb_info *info = platform_get_drvdata(dev); struct mfd_cell *cell = dev->dev.platform_data; int retval; acquire_console_sem(); if (cell->resume) { retval = cell->resume(dev); if (retval) goto out; } tmiofb_irq(-1, info); tmiofb_hw_init(dev); tmiofb_hw_mode(dev); fb_set_suspend(info, 0);out: release_console_sem(); return retval;}#else#define tmiofb_suspend NULL#define tmiofb_resume NULL#endifstatic struct platform_driver tmiofb_driver = { .driver.name = "tmio-fb", .driver.owner = THIS_MODULE, .probe = tmiofb_probe, .remove = __devexit_p(tmiofb_remove), .suspend = tmiofb_suspend, .resume = tmiofb_resume,};/*--------------------------------------------------------------------------*/#ifndef MODULEstatic void __init tmiofb_setup(char *options){ char *this_opt; if (!options || !*options) return; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; /* * FIXME */ }}#endifstatic int __init tmiofb_init(void){#ifndef MODULE char *option = NULL; if (fb_get_options("tmiofb", &option)) return -ENODEV; tmiofb_setup(option);#endif return platform_driver_register(&tmiofb_driver);}static void __exit tmiofb_cleanup(void){ platform_driver_unregister(&tmiofb_driver);}module_init(tmiofb_init);module_exit(tmiofb_cleanup);MODULE_DESCRIPTION("TMIO framebuffer driver");MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -