📄 omapfb_main.c
字号:
{ struct fb_var_screeninfo *var = &info->var; struct fb_fix_screeninfo *fix = &info->fix; int r = 0; info->fbops = &omapfb_ops; info->flags = FBINFO_FLAG_DEFAULT; strncpy(fix->id, MODULE_NAME, sizeof(fix->id)); info->pseudo_palette = fbdev->pseudo_palette; var->accel_flags = def_accel ? FB_ACCELF_TEXT : 0; var->xres = def_vxres; var->yres = def_vyres; var->xres_virtual = def_vxres; var->yres_virtual = def_vyres; var->rotate = def_rotate; var->bits_per_pixel = fbdev->panel->bpp; set_fb_var(info, var); set_fb_fix(info); r = fb_alloc_cmap(&info->cmap, 16, 0); if (r != 0) dev_err(fbdev->dev, "unable to allocate color map memory\n"); return r;}/* Release the fb_info object */static void fbinfo_cleanup(struct omapfb_device *fbdev, struct fb_info *fbi){ fb_dealloc_cmap(&fbi->cmap);}static void planes_cleanup(struct omapfb_device *fbdev){ int i; for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { if (fbdev->fb_info[i] == NULL) break; fbinfo_cleanup(fbdev, fbdev->fb_info[i]); framebuffer_release(fbdev->fb_info[i]); }}static int planes_init(struct omapfb_device *fbdev){ struct fb_info *fbi; int i; int r; for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { struct omapfb_plane_struct *plane; fbi = framebuffer_alloc(sizeof(struct omapfb_plane_struct), fbdev->dev); if (fbi == NULL) { dev_err(fbdev->dev, "unable to allocate memory for plane info\n"); planes_cleanup(fbdev); return -ENOMEM; } plane = fbi->par; plane->idx = i; plane->fbdev = fbdev; plane->info.mirror = def_mirror; fbdev->fb_info[i] = fbi; if ((r = fbinfo_init(fbdev, fbi)) < 0) { framebuffer_release(fbi); planes_cleanup(fbdev); return r; } plane->info.out_width = fbi->var.xres; plane->info.out_height = fbi->var.yres; } return 0;}/* * Free driver resources. Can be called to rollback an aborted initialization * sequence. */static void omapfb_free_resources(struct omapfb_device *fbdev, int state){ int i; switch (state) { case OMAPFB_ACTIVE: for (i = 0; i < fbdev->mem_desc.region_cnt; i++) unregister_framebuffer(fbdev->fb_info[i]); case 7: omapfb_unregister_sysfs(fbdev); case 6: fbdev->panel->disable(fbdev->panel); case 5: omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED); case 4: planes_cleanup(fbdev); case 3: ctrl_cleanup(fbdev); case 2: fbdev->panel->cleanup(fbdev->panel); case 1: dev_set_drvdata(fbdev->dev, NULL); kfree(fbdev); case 0: /* nothing to free */ break; default: BUG(); }}static int omapfb_find_ctrl(struct omapfb_device *fbdev){ struct omapfb_platform_data *conf; char name[17]; int i; conf = fbdev->dev->platform_data; fbdev->ctrl = NULL; strncpy(name, conf->lcd.ctrl_name, sizeof(name) - 1); name[sizeof(name) - 1] = '\0'; if (strcmp(name, "internal") == 0) { fbdev->ctrl = fbdev->int_ctrl; return 0; } for (i = 0; i < ARRAY_SIZE(ctrls); i++) { dev_dbg(fbdev->dev, "ctrl %s\n", ctrls[i]->name); if (strcmp(ctrls[i]->name, name) == 0) { fbdev->ctrl = ctrls[i]; break; } } if (fbdev->ctrl == NULL) { dev_dbg(fbdev->dev, "ctrl %s not supported\n", name); return -1; } return 0;}static void check_required_callbacks(struct omapfb_device *fbdev){#define _C(x) (fbdev->ctrl->x != NULL)#define _P(x) (fbdev->panel->x != NULL) BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL); BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) && _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) && _P(init) && _P(cleanup) && _P(enable) && _P(disable) && _P(get_caps)));#undef _P#undef _C}/* * Called by LDM binding to probe and attach a new device. * Initialization sequence: * 1. allocate system omapfb_device structure * 2. select controller type according to platform configuration * init LCD panel * 3. init LCD controller and LCD DMA * 4. init system fb_info structure for all planes * 5. setup video mode for first plane and enable it * 6. enable LCD panel * 7. register sysfs attributes * OMAPFB_ACTIVE: register system fb_info structure for all planes */static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel){ struct omapfb_device *fbdev = NULL; int init_state; unsigned long phz, hhz, vhz; unsigned long vram; int i; int r = 0; init_state = 0; if (pdev->num_resources != 0) { dev_err(&pdev->dev, "probed for an unknown device\n"); r = -ENODEV; goto cleanup; } if (pdev->dev.platform_data == NULL) { dev_err(&pdev->dev, "missing platform data\n"); r = -ENOENT; goto cleanup; } fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL); if (fbdev == NULL) { dev_err(&pdev->dev, "unable to allocate memory for device info\n"); r = -ENOMEM; goto cleanup; } init_state++; fbdev->dev = &pdev->dev; fbdev->panel = panel; platform_set_drvdata(pdev, fbdev); mutex_init(&fbdev->rqueue_mutex);#ifdef CONFIG_ARCH_OMAP1 fbdev->int_ctrl = &omap1_int_ctrl;#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL fbdev->ext_if = &omap1_ext_if;#endif#else /* OMAP2 */ fbdev->int_ctrl = &omap2_int_ctrl;#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL fbdev->ext_if = &omap2_ext_if;#endif#endif if (omapfb_find_ctrl(fbdev) < 0) { dev_err(fbdev->dev, "LCD controller not found, board not supported\n"); r = -ENODEV; goto cleanup; } r = fbdev->panel->init(fbdev->panel, fbdev); if (r) goto cleanup; pr_info("omapfb: configured for panel %s\n", fbdev->panel->name); def_vxres = def_vxres ? : fbdev->panel->x_res; def_vyres = def_vyres ? : fbdev->panel->y_res; init_state++; r = ctrl_init(fbdev); if (r) goto cleanup; if (fbdev->ctrl->mmap != NULL) omapfb_ops.fb_mmap = omapfb_mmap; init_state++; check_required_callbacks(fbdev); r = planes_init(fbdev); if (r) goto cleanup; init_state++;#ifdef CONFIG_FB_OMAP_DMA_TUNE /* Set DMA priority for EMIFF access to highest */ if (cpu_class_is_omap1()) omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);#endif r = ctrl_change_mode(fbdev->fb_info[0]); if (r) { dev_err(fbdev->dev, "mode setting failed\n"); goto cleanup; } /* GFX plane is enabled by default */ r = fbdev->ctrl->enable_plane(OMAPFB_PLANE_GFX, 1); if (r) goto cleanup; omapfb_set_update_mode(fbdev, manual_update ? OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE); init_state++; r = fbdev->panel->enable(fbdev->panel); if (r) goto cleanup; init_state++; r = omapfb_register_sysfs(fbdev); if (r) goto cleanup; init_state++; vram = 0; for (i = 0; i < fbdev->mem_desc.region_cnt; i++) { r = register_framebuffer(fbdev->fb_info[i]); if (r != 0) { dev_err(fbdev->dev, "registering framebuffer %d failed\n", i); goto cleanup; } vram += fbdev->mem_desc.region[i].size; } fbdev->state = OMAPFB_ACTIVE; panel = fbdev->panel; phz = panel->pixel_clock * 1000; hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw); vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw); omapfb_dev = fbdev; pr_info("omapfb: Framebuffer initialized. Total vram %lu planes %d\n", vram, fbdev->mem_desc.region_cnt); pr_info("omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz " "vfreq %lu.%lu Hz\n", phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10); return 0;cleanup: omapfb_free_resources(fbdev, init_state); return r;}static int omapfb_probe(struct platform_device *pdev){ BUG_ON(fbdev_pdev != NULL); /* Delay actual initialization until the LCD is registered */ fbdev_pdev = pdev; if (fbdev_panel != NULL) omapfb_do_probe(fbdev_pdev, fbdev_panel); return 0;}void omapfb_register_panel(struct lcd_panel *panel){ BUG_ON(fbdev_panel != NULL); fbdev_panel = panel; if (fbdev_pdev != NULL) omapfb_do_probe(fbdev_pdev, fbdev_panel);}/* Called when the device is being detached from the driver */static int omapfb_remove(struct platform_device *pdev){ struct omapfb_device *fbdev = platform_get_drvdata(pdev); enum omapfb_state saved_state = fbdev->state; /* FIXME: wait till completion of pending events */ fbdev->state = OMAPFB_DISABLED; omapfb_free_resources(fbdev, saved_state); return 0;}/* PM suspend */static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg){ struct omapfb_device *fbdev = platform_get_drvdata(pdev); omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]); return 0;}/* PM resume */static int omapfb_resume(struct platform_device *pdev){ struct omapfb_device *fbdev = platform_get_drvdata(pdev); omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]); return 0;}static struct platform_driver omapfb_driver = { .probe = omapfb_probe, .remove = omapfb_remove, .suspend = omapfb_suspend, .resume = omapfb_resume, .driver = { .name = MODULE_NAME, .owner = THIS_MODULE, },};#ifndef MODULE/* Process kernel command line parameters */static int __init omapfb_setup(char *options){ char *this_opt = NULL; int r = 0; pr_debug("omapfb: options %s\n", options); if (!options || !*options) return 0; while (!r && (this_opt = strsep(&options, ",")) != NULL) { if (!strncmp(this_opt, "accel", 5)) def_accel = 1; else if (!strncmp(this_opt, "vram:", 5)) { char *suffix; unsigned long vram; vram = (simple_strtoul(this_opt + 5, &suffix, 0)); switch (suffix[0]) { case '\0': break; case 'm': case 'M': vram *= 1024; /* Fall through */ case 'k': case 'K': vram *= 1024; break; default: pr_debug("omapfb: invalid vram suffix %c\n", suffix[0]); r = -1; } def_vram[def_vram_cnt++] = vram; } else if (!strncmp(this_opt, "vxres:", 6)) def_vxres = simple_strtoul(this_opt + 6, NULL, 0); else if (!strncmp(this_opt, "vyres:", 6)) def_vyres = simple_strtoul(this_opt + 6, NULL, 0); else if (!strncmp(this_opt, "rotate:", 7)) def_rotate = (simple_strtoul(this_opt + 7, NULL, 0)); else if (!strncmp(this_opt, "mirror:", 7)) def_mirror = (simple_strtoul(this_opt + 7, NULL, 0)); else if (!strncmp(this_opt, "manual_update", 13)) manual_update = 1; else { pr_debug("omapfb: invalid option\n"); r = -1; } } return r;}#endif/* Register both the driver and the device */static int __init omapfb_init(void){#ifndef MODULE char *option; if (fb_get_options("omapfb", &option)) return -ENODEV; omapfb_setup(option);#endif /* Register the driver with LDM */ if (platform_driver_register(&omapfb_driver)) { pr_debug("failed to register omapfb driver\n"); return -ENODEV; } return 0;}static void __exit omapfb_cleanup(void){ platform_driver_unregister(&omapfb_driver);}module_param_named(accel, def_accel, uint, 0664);module_param_array_named(vram, def_vram, ulong, &def_vram_cnt, 0664);module_param_named(vxres, def_vxres, long, 0664);module_param_named(vyres, def_vyres, long, 0664);module_param_named(rotate, def_rotate, uint, 0664);module_param_named(mirror, def_mirror, uint, 0664);module_param_named(manual_update, manual_update, bool, 0664);module_init(omapfb_init);module_exit(omapfb_cleanup);MODULE_DESCRIPTION("TI OMAP framebuffer driver");MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -