diff options
author | Andrey Konovalov <andrey.konovalov@linaro.org> | 2012-06-22 18:03:21 +0400 |
---|---|---|
committer | Andrey Konovalov <andrey.konovalov@linaro.org> | 2012-06-22 18:03:21 +0400 |
commit | 0a19683a881db6d6354920e097b628859cb8bb13 (patch) | |
tree | 209b7a2c26d92e7b40a7e838d2bb9fcb63999ffb | |
parent | 98d4f642616c9b2096e7bde229b8fb80e1cf5a4e (diff) | |
parent | 3ec1aabbd534a0497ea90b938bed4d4bc11ab8d4 (diff) |
Merge branch 'tracking-samslt-bl' into merge-linux-linaro
-rw-r--r-- | Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt | 36 | ||||
-rw-r--r-- | arch/arm/configs/android_origen_defconfig | 1 | ||||
-rw-r--r-- | arch/arm/configs/exynos4_defconfig | 1 | ||||
-rw-r--r-- | arch/arm/configs/ubuntu_origen_defconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/mach-origen.c | 29 | ||||
-rw-r--r-- | drivers/video/backlight/Kconfig | 7 | ||||
-rw-r--r-- | drivers/video/backlight/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/backlight/lcd_pwrctrl.c | 226 | ||||
-rw-r--r-- | include/video/lcd_pwrctrl.h | 24 | ||||
-rw-r--r-- | linaro/configs/origen.conf | 1 |
10 files changed, 304 insertions, 23 deletions
diff --git a/Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt b/Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt new file mode 100644 index 000000000000..22604a208c60 --- /dev/null +++ b/Documentation/devicetree/bindings/lcd/lcd-pwrctrl.txt @@ -0,0 +1,36 @@ +* Power controller for simple lcd panels + +Some LCD panels provide a simple control interface for the host system. The +control mechanism would include a nRESET line connected to a gpio of the host +system and a Vcc supply line which the host can optionally be controlled using +a voltage regulator. Such simple panels do not support serial command +interface (such as i2c or spi) or memory-mapped-io interface. + +Required properties: +- compatible: should be 'lcd-powercontrol' + +- lcd-reset-gpio: The GPIO number of the host system used to control the + nRESET line. The format of the gpio specifier depends on the gpio controller + of the host system. + +Optional properties: +- lcd-reset-active-high: When the nRESET line is asserted low, the lcd panel + is reset and stays in reset mode as long as the nRESET line is asserted low. + This is the default behaviour of most lcd panels. If a lcd panel requires the + nRESET line to be asserted high for panel reset, then this property is used. + Note: Some platforms might allow inverting the polarity of the gpio output + in the 'lcd-reset-gpio' gpio specifier. On such platforms, if the polarity + is used to control the output of the gpio, then this property should not be + used. + +- vcc-lcd-supply: phandle of the regulator that controls the vcc supply to + the lcd panel. + +Example: + + lcd_pwrctrl { + compatible = "lcd-powercontrol"; + lcd-reset-gpio = <&gpe0 4 1 0 0>; + lcd-reset-active-high; + lcd-vcc-supply = <®ulator7>; + }; diff --git a/arch/arm/configs/android_origen_defconfig b/arch/arm/configs/android_origen_defconfig index 29edf7692984..62f758a73d9d 100644 --- a/arch/arm/configs/android_origen_defconfig +++ b/arch/arm/configs/android_origen_defconfig @@ -130,6 +130,7 @@ CONFIG_FB_S3C=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=y +CONFIG_LCD_PWRCTRL=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig index 7a56a9c68d84..8f29c5e1a97a 100644 --- a/arch/arm/configs/exynos4_defconfig +++ b/arch/arm/configs/exynos4_defconfig @@ -92,6 +92,7 @@ CONFIG_FB_S3C=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=y +CONFIG_LCD_PWRCTRL=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y diff --git a/arch/arm/configs/ubuntu_origen_defconfig b/arch/arm/configs/ubuntu_origen_defconfig index fe9933bb604c..7496bc5dc128 100644 --- a/arch/arm/configs/ubuntu_origen_defconfig +++ b/arch/arm/configs/ubuntu_origen_defconfig @@ -133,6 +133,7 @@ CONFIG_FB_S3C=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=y +CONFIG_LCD_PWRCTRL=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_PWM=y CONFIG_FRAMEBUFFER_CONSOLE=y diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 6b7ed680c39b..06e2b7782e86 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -26,7 +26,7 @@ #include <asm/hardware/gic.h> #include <asm/mach-types.h> -#include <video/platform_lcd.h> +#include <video/lcd_pwrctrl.h> #include <plat-samsung/regs-serial.h> #include <plat-samsung/regs-fb-v4.h> @@ -130,7 +130,7 @@ static struct regulator_consumer_supply __initdata buck3_consumer[] = { REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */ }; static struct regulator_consumer_supply __initdata buck7_consumer[] = { - REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */ + REGULATOR_SUPPLY("vcc-lcd", "lcd-pwrctrl.0"), /* LCD */ }; static struct regulator_init_data __initdata max8997_ldo1_data = { @@ -385,7 +385,7 @@ static struct regulator_init_data __initdata max8997_buck7_data = { .name = "VDD_LCD_3.3V", .min_uV = 3300000, .max_uV = 3300000, - .boot_on = 1, + .boot_on = 0, .apply_uV = 1, .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { @@ -555,29 +555,12 @@ static struct platform_device origen_device_gpiokeys = { }, }; -static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power) -{ - int ret; - - if (power) - ret = gpio_request_one(EXYNOS4_GPE3(4), - GPIOF_OUT_INIT_HIGH, "GPE3_4"); - else - ret = gpio_request_one(EXYNOS4_GPE3(4), - GPIOF_OUT_INIT_LOW, "GPE3_4"); - - gpio_free(EXYNOS4_GPE3(4)); - - if (ret) - pr_err("failed to request gpio for LCD power: %d\n", ret); -} - -static struct plat_lcd_data origen_lcd_hv070wsa_data = { - .set_power = lcd_hv070wsa_set_power, +static struct lcd_pwrctrl_data origen_lcd_hv070wsa_data = { + .gpio = EXYNOS4_GPE3(4), }; static struct platform_device origen_lcd_hv070wsa = { - .name = "platform-lcd", + .name = "lcd-pwrctrl", .dev.parent = &s5p_device_fimd0.dev, .dev.platform_data = &origen_lcd_hv070wsa_data, }; diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 2979292650d6..588adc357583 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -86,6 +86,13 @@ config LCD_PLATFORM This driver provides a platform-device registered LCD power control interface. +config LCD_PWRCTRL + tristate "LCD panel power control" + help + Say y here, if you have a lcd panel that allows reset and vcc to be + controlled by the host system, and which does not use a serial command + interface (such as i2c or spi) or memory-mapped-io interface. + config LCD_TOSA tristate "Sharp SL-6000 LCD Driver" depends on I2C && SPI && MACH_TOSA diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index a2ac9cfbaf6b..915650e01038 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o obj-$(CONFIG_LCD_ILI9320) += ili9320.o obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o +obj-$(CONFIG_LCD_PWRCTRL) += lcd_pwrctrl.o obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o obj-$(CONFIG_LCD_TDO24M) += tdo24m.o obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o diff --git a/drivers/video/backlight/lcd_pwrctrl.c b/drivers/video/backlight/lcd_pwrctrl.c new file mode 100644 index 000000000000..917d842523c8 --- /dev/null +++ b/drivers/video/backlight/lcd_pwrctrl.c @@ -0,0 +1,226 @@ +/* + * Simple lcd panel power control driver. + * + * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. + * Copyright (c) 2011-2012 Linaro Ltd. + * + * This driver is for controlling power for raster type lcd panels that requires + * its nRESET interface line to be connected and controlled by a GPIO of the + * host system and the Vcc line controlled by a voltage regulator. This + * excludes support for lcd panels that use a serial command interface or direct + * memory mapped IO interface. + * + * The nRESET interface line of the panel should be connected to a gpio of the + * host system. The Vcc pin is controlled using a external volatage regulator. + * Panel backlight is not controlled by this driver. + * + * This driver is derived from platform-lcd.c which was written by + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/lcd.h> +#include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/regulator/consumer.h> +#include <video/lcd_pwrctrl.h> + +struct lcd_pwrctrl { + struct device *dev; + struct lcd_device *lcd; + struct lcd_pwrctrl_data *pdata; + struct regulator *regulator; + unsigned int power; + bool suspended; + bool pwr_en; +}; + +static int lcd_pwrctrl_get_power(struct lcd_device *lcd) +{ + struct lcd_pwrctrl *lp = lcd_get_data(lcd); + return lp->power; +} + +static int lcd_pwrctrl_set_power(struct lcd_device *lcd, int power) +{ + struct lcd_pwrctrl *lp = lcd_get_data(lcd); + struct lcd_pwrctrl_data *pd = lp->pdata; + bool lcd_enable; + int lcd_reset, ret = 0; + + lcd_enable = (power == FB_BLANK_POWERDOWN || lp->suspended) ? 0 : 1; + lcd_reset = (pd->invert) ? !lcd_enable : lcd_enable; + + if (lp->pwr_en == lcd_enable) + return 0; + + if (!IS_ERR_OR_NULL(lp->regulator)) { + if (lcd_enable) { + if (regulator_enable(lp->regulator)) { + dev_info(lp->dev, "regulator enable failed\n"); + ret = -EPERM; + } + } else { + if (regulator_disable(lp->regulator)) { + dev_info(lp->dev, "regulator disable failed\n"); + ret = -EPERM; + } + } + } + + gpio_direction_output(lp->pdata->gpio, lcd_reset); + lp->power = power; + lp->pwr_en = lcd_enable; + return ret; +} + +static int lcd_pwrctrl_check_fb(struct lcd_device *lcd, struct fb_info *info) +{ + struct lcd_pwrctrl *lp = lcd_get_data(lcd); + return lp->dev->parent == info->device; +} + +static struct lcd_ops lcd_pwrctrl_ops = { + .get_power = lcd_pwrctrl_get_power, + .set_power = lcd_pwrctrl_set_power, + .check_fb = lcd_pwrctrl_check_fb, +}; + +#ifdef CONFIG_OF +static void __devinit lcd_pwrctrl_parse_dt(struct device *dev, + struct lcd_pwrctrl_data *pdata) +{ + struct device_node *np = dev->of_node; + + pdata->gpio = of_get_named_gpio(np, "lcd-reset-gpio", 0); + if (of_get_property(np, "lcd-reset-active-high", NULL)) + pdata->invert = true; +} +#endif + +static int __devinit lcd_pwrctrl_probe(struct platform_device *pdev) +{ + struct lcd_pwrctrl *lp; + struct lcd_pwrctrl_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + int err; + +#ifdef CONFIG_OF + if (dev->of_node) { + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "memory allocation for pdata failed\n"); + return -ENOMEM; + } + lcd_pwrctrl_parse_dt(dev, pdata); + } +#endif + + if (!pdata) { + dev_err(dev, "platform data not available\n"); + return -EINVAL; + } + + lp = devm_kzalloc(dev, sizeof(struct lcd_pwrctrl), GFP_KERNEL); + if (!lp) { + dev_err(dev, "memory allocation failed for private data\n"); + return -ENOMEM; + } + + err = gpio_request(pdata->gpio, "LCD-nRESET"); + if (err) { + dev_err(dev, "gpio [%d] request failed\n", pdata->gpio); + return err; + } + + /* + * If power to lcd and/or lcd interface is controlled using a regulator, + * get the handle to the regulator for later use during power switching. + */ + lp->regulator = devm_regulator_get(dev, "vcc-lcd"); + if (IS_ERR(lp->regulator)) + dev_info(dev, "could not find regulator\n"); + + lp->dev = dev; + lp->pdata = pdata; + lp->lcd = lcd_device_register(dev_name(dev), dev, lp, &lcd_pwrctrl_ops); + if (IS_ERR(lp->lcd)) { + dev_err(dev, "cannot register lcd device\n"); + gpio_free(pdata->gpio); + return PTR_ERR(lp->lcd); + } + + platform_set_drvdata(pdev, lp); + lcd_pwrctrl_set_power(lp->lcd, FB_BLANK_NORMAL); + return 0; +} + +static int __devexit lcd_pwrctrl_remove(struct platform_device *pdev) +{ + struct lcd_pwrctrl *lp = platform_get_drvdata(pdev); + lcd_device_unregister(lp->lcd); + gpio_free(lp->pdata->gpio); + return 0; +} + +#ifdef CONFIG_PM +static int lcd_pwrctrl_suspend(struct device *dev) +{ + struct lcd_pwrctrl *lp = dev_get_drvdata(dev); + + lp->suspended = true; + lcd_pwrctrl_set_power(lp->lcd, FB_BLANK_POWERDOWN); + return 0; +} + +static int lcd_pwrctrl_resume(struct device *dev) +{ + struct lcd_pwrctrl *lp = dev_get_drvdata(dev); + + lp->suspended = false; + lcd_pwrctrl_set_power(lp->lcd, FB_BLANK_UNBLANK); + return 0; +} + +static const struct dev_pm_ops lcd_pwrctrl_dev_pm_ops = { + .suspend = lcd_pwrctrl_suspend, + .resume = lcd_pwrctrl_resume, +}; + +#define LCD_PWRCTRL_DEV_PM_OPS (&lcd_pwrctrl_dev_pm_ops) +#else +#define LCD_PWRCTRL_DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + +#ifdef CONFIG_OF +static const struct of_device_id lcd_pwrctrl_match[] = { + { .compatible = "lcd-powercontrol", }, + {}, +}; +MODULE_DEVICE_TABLE(of, lcd_pwrctrl_match); +#endif + +static struct platform_driver lcd_pwrctrl_driver = { + .driver = { + .name = "lcd-pwrctrl", + .owner = THIS_MODULE, + .pm = LCD_PWRCTRL_DEV_PM_OPS, + .of_match_table = of_match_ptr(lcd_pwrctrl_match), + }, + .probe = lcd_pwrctrl_probe, + .remove = lcd_pwrctrl_remove, +}; + +module_platform_driver(lcd_pwrctrl_driver); + +MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:lcd-pwrctrl"); diff --git a/include/video/lcd_pwrctrl.h b/include/video/lcd_pwrctrl.h new file mode 100644 index 000000000000..924bfd222340 --- /dev/null +++ b/include/video/lcd_pwrctrl.h @@ -0,0 +1,24 @@ +/* + * Simple lcd panel power control driver. + * + * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd. + * Copyright (c) 2011-2012 Linaro Ltd. + * + * This driver is derived from platform-lcd.h which was written by + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +/** + * struct lcd_pwrctrl_data - platform data for lcd_pwrctrl driver. + * @gpio: GPIO number of the host system that connects to nRESET line. + * @invert: True, if output of gpio connected to nRESET should be inverted. + */ +struct lcd_pwrctrl_data { + int gpio; + bool invert; +}; diff --git a/linaro/configs/origen.conf b/linaro/configs/origen.conf index 3a4a767edb32..f0935e6d59f2 100644 --- a/linaro/configs/origen.conf +++ b/linaro/configs/origen.conf @@ -71,6 +71,7 @@ CONFIG_FB_S3C=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_PLATFORM=y +CONFIG_LCD_PWRCTRL=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_PWM=y CONFIG_LOGO=y |