in fbdev/da8xx-fb.c [1331:1540]
static int fb_probe(struct platform_device *device)
{
struct da8xx_lcdc_platform_data *fb_pdata =
dev_get_platdata(&device->dev);
struct lcd_ctrl_config *lcd_cfg;
struct fb_videomode *lcdc_info;
struct fb_info *da8xx_fb_info;
struct da8xx_fb_par *par;
struct clk *tmp_lcdc_clk;
int ret;
unsigned long ulcm;
if (fb_pdata == NULL) {
dev_err(&device->dev, "Can not get platform data\n");
return -ENOENT;
}
lcdc_info = da8xx_fb_get_videomode(device);
if (lcdc_info == NULL)
return -ENODEV;
da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0);
if (IS_ERR(da8xx_fb_reg_base))
return PTR_ERR(da8xx_fb_reg_base);
tmp_lcdc_clk = devm_clk_get(&device->dev, "fck");
if (IS_ERR(tmp_lcdc_clk)) {
dev_err(&device->dev, "Can not get device clock\n");
return PTR_ERR(tmp_lcdc_clk);
}
pm_runtime_enable(&device->dev);
pm_runtime_get_sync(&device->dev);
/* Determine LCD IP Version */
switch (lcdc_read(LCD_PID_REG)) {
case 0x4C100102:
lcd_revision = LCD_VERSION_1;
break;
case 0x4F200800:
case 0x4F201000:
lcd_revision = LCD_VERSION_2;
break;
default:
dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
"defaulting to LCD revision 1\n",
lcdc_read(LCD_PID_REG));
lcd_revision = LCD_VERSION_1;
break;
}
lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
if (!lcd_cfg) {
ret = -EINVAL;
goto err_pm_runtime_disable;
}
da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
&device->dev);
if (!da8xx_fb_info) {
ret = -ENOMEM;
goto err_pm_runtime_disable;
}
par = da8xx_fb_info->par;
par->dev = &device->dev;
par->lcdc_clk = tmp_lcdc_clk;
par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd");
if (IS_ERR(par->lcd_supply)) {
if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_release_fb;
}
par->lcd_supply = NULL;
} else {
ret = regulator_enable(par->lcd_supply);
if (ret)
goto err_release_fb;
}
fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
par->cfg = *lcd_cfg;
da8xx_fb_lcd_reset();
/* allocate frame buffer */
par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
par->vram_size = roundup(par->vram_size/8, ulcm);
par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
par->vram_virt = dmam_alloc_coherent(par->dev,
par->vram_size,
&par->vram_phys,
GFP_KERNEL | GFP_DMA);
if (!par->vram_virt) {
dev_err(&device->dev,
"GLCD: kmalloc for frame buffer failed\n");
ret = -EINVAL;
goto err_release_fb;
}
da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
da8xx_fb_fix.smem_start = par->vram_phys;
da8xx_fb_fix.smem_len = par->vram_size;
da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8;
par->dma_start = par->vram_phys;
par->dma_end = par->dma_start + lcdc_info->yres *
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE,
&par->p_palette_base,
GFP_KERNEL | GFP_DMA);
if (!par->v_palette_base) {
dev_err(&device->dev,
"GLCD: kmalloc for palette buffer failed\n");
ret = -EINVAL;
goto err_release_fb;
}
par->irq = platform_get_irq(device, 0);
if (par->irq < 0) {
ret = -ENOENT;
goto err_release_fb;
}
da8xx_fb_var.grayscale =
lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
/* Initialize fbinfo */
da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
da8xx_fb_info->fix = da8xx_fb_fix;
da8xx_fb_info->var = da8xx_fb_var;
da8xx_fb_info->fbops = &da8xx_fb_ops;
da8xx_fb_info->pseudo_palette = par->pseudo_palette;
da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
if (ret)
goto err_release_fb;
da8xx_fb_info->cmap.len = par->palette_sz;
/* initialize var_screeninfo */
da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
fb_set_var(da8xx_fb_info, &da8xx_fb_var);
platform_set_drvdata(device, da8xx_fb_info);
/* initialize the vsync wait queue */
init_waitqueue_head(&par->vsync_wait);
par->vsync_timeout = HZ / 5;
par->which_dma_channel_done = -1;
spin_lock_init(&par->lock_for_chan_update);
/* Register the Frame Buffer */
if (register_framebuffer(da8xx_fb_info) < 0) {
dev_err(&device->dev,
"GLCD: Frame Buffer Registration Failed!\n");
ret = -EINVAL;
goto err_dealloc_cmap;
}
#ifdef CONFIG_CPU_FREQ
ret = lcd_da8xx_cpufreq_register(par);
if (ret) {
dev_err(&device->dev, "failed to register cpufreq\n");
goto err_cpu_freq;
}
#endif
if (lcd_revision == LCD_VERSION_1)
lcdc_irq_handler = lcdc_irq_handler_rev01;
else {
init_waitqueue_head(&frame_done_wq);
lcdc_irq_handler = lcdc_irq_handler_rev02;
}
ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
DRIVER_NAME, par);
if (ret)
goto irq_freq;
return 0;
irq_freq:
#ifdef CONFIG_CPU_FREQ
lcd_da8xx_cpufreq_deregister(par);
err_cpu_freq:
#endif
unregister_framebuffer(da8xx_fb_info);
err_dealloc_cmap:
fb_dealloc_cmap(&da8xx_fb_info->cmap);
err_release_fb:
framebuffer_release(da8xx_fb_info);
err_pm_runtime_disable:
pm_runtime_put_sync(&device->dev);
pm_runtime_disable(&device->dev);
return ret;
}