Commit 735f0131 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'davinci-for-v5.4/fbdev' of...

Merge tag 'davinci-for-v5.4/fbdev' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into arm/drivers

This converts the da8xx fbdev driver to use GPIO backlight device
and regulator devices. This will finally help get rid of legacy
GPIO API calls and simplify DaVinci GPIO driver.

* tag 'davinci-for-v5.4/fbdev' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci:
  fbdev: da8xx: use resource management for dma
  fbdev: da8xx-fb: drop a redundant if
  fbdev: da8xx-fb: use devm_platform_ioremap_resource()
  fbdev: da8xx: remove panel_power_ctrl() callback from platform data
  ARM: davinci: da850-evm: switch to using a fixed regulator for lcdc
  fbdev: da8xx: add support for a regulator
  ARM: davinci: da850-evm: model the backlight GPIO as an actual device
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents bff00fdf 671da5f3
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/platform_data/ti-aemif.h> #include <linux/platform_data/ti-aemif.h>
#include <linux/platform_data/spi-davinci.h> #include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/uio_pruss.h> #include <linux/platform_data/uio_pruss.h>
#include <linux/property.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/tps6507x.h> #include <linux/regulator/tps6507x.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
...@@ -802,37 +803,79 @@ static const short da850_evm_mmcsd0_pins[] __initconst = { ...@@ -802,37 +803,79 @@ static const short da850_evm_mmcsd0_pins[] __initconst = {
-1 -1
}; };
static void da850_panel_power_ctrl(int val) static struct property_entry da850_lcd_backlight_props[] = {
{ PROPERTY_ENTRY_BOOL("default-on"),
/* lcd backlight */ { }
gpio_set_value(DA850_LCD_BL_PIN, val); };
/* lcd power */ static struct gpiod_lookup_table da850_lcd_backlight_gpio_table = {
gpio_set_value(DA850_LCD_PWR_PIN, val); .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) static int da850_lcd_hw_init(void)
{ {
struct platform_device *backlight;
int status; int status;
status = gpio_request(DA850_LCD_BL_PIN, "lcd bl"); gpiod_add_lookup_tables(da850_lcd_gpio_lookups,
if (status < 0) ARRAY_SIZE(da850_lcd_gpio_lookups));
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); backlight = platform_device_register_full(&da850_lcd_backlight_info);
gpio_direction_output(DA850_LCD_PWR_PIN, 0); if (IS_ERR(backlight))
return PTR_ERR(backlight);
/* Switch off panel power and backlight */ status = platform_device_register(&da850_lcd_supply_device);
da850_panel_power_ctrl(0); if (status)
return status;
/* Switch on panel power and backlight */
da850_panel_power_ctrl(1);
return 0; return 0;
} }
...@@ -1443,7 +1486,6 @@ static __init void da850_evm_init(void) ...@@ -1443,7 +1486,6 @@ static __init void da850_evm_init(void)
if (ret) if (ret)
pr_warn("%s: LCD initialization failed: %d\n", __func__, 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); ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata);
if (ret) if (ret)
pr_warn("%s: LCDC registration failed: %d\n", __func__, ret); pr_warn("%s: LCDC registration failed: %d\n", __func__, ret);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/regulator/consumer.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -164,7 +165,7 @@ struct da8xx_fb_par { ...@@ -164,7 +165,7 @@ struct da8xx_fb_par {
struct notifier_block freq_transition; struct notifier_block freq_transition;
#endif #endif
unsigned int lcdc_clk_rate; unsigned int lcdc_clk_rate;
void (*panel_power_ctrl)(int); struct regulator *lcd_supply;
u32 pseudo_palette[16]; u32 pseudo_palette[16];
struct fb_videomode mode; struct fb_videomode mode;
struct lcd_ctrl_config cfg; struct lcd_ctrl_config cfg;
...@@ -1066,15 +1067,17 @@ static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) ...@@ -1066,15 +1067,17 @@ static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
static int fb_remove(struct platform_device *dev) static int fb_remove(struct platform_device *dev)
{ {
struct fb_info *info = dev_get_drvdata(&dev->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 #ifdef CONFIG_CPU_FREQ
lcd_da8xx_cpufreq_deregister(par); lcd_da8xx_cpufreq_deregister(par);
#endif #endif
if (par->panel_power_ctrl) if (par->lcd_supply) {
par->panel_power_ctrl(0); ret = regulator_disable(par->lcd_supply);
if (ret)
return ret;
}
lcd_disable_raster(DA8XX_FRAME_WAIT); lcd_disable_raster(DA8XX_FRAME_WAIT);
lcdc_write(0, LCD_RASTER_CTRL_REG); lcdc_write(0, LCD_RASTER_CTRL_REG);
...@@ -1084,15 +1087,10 @@ static int fb_remove(struct platform_device *dev) ...@@ -1084,15 +1087,10 @@ static int fb_remove(struct platform_device *dev)
unregister_framebuffer(info); unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap); 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_put_sync(&dev->dev);
pm_runtime_disable(&dev->dev); pm_runtime_disable(&dev->dev);
framebuffer_release(info); framebuffer_release(info);
}
return 0; return 0;
} }
...@@ -1179,15 +1177,21 @@ static int cfb_blank(int blank, struct fb_info *info) ...@@ -1179,15 +1177,21 @@ static int cfb_blank(int blank, struct fb_info *info)
case FB_BLANK_UNBLANK: case FB_BLANK_UNBLANK:
lcd_enable_raster(); lcd_enable_raster();
if (par->panel_power_ctrl) if (par->lcd_supply) {
par->panel_power_ctrl(1); ret = regulator_enable(par->lcd_supply);
if (ret)
return ret;
}
break; break;
case FB_BLANK_NORMAL: case FB_BLANK_NORMAL:
case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN: case FB_BLANK_POWERDOWN:
if (par->panel_power_ctrl) if (par->lcd_supply) {
par->panel_power_ctrl(0); ret = regulator_disable(par->lcd_supply);
if (ret)
return ret;
}
lcd_disable_raster(DA8XX_FRAME_WAIT); lcd_disable_raster(DA8XX_FRAME_WAIT);
break; break;
...@@ -1328,7 +1332,6 @@ static int fb_probe(struct platform_device *device) ...@@ -1328,7 +1332,6 @@ static int fb_probe(struct platform_device *device)
{ {
struct da8xx_lcdc_platform_data *fb_pdata = struct da8xx_lcdc_platform_data *fb_pdata =
dev_get_platdata(&device->dev); dev_get_platdata(&device->dev);
struct resource *lcdc_regs;
struct lcd_ctrl_config *lcd_cfg; struct lcd_ctrl_config *lcd_cfg;
struct fb_videomode *lcdc_info; struct fb_videomode *lcdc_info;
struct fb_info *da8xx_fb_info; struct fb_info *da8xx_fb_info;
...@@ -1346,8 +1349,7 @@ static int fb_probe(struct platform_device *device) ...@@ -1346,8 +1349,7 @@ static int fb_probe(struct platform_device *device)
if (lcdc_info == NULL) if (lcdc_info == NULL)
return -ENODEV; return -ENODEV;
lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0); da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0);
da8xx_fb_reg_base = devm_ioremap_resource(&device->dev, lcdc_regs);
if (IS_ERR(da8xx_fb_reg_base)) if (IS_ERR(da8xx_fb_reg_base))
return PTR_ERR(da8xx_fb_reg_base); return PTR_ERR(da8xx_fb_reg_base);
...@@ -1395,9 +1397,19 @@ static int fb_probe(struct platform_device *device) ...@@ -1395,9 +1397,19 @@ static int fb_probe(struct platform_device *device)
par->dev = &device->dev; par->dev = &device->dev;
par->lcdc_clk = tmp_lcdc_clk; par->lcdc_clk = tmp_lcdc_clk;
par->lcdc_clk_rate = clk_get_rate(par->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->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd");
par->panel_power_ctrl(1); 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); fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
...@@ -1411,7 +1423,7 @@ static int fb_probe(struct platform_device *device) ...@@ -1411,7 +1423,7 @@ static int fb_probe(struct platform_device *device)
par->vram_size = roundup(par->vram_size/8, ulcm); par->vram_size = roundup(par->vram_size/8, ulcm);
par->vram_size = par->vram_size * LCD_NUM_BUFFERS; par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
par->vram_virt = dma_alloc_coherent(par->dev, par->vram_virt = dmam_alloc_coherent(par->dev,
par->vram_size, par->vram_size,
&par->vram_phys, &par->vram_phys,
GFP_KERNEL | GFP_DMA); GFP_KERNEL | GFP_DMA);
...@@ -1432,20 +1444,20 @@ static int fb_probe(struct platform_device *device) ...@@ -1432,20 +1444,20 @@ static int fb_probe(struct platform_device *device)
da8xx_fb_fix.line_length - 1; da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */ /* allocate palette buffer */
par->v_palette_base = dma_alloc_coherent(par->dev, PALETTE_SIZE, par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE,
&par->p_palette_base, &par->p_palette_base,
GFP_KERNEL | GFP_DMA); GFP_KERNEL | GFP_DMA);
if (!par->v_palette_base) { if (!par->v_palette_base) {
dev_err(&device->dev, dev_err(&device->dev,
"GLCD: kmalloc for palette buffer failed\n"); "GLCD: kmalloc for palette buffer failed\n");
ret = -EINVAL; ret = -EINVAL;
goto err_release_fb_mem; goto err_release_fb;
} }
par->irq = platform_get_irq(device, 0); par->irq = platform_get_irq(device, 0);
if (par->irq < 0) { if (par->irq < 0) {
ret = -ENOENT; ret = -ENOENT;
goto err_release_pl_mem; goto err_release_fb;
} }
da8xx_fb_var.grayscale = da8xx_fb_var.grayscale =
...@@ -1463,7 +1475,7 @@ static int fb_probe(struct platform_device *device) ...@@ -1463,7 +1475,7 @@ static int fb_probe(struct platform_device *device)
ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
if (ret) if (ret)
goto err_release_pl_mem; goto err_release_fb;
da8xx_fb_info->cmap.len = par->palette_sz; da8xx_fb_info->cmap.len = par->palette_sz;
/* initialize var_screeninfo */ /* initialize var_screeninfo */
...@@ -1517,14 +1529,6 @@ static int fb_probe(struct platform_device *device) ...@@ -1517,14 +1529,6 @@ static int fb_probe(struct platform_device *device)
err_dealloc_cmap: err_dealloc_cmap:
fb_dealloc_cmap(&da8xx_fb_info->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: err_release_fb:
framebuffer_release(da8xx_fb_info); framebuffer_release(da8xx_fb_info);
...@@ -1603,10 +1607,14 @@ static int fb_suspend(struct device *dev) ...@@ -1603,10 +1607,14 @@ static int fb_suspend(struct device *dev)
{ {
struct fb_info *info = dev_get_drvdata(dev); struct fb_info *info = dev_get_drvdata(dev);
struct da8xx_fb_par *par = info->par; struct da8xx_fb_par *par = info->par;
int ret;
console_lock(); console_lock();
if (par->panel_power_ctrl) if (par->lcd_supply) {
par->panel_power_ctrl(0); ret = regulator_disable(par->lcd_supply);
if (ret)
return ret;
}
fb_set_suspend(info, 1); fb_set_suspend(info, 1);
lcd_disable_raster(DA8XX_FRAME_WAIT); lcd_disable_raster(DA8XX_FRAME_WAIT);
...@@ -1620,6 +1628,7 @@ static int fb_resume(struct device *dev) ...@@ -1620,6 +1628,7 @@ static int fb_resume(struct device *dev)
{ {
struct fb_info *info = dev_get_drvdata(dev); struct fb_info *info = dev_get_drvdata(dev);
struct da8xx_fb_par *par = info->par; struct da8xx_fb_par *par = info->par;
int ret;
console_lock(); console_lock();
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
...@@ -1627,8 +1636,11 @@ static int fb_resume(struct device *dev) ...@@ -1627,8 +1636,11 @@ static int fb_resume(struct device *dev)
if (par->blank == FB_BLANK_UNBLANK) { if (par->blank == FB_BLANK_UNBLANK) {
lcd_enable_raster(); lcd_enable_raster();
if (par->panel_power_ctrl) if (par->lcd_supply) {
par->panel_power_ctrl(1); ret = regulator_enable(par->lcd_supply);
if (ret)
return ret;
}
} }
fb_set_suspend(info, 0); fb_set_suspend(info, 0);
......
...@@ -32,7 +32,6 @@ struct da8xx_lcdc_platform_data { ...@@ -32,7 +32,6 @@ struct da8xx_lcdc_platform_data {
const char manu_name[10]; const char manu_name[10];
void *controller_data; void *controller_data;
const char type[25]; const char type[25];
void (*panel_power_ctrl)(int);
}; };
struct lcd_ctrl_config { struct lcd_ctrl_config {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment