summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2019-09-04 16:55:52 +0200
committerArnd Bergmann <arnd@arndb.de>2019-09-04 16:56:25 +0200
commit735f013110da10f56b7c8733cafac8d513ad407e (patch)
treef18bac66865fdc2175c5d20e38b993a0198db2b7
parentMerge tag 'imx-drivers-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff)
parentfbdev: da8xx: use resource management for dma (diff)
downloadlinux-735f013110da10f56b7c8733cafac8d513ad407e.tar.xz
linux-735f013110da10f56b7c8733cafac8d513ad407e.zip
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: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c90
-rw-r--r--drivers/video/fbdev/da8xx-fb.c118
-rw-r--r--include/video/da8xx-fb.h1
3 files changed, 131 insertions, 78 deletions
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 <linux/platform_data/ti-aemif.h>
#include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/uio_pruss.h>
+#include <linux/property.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/tps6507x.h>
#include <linux/regulator/fixed.h>
@@ -802,37 +803,79 @@ 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)
- return status;
-
- status = gpio_request(DA850_LCD_PWR_PIN, "lcd pwr");
- if (status < 0) {
- gpio_free(DA850_LCD_BL_PIN);
- return status;
- }
+ gpiod_add_lookup_tables(da850_lcd_gpio_lookups,
+ ARRAY_SIZE(da850_lcd_gpio_lookups));
- gpio_direction_output(DA850_LCD_BL_PIN, 0);
- gpio_direction_output(DA850_LCD_PWR_PIN, 0);
+ backlight = platform_device_register_full(&da850_lcd_backlight_info);
+ if (IS_ERR(backlight))
+ return PTR_ERR(backlight);
- /* Switch off panel power and backlight */
- da850_panel_power_ctrl(0);
-
- /* Switch on panel power and backlight */
- da850_panel_power_ctrl(1);
+ status = platform_device_register(&da850_lcd_supply_device);
+ if (status)
+ return status;
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 <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/console.h>
+#include <linux/regulator/consumer.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -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);
+ 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);
+ lcd_disable_raster(DA8XX_FRAME_WAIT);
+ lcdc_write(0, LCD_RASTER_CTRL_REG);
- /* disable DMA */
- lcdc_write(0, LCD_DMA_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);
+ 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 {