diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 0628e7d7dcf3..5b3549f1236c 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -802,38 +803,80 @@ static const short da850_evm_mmcsd0_pins[] __initconst = { -1 }; -static void da850_panel_power_ctrl(int val) -{ - /* lcd backlight */ - gpio_set_value(DA850_LCD_BL_PIN, val); +static struct property_entry da850_lcd_backlight_props[] = { + PROPERTY_ENTRY_BOOL("default-on"), + { } +}; - /* lcd power */ - gpio_set_value(DA850_LCD_PWR_PIN, val); -} +static struct gpiod_lookup_table da850_lcd_backlight_gpio_table = { + .dev_id = "gpio-backlight", + .table = { + GPIO_LOOKUP("davinci_gpio", DA850_LCD_BL_PIN, NULL, 0), + { } + }, +}; + +static const struct platform_device_info da850_lcd_backlight_info = { + .name = "gpio-backlight", + .id = PLATFORM_DEVID_NONE, + .properties = da850_lcd_backlight_props, +}; + +static struct regulator_consumer_supply da850_lcd_supplies[] = { + REGULATOR_SUPPLY("lcd", NULL), +}; + +static struct regulator_init_data da850_lcd_supply_data = { + .consumer_supplies = da850_lcd_supplies, + .num_consumer_supplies = ARRAY_SIZE(da850_lcd_supplies), + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config da850_lcd_supply = { + .supply_name = "lcd", + .microvolts = 33000000, + .init_data = &da850_lcd_supply_data, +}; + +static struct platform_device da850_lcd_supply_device = { + .name = "reg-fixed-voltage", + .id = 1, /* Dummy fixed regulator is 0 */ + .dev = { + .platform_data = &da850_lcd_supply, + }, +}; + +static struct gpiod_lookup_table da850_lcd_supply_gpio_table = { + .dev_id = "reg-fixed-voltage.1", + .table = { + GPIO_LOOKUP("davinci_gpio", DA850_LCD_PWR_PIN, NULL, 0), + { } + }, +}; + +static struct gpiod_lookup_table *da850_lcd_gpio_lookups[] = { + &da850_lcd_backlight_gpio_table, + &da850_lcd_supply_gpio_table, +}; static int da850_lcd_hw_init(void) { + struct platform_device *backlight; int status; - status = gpio_request(DA850_LCD_BL_PIN, "lcd bl"); - if (status < 0) + gpiod_add_lookup_tables(da850_lcd_gpio_lookups, + ARRAY_SIZE(da850_lcd_gpio_lookups)); + + backlight = platform_device_register_full(&da850_lcd_backlight_info); + if (IS_ERR(backlight)) + return PTR_ERR(backlight); + + status = platform_device_register(&da850_lcd_supply_device); + if (status) return status; - status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr"); - if (status < 0) { - gpio_free(DA850_LCD_BL_PIN); - return status; - } - - gpio_direction_output(DA850_LCD_BL_PIN, 0); - gpio_direction_output(DA850_LCD_PWR_PIN, 0); - - /* Switch off panel power and backlight */ - da850_panel_power_ctrl(0); - - /* Switch on panel power and backlight */ - da850_panel_power_ctrl(1); - return 0; } @@ -1443,7 +1486,6 @@ static __init void da850_evm_init(void) if (ret) pr_warn("%s: LCD initialization failed: %d\n", __func__, ret); - sharp_lk043t1dg01_pdata.panel_power_ctrl = da850_panel_power_ctrl, ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata); if (ret) pr_warn("%s: LCDC registration failed: %d\n", __func__, ret); diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c index b1cf248f3291..2d3dcc52fcf3 100644 --- a/drivers/video/fbdev/da8xx-fb.c +++ b/drivers/video/fbdev/da8xx-fb.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -164,7 +165,7 @@ struct da8xx_fb_par { struct notifier_block freq_transition; #endif unsigned int lcdc_clk_rate; - void (*panel_power_ctrl)(int); + struct regulator *lcd_supply; u32 pseudo_palette[16]; struct fb_videomode mode; struct lcd_ctrl_config cfg; @@ -1066,33 +1067,30 @@ static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) static int fb_remove(struct platform_device *dev) { struct fb_info *info = dev_get_drvdata(&dev->dev); - - if (info) { - struct da8xx_fb_par *par = info->par; + struct da8xx_fb_par *par = info->par; + int ret; #ifdef CONFIG_CPU_FREQ - lcd_da8xx_cpufreq_deregister(par); + lcd_da8xx_cpufreq_deregister(par); #endif - if (par->panel_power_ctrl) - par->panel_power_ctrl(0); - - lcd_disable_raster(DA8XX_FRAME_WAIT); - lcdc_write(0, LCD_RASTER_CTRL_REG); - - /* disable DMA */ - lcdc_write(0, LCD_DMA_CTRL_REG); - - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base, - par->p_palette_base); - dma_free_coherent(par->dev, par->vram_size, par->vram_virt, - par->vram_phys); - pm_runtime_put_sync(&dev->dev); - pm_runtime_disable(&dev->dev); - framebuffer_release(info); - + if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; } + + lcd_disable_raster(DA8XX_FRAME_WAIT); + lcdc_write(0, LCD_RASTER_CTRL_REG); + + /* disable DMA */ + lcdc_write(0, LCD_DMA_CTRL_REG); + + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + pm_runtime_put_sync(&dev->dev); + pm_runtime_disable(&dev->dev); + framebuffer_release(info); + return 0; } @@ -1179,15 +1177,21 @@ static int cfb_blank(int blank, struct fb_info *info) case FB_BLANK_UNBLANK: lcd_enable_raster(); - if (par->panel_power_ctrl) - par->panel_power_ctrl(1); + if (par->lcd_supply) { + ret = regulator_enable(par->lcd_supply); + if (ret) + return ret; + } break; case FB_BLANK_NORMAL: case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: - if (par->panel_power_ctrl) - par->panel_power_ctrl(0); + if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; + } lcd_disable_raster(DA8XX_FRAME_WAIT); break; @@ -1328,7 +1332,6 @@ static int fb_probe(struct platform_device *device) { struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&device->dev); - struct resource *lcdc_regs; struct lcd_ctrl_config *lcd_cfg; struct fb_videomode *lcdc_info; struct fb_info *da8xx_fb_info; @@ -1346,8 +1349,7 @@ static int fb_probe(struct platform_device *device) if (lcdc_info == NULL) return -ENODEV; - lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); - da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs); + da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0); if (IS_ERR(da8xx_fb_reg_base)) return PTR_ERR(da8xx_fb_reg_base); @@ -1395,9 +1397,19 @@ static int fb_probe(struct platform_device *device) par->dev = &device->dev; par->lcdc_clk = tmp_lcdc_clk; par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - if (fb_pdata->panel_power_ctrl) { - par->panel_power_ctrl = fb_pdata->panel_power_ctrl; - par->panel_power_ctrl(1); + + 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_pm_runtime_disable; + } + + par->lcd_supply = NULL; + } else { + ret = regulator_enable(par->lcd_supply); + if (ret) + goto err_pm_runtime_disable; } fb_videomode_to_var(&da8xx_fb_var, lcdc_info); @@ -1411,10 +1423,10 @@ static int fb_probe(struct platform_device *device) par->vram_size = roundup(par->vram_size/8, ulcm); par->vram_size = par->vram_size * LCD_NUM_BUFFERS; - par->vram_virt = dma_alloc_coherent(par->dev, - par->vram_size, - &par->vram_phys, - GFP_KERNEL | GFP_DMA); + 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"); @@ -1432,20 +1444,20 @@ static int fb_probe(struct platform_device *device) da8xx_fb_fix.line_length - 1; /* allocate palette buffer */ - par->v_palette_base = dma_alloc_coherent(par->dev, PALETTE_SIZE, - &par->p_palette_base, - GFP_KERNEL | GFP_DMA); + 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_mem; + goto err_release_fb; } par->irq = platform_get_irq(device, 0); if (par->irq < 0) { ret = -ENOENT; - goto err_release_pl_mem; + goto err_release_fb; } da8xx_fb_var.grayscale = @@ -1463,7 +1475,7 @@ static int fb_probe(struct platform_device *device) ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); if (ret) - goto err_release_pl_mem; + goto err_release_fb; da8xx_fb_info->cmap.len = par->palette_sz; /* initialize var_screeninfo */ @@ -1517,14 +1529,6 @@ err_cpu_freq: err_dealloc_cmap: fb_dealloc_cmap(&da8xx_fb_info->cmap); -err_release_pl_mem: - dma_free_coherent(par->dev, PALETTE_SIZE, par->v_palette_base, - par->p_palette_base); - -err_release_fb_mem: - dma_free_coherent(par->dev, par->vram_size, par->vram_virt, - par->vram_phys); - err_release_fb: framebuffer_release(da8xx_fb_info); @@ -1603,10 +1607,14 @@ static int fb_suspend(struct device *dev) { struct fb_info *info = dev_get_drvdata(dev); struct da8xx_fb_par *par = info->par; + int ret; console_lock(); - if (par->panel_power_ctrl) - par->panel_power_ctrl(0); + if (par->lcd_supply) { + ret = regulator_disable(par->lcd_supply); + if (ret) + return ret; + } fb_set_suspend(info, 1); lcd_disable_raster(DA8XX_FRAME_WAIT); @@ -1620,6 +1628,7 @@ static int fb_resume(struct device *dev) { struct fb_info *info = dev_get_drvdata(dev); struct da8xx_fb_par *par = info->par; + int ret; console_lock(); pm_runtime_get_sync(dev); @@ -1627,8 +1636,11 @@ static int fb_resume(struct device *dev) if (par->blank == FB_BLANK_UNBLANK) { lcd_enable_raster(); - if (par->panel_power_ctrl) - par->panel_power_ctrl(1); + if (par->lcd_supply) { + ret = regulator_enable(par->lcd_supply); + if (ret) + return ret; + } } fb_set_suspend(info, 0); diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h index efed3c3383d6..1d19ae62b844 100644 --- a/include/video/da8xx-fb.h +++ b/include/video/da8xx-fb.h @@ -32,7 +32,6 @@ struct da8xx_lcdc_platform_data { const char manu_name[10]; void *controller_data; const char type[25]; - void (*panel_power_ctrl)(int); }; struct lcd_ctrl_config {