diff options
| -rw-r--r-- | drivers/video/backlight/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/video/backlight/Makefile | 1 | ||||
| -rw-r--r-- | drivers/video/backlight/l4f00242t03.c | 256 | ||||
| -rw-r--r-- | include/linux/spi/l4f00242t03.h | 31 |
4 files changed, 295 insertions, 0 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 0c77fc610212..c025c84601b0 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
| @@ -31,6 +31,13 @@ config LCD_CORGI | |||
| 31 | Say y here to support the LCD panels usually found on SHARP | 31 | Say y here to support the LCD panels usually found on SHARP |
| 32 | corgi (C7x0) and spitz (Cxx00) models. | 32 | corgi (C7x0) and spitz (Cxx00) models. |
| 33 | 33 | ||
| 34 | config LCD_L4F00242T03 | ||
| 35 | tristate "Epson L4F00242T03 LCD" | ||
| 36 | depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO | ||
| 37 | help | ||
| 38 | SPI driver for Epson L4F00242T03. This provides basic support | ||
| 39 | for init and powering the LCD up/down through a sysfs interface. | ||
| 40 | |||
| 34 | config LCD_LMS283GF05 | 41 | config LCD_LMS283GF05 |
| 35 | tristate "Samsung LMS283GF05 LCD" | 42 | tristate "Samsung LMS283GF05 LCD" |
| 36 | depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO | 43 | depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO |
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 6c704d41462d..09d1f14d6257 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o | 3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o |
| 4 | obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o | 4 | obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o |
| 5 | obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o | 5 | obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o |
| 6 | obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o | ||
| 6 | obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o | 7 | obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o |
| 7 | obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o | 8 | obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o |
| 8 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o | 9 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o |
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c new file mode 100644 index 000000000000..42d061e1403b --- /dev/null +++ b/drivers/video/backlight/l4f00242t03.c | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | /* | ||
| 2 | * l4f00242t03.c -- support for Epson L4F00242T03 LCD | ||
| 3 | * | ||
| 4 | * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> | ||
| 7 | * Inspired by Marek Vasut work in l4f00242t03.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/lcd.h> | ||
| 19 | #include <linux/regulator/consumer.h> | ||
| 20 | |||
| 21 | #include <linux/spi/spi.h> | ||
| 22 | #include <linux/spi/l4f00242t03.h> | ||
| 23 | |||
| 24 | struct l4f00242t03_priv { | ||
| 25 | struct spi_device *spi; | ||
| 26 | struct lcd_device *ld; | ||
| 27 | int lcd_on:1; | ||
| 28 | struct regulator *io_reg; | ||
| 29 | struct regulator *core_reg; | ||
| 30 | }; | ||
| 31 | |||
| 32 | |||
| 33 | static void l4f00242t03_reset(unsigned int gpio) | ||
| 34 | { | ||
| 35 | pr_debug("l4f00242t03_reset.\n"); | ||
| 36 | gpio_set_value(gpio, 1); | ||
| 37 | mdelay(100); | ||
| 38 | gpio_set_value(gpio, 0); | ||
| 39 | mdelay(10); /* tRES >= 100us */ | ||
| 40 | gpio_set_value(gpio, 1); | ||
| 41 | mdelay(20); | ||
| 42 | } | ||
| 43 | |||
| 44 | #define param(x) ((x) | 0x100) | ||
| 45 | |||
| 46 | static void l4f00242t03_lcd_init(struct spi_device *spi) | ||
| 47 | { | ||
| 48 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; | ||
| 49 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | ||
| 50 | const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) }; | ||
| 51 | |||
| 52 | dev_dbg(&spi->dev, "initializing LCD\n"); | ||
| 53 | |||
| 54 | if (priv->io_reg) { | ||
| 55 | regulator_set_voltage(priv->io_reg, 1800000, 1800000); | ||
| 56 | regulator_enable(priv->io_reg); | ||
| 57 | } | ||
| 58 | |||
| 59 | if (priv->core_reg) { | ||
| 60 | regulator_set_voltage(priv->core_reg, 2800000, 2800000); | ||
| 61 | regulator_enable(priv->core_reg); | ||
| 62 | } | ||
| 63 | |||
| 64 | gpio_set_value(pdata->data_enable_gpio, 1); | ||
| 65 | msleep(60); | ||
| 66 | spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16)); | ||
| 67 | } | ||
| 68 | |||
| 69 | static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) | ||
| 70 | { | ||
| 71 | struct l4f00242t03_priv *priv = lcd_get_data(ld); | ||
| 72 | struct spi_device *spi = priv->spi; | ||
| 73 | |||
| 74 | const u16 slpout = 0x11; | ||
| 75 | const u16 dison = 0x29; | ||
| 76 | |||
| 77 | const u16 slpin = 0x10; | ||
| 78 | const u16 disoff = 0x28; | ||
| 79 | |||
| 80 | if (power) { | ||
| 81 | if (priv->lcd_on) | ||
| 82 | return 0; | ||
| 83 | |||
| 84 | dev_dbg(&spi->dev, "turning on LCD\n"); | ||
| 85 | |||
| 86 | spi_write(spi, (const u8 *)&slpout, sizeof(u16)); | ||
| 87 | msleep(60); | ||
| 88 | spi_write(spi, (const u8 *)&dison, sizeof(u16)); | ||
| 89 | |||
| 90 | priv->lcd_on = 1; | ||
| 91 | } else { | ||
| 92 | if (!priv->lcd_on) | ||
| 93 | return 0; | ||
| 94 | |||
| 95 | dev_dbg(&spi->dev, "turning off LCD\n"); | ||
| 96 | |||
| 97 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); | ||
| 98 | msleep(60); | ||
| 99 | spi_write(spi, (const u8 *)&slpin, sizeof(u16)); | ||
| 100 | |||
| 101 | priv->lcd_on = 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | static struct lcd_ops l4f_ops = { | ||
| 108 | .set_power = l4f00242t03_lcd_power_set, | ||
| 109 | .get_power = NULL, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static int __devinit l4f00242t03_probe(struct spi_device *spi) | ||
| 113 | { | ||
| 114 | struct l4f00242t03_priv *priv; | ||
| 115 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; | ||
| 116 | int ret; | ||
| 117 | |||
| 118 | if (pdata == NULL) { | ||
| 119 | dev_err(&spi->dev, "Uninitialized platform data.\n"); | ||
| 120 | return -EINVAL; | ||
| 121 | } | ||
| 122 | |||
| 123 | priv = kzalloc(sizeof(struct l4f00242t03_priv), GFP_KERNEL); | ||
| 124 | |||
| 125 | if (priv == NULL) { | ||
| 126 | dev_err(&spi->dev, "No memory for this device.\n"); | ||
| 127 | ret = -ENOMEM; | ||
| 128 | goto err; | ||
| 129 | } | ||
| 130 | |||
| 131 | dev_set_drvdata(&spi->dev, priv); | ||
| 132 | spi->bits_per_word = 9; | ||
| 133 | spi_setup(spi); | ||
| 134 | |||
| 135 | priv->spi = spi; | ||
| 136 | |||
| 137 | ret = gpio_request(pdata->reset_gpio, "lcd l4f00242t03 reset"); | ||
| 138 | if (ret) { | ||
| 139 | dev_err(&spi->dev, | ||
| 140 | "Unable to get the lcd l4f00242t03 reset gpio.\n"); | ||
| 141 | return ret; | ||
| 142 | } | ||
| 143 | |||
| 144 | ret = gpio_direction_output(pdata->reset_gpio, 1); | ||
| 145 | if (ret) | ||
| 146 | goto err2; | ||
| 147 | |||
| 148 | ret = gpio_request(pdata->data_enable_gpio, | ||
| 149 | "lcd l4f00242t03 data enable"); | ||
| 150 | if (ret) { | ||
| 151 | dev_err(&spi->dev, | ||
| 152 | "Unable to get the lcd l4f00242t03 data en gpio.\n"); | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | |||
| 156 | ret = gpio_direction_output(pdata->data_enable_gpio, 0); | ||
| 157 | if (ret) | ||
| 158 | goto err3; | ||
| 159 | |||
| 160 | if (pdata->io_supply) { | ||
| 161 | priv->io_reg = regulator_get(NULL, pdata->io_supply); | ||
| 162 | |||
| 163 | if (IS_ERR(priv->io_reg)) { | ||
| 164 | pr_err("%s: Unable to get the IO regulator\n", | ||
| 165 | __func__); | ||
| 166 | goto err3; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | if (pdata->core_supply) { | ||
| 171 | priv->core_reg = regulator_get(NULL, pdata->core_supply); | ||
| 172 | |||
| 173 | if (IS_ERR(priv->core_reg)) { | ||
| 174 | pr_err("%s: Unable to get the core regulator\n", | ||
| 175 | __func__); | ||
| 176 | goto err4; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | priv->ld = lcd_device_register("l4f00242t03", | ||
| 181 | &spi->dev, priv, &l4f_ops); | ||
| 182 | if (IS_ERR(priv->ld)) { | ||
| 183 | ret = PTR_ERR(priv->ld); | ||
| 184 | goto err5; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* Init the LCD */ | ||
| 188 | l4f00242t03_reset(pdata->reset_gpio); | ||
| 189 | l4f00242t03_lcd_init(spi); | ||
| 190 | l4f00242t03_lcd_power_set(priv->ld, 1); | ||
| 191 | |||
| 192 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); | ||
| 193 | |||
| 194 | return 0; | ||
| 195 | |||
| 196 | err5: | ||
| 197 | if (priv->core_reg) | ||
| 198 | regulator_put(priv->core_reg); | ||
| 199 | err4: | ||
| 200 | if (priv->io_reg) | ||
| 201 | regulator_put(priv->io_reg); | ||
| 202 | err3: | ||
| 203 | gpio_free(pdata->data_enable_gpio); | ||
| 204 | err2: | ||
| 205 | gpio_free(pdata->reset_gpio); | ||
| 206 | err: | ||
| 207 | kfree(priv); | ||
| 208 | |||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int __devexit l4f00242t03_remove(struct spi_device *spi) | ||
| 213 | { | ||
| 214 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | ||
| 215 | struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; | ||
| 216 | |||
| 217 | l4f00242t03_lcd_power_set(priv->ld, 0); | ||
| 218 | lcd_device_unregister(priv->ld); | ||
| 219 | |||
| 220 | gpio_free(pdata->data_enable_gpio); | ||
| 221 | gpio_free(pdata->reset_gpio); | ||
| 222 | |||
| 223 | if (priv->io_reg) | ||
| 224 | regulator_put(priv->core_reg); | ||
| 225 | if (priv->core_reg) | ||
| 226 | regulator_put(priv->io_reg); | ||
| 227 | |||
| 228 | kfree(priv); | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | static struct spi_driver l4f00242t03_driver = { | ||
| 234 | .driver = { | ||
| 235 | .name = "l4f00242t03", | ||
| 236 | .owner = THIS_MODULE, | ||
| 237 | }, | ||
| 238 | .probe = l4f00242t03_probe, | ||
| 239 | .remove = __devexit_p(l4f00242t03_remove), | ||
| 240 | }; | ||
| 241 | |||
| 242 | static __init int l4f00242t03_init(void) | ||
| 243 | { | ||
| 244 | return spi_register_driver(&l4f00242t03_driver); | ||
| 245 | } | ||
| 246 | |||
| 247 | static __exit void l4f00242t03_exit(void) | ||
| 248 | { | ||
| 249 | spi_unregister_driver(&l4f00242t03_driver); | ||
| 250 | } | ||
| 251 | |||
| 252 | module_init(l4f00242t03_init); | ||
| 253 | module_exit(l4f00242t03_exit); | ||
| 254 | |||
| 255 | MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>"); | ||
| 256 | MODULE_DESCRIPTION("EPSON L4F00242T03 LCD"); | ||
diff --git a/include/linux/spi/l4f00242t03.h b/include/linux/spi/l4f00242t03.h new file mode 100644 index 000000000000..aee1dbda4edc --- /dev/null +++ b/include/linux/spi/l4f00242t03.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* | ||
| 2 | * l4f00242t03.h -- Platform glue for Epson L4F00242T03 LCD | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> | ||
| 5 | * Based on Marek Vasut work in lms283gf05.h | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _INCLUDE_LINUX_SPI_L4F00242T03_H_ | ||
| 22 | #define _INCLUDE_LINUX_SPI_L4F00242T03_H_ | ||
| 23 | |||
| 24 | struct l4f00242t03_pdata { | ||
| 25 | unsigned int reset_gpio; | ||
| 26 | unsigned int data_enable_gpio; | ||
| 27 | const char *io_supply; /* will be set to 1.8 V */ | ||
| 28 | const char *core_supply; /* will be set to 2.8 V */ | ||
| 29 | }; | ||
| 30 | |||
| 31 | #endif /* _INCLUDE_LINUX_SPI_L4F00242T03_H_ */ | ||
