linux/drivers/video/backlight/l4f00242t03.c
<<
>>
Prefs
   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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15
  16#include <linux/device.h>
  17#include <linux/kernel.h>
  18#include <linux/delay.h>
  19#include <linux/module.h>
  20#include <linux/gpio.h>
  21#include <linux/lcd.h>
  22#include <linux/slab.h>
  23#include <linux/regulator/consumer.h>
  24
  25#include <linux/spi/spi.h>
  26#include <linux/spi/l4f00242t03.h>
  27
  28struct l4f00242t03_priv {
  29        struct spi_device       *spi;
  30        struct lcd_device       *ld;
  31        int lcd_state;
  32        struct regulator *io_reg;
  33        struct regulator *core_reg;
  34};
  35
  36static void l4f00242t03_reset(unsigned int gpio)
  37{
  38        pr_debug("l4f00242t03_reset.\n");
  39        gpio_set_value(gpio, 1);
  40        mdelay(100);
  41        gpio_set_value(gpio, 0);
  42        mdelay(10);     /* tRES >= 100us */
  43        gpio_set_value(gpio, 1);
  44        mdelay(20);
  45}
  46
  47#define param(x) ((x) | 0x100)
  48
  49static void l4f00242t03_lcd_init(struct spi_device *spi)
  50{
  51        struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
  52        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
  53        const u16 cmd[] = { 0x36, param(0), 0x3A, param(0x60) };
  54        int ret;
  55
  56        dev_dbg(&spi->dev, "initializing LCD\n");
  57
  58        ret = regulator_set_voltage(priv->io_reg, 1800000, 1800000);
  59        if (ret) {
  60                dev_err(&spi->dev, "failed to set the IO regulator voltage.\n");
  61                return;
  62        }
  63        ret = regulator_enable(priv->io_reg);
  64        if (ret) {
  65                dev_err(&spi->dev, "failed to enable the IO regulator.\n");
  66                return;
  67        }
  68
  69        ret = regulator_set_voltage(priv->core_reg, 2800000, 2800000);
  70        if (ret) {
  71                dev_err(&spi->dev, "failed to set the core regulator voltage.\n");
  72                regulator_disable(priv->io_reg);
  73                return;
  74        }
  75        ret = regulator_enable(priv->core_reg);
  76        if (ret) {
  77                dev_err(&spi->dev, "failed to enable the core regulator.\n");
  78                regulator_disable(priv->io_reg);
  79                return;
  80        }
  81
  82        l4f00242t03_reset(pdata->reset_gpio);
  83
  84        gpio_set_value(pdata->data_enable_gpio, 1);
  85        msleep(60);
  86        spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16));
  87}
  88
  89static void l4f00242t03_lcd_powerdown(struct spi_device *spi)
  90{
  91        struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
  92        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
  93
  94        dev_dbg(&spi->dev, "Powering down LCD\n");
  95
  96        gpio_set_value(pdata->data_enable_gpio, 0);
  97
  98        regulator_disable(priv->io_reg);
  99        regulator_disable(priv->core_reg);
 100}
 101
 102static int l4f00242t03_lcd_power_get(struct lcd_device *ld)
 103{
 104        struct l4f00242t03_priv *priv = lcd_get_data(ld);
 105
 106        return priv->lcd_state;
 107}
 108
 109static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power)
 110{
 111        struct l4f00242t03_priv *priv = lcd_get_data(ld);
 112        struct spi_device *spi = priv->spi;
 113
 114        const u16 slpout = 0x11;
 115        const u16 dison = 0x29;
 116
 117        const u16 slpin = 0x10;
 118        const u16 disoff = 0x28;
 119
 120        if (power <= FB_BLANK_NORMAL) {
 121                if (priv->lcd_state <= FB_BLANK_NORMAL) {
 122                        /* Do nothing, the LCD is running */
 123                } else if (priv->lcd_state < FB_BLANK_POWERDOWN) {
 124                        dev_dbg(&spi->dev, "Resuming LCD\n");
 125
 126                        spi_write(spi, (const u8 *)&slpout, sizeof(u16));
 127                        msleep(60);
 128                        spi_write(spi, (const u8 *)&dison, sizeof(u16));
 129                } else {
 130                        /* priv->lcd_state == FB_BLANK_POWERDOWN */
 131                        l4f00242t03_lcd_init(spi);
 132                        priv->lcd_state = FB_BLANK_VSYNC_SUSPEND;
 133                        l4f00242t03_lcd_power_set(priv->ld, power);
 134                }
 135        } else if (power < FB_BLANK_POWERDOWN) {
 136                if (priv->lcd_state <= FB_BLANK_NORMAL) {
 137                        /* Send the display in standby */
 138                        dev_dbg(&spi->dev, "Standby the LCD\n");
 139
 140                        spi_write(spi, (const u8 *)&disoff, sizeof(u16));
 141                        msleep(60);
 142                        spi_write(spi, (const u8 *)&slpin, sizeof(u16));
 143                } else if (priv->lcd_state < FB_BLANK_POWERDOWN) {
 144                        /* Do nothing, the LCD is already in standby */
 145                } else {
 146                        /* priv->lcd_state == FB_BLANK_POWERDOWN */
 147                        l4f00242t03_lcd_init(spi);
 148                        priv->lcd_state = FB_BLANK_UNBLANK;
 149                        l4f00242t03_lcd_power_set(ld, power);
 150                }
 151        } else {
 152                /* power == FB_BLANK_POWERDOWN */
 153                if (priv->lcd_state != FB_BLANK_POWERDOWN) {
 154                        /* Clear the screen before shutting down */
 155                        spi_write(spi, (const u8 *)&disoff, sizeof(u16));
 156                        msleep(60);
 157                        l4f00242t03_lcd_powerdown(spi);
 158                }
 159        }
 160
 161        priv->lcd_state = power;
 162
 163        return 0;
 164}
 165
 166static struct lcd_ops l4f_ops = {
 167        .set_power      = l4f00242t03_lcd_power_set,
 168        .get_power      = l4f00242t03_lcd_power_get,
 169};
 170
 171static int l4f00242t03_probe(struct spi_device *spi)
 172{
 173        struct l4f00242t03_priv *priv;
 174        struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
 175        int ret;
 176
 177        if (pdata == NULL) {
 178                dev_err(&spi->dev, "Uninitialized platform data.\n");
 179                return -EINVAL;
 180        }
 181
 182        priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv),
 183                                GFP_KERNEL);
 184
 185        if (priv == NULL) {
 186                dev_err(&spi->dev, "No memory for this device.\n");
 187                return -ENOMEM;
 188        }
 189
 190        spi_set_drvdata(spi, priv);
 191        spi->bits_per_word = 9;
 192        spi_setup(spi);
 193
 194        priv->spi = spi;
 195
 196        ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio,
 197                        GPIOF_OUT_INIT_HIGH, "lcd l4f00242t03 reset");
 198        if (ret) {
 199                dev_err(&spi->dev,
 200                        "Unable to get the lcd l4f00242t03 reset gpio.\n");
 201                return ret;
 202        }
 203
 204        ret = devm_gpio_request_one(&spi->dev, pdata->data_enable_gpio,
 205                        GPIOF_OUT_INIT_LOW, "lcd l4f00242t03 data enable");
 206        if (ret) {
 207                dev_err(&spi->dev,
 208                        "Unable to get the lcd l4f00242t03 data en gpio.\n");
 209                return ret;
 210        }
 211
 212        priv->io_reg = devm_regulator_get(&spi->dev, "vdd");
 213        if (IS_ERR(priv->io_reg)) {
 214                dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
 215                       __func__);
 216                return PTR_ERR(priv->io_reg);
 217        }
 218
 219        priv->core_reg = devm_regulator_get(&spi->dev, "vcore");
 220        if (IS_ERR(priv->core_reg)) {
 221                dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
 222                       __func__);
 223                return PTR_ERR(priv->core_reg);
 224        }
 225
 226        priv->ld = lcd_device_register("l4f00242t03",
 227                                        &spi->dev, priv, &l4f_ops);
 228        if (IS_ERR(priv->ld))
 229                return PTR_ERR(priv->ld);
 230
 231        /* Init the LCD */
 232        l4f00242t03_lcd_init(spi);
 233        priv->lcd_state = FB_BLANK_VSYNC_SUSPEND;
 234        l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_UNBLANK);
 235
 236        dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n");
 237
 238        return 0;
 239}
 240
 241static int l4f00242t03_remove(struct spi_device *spi)
 242{
 243        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
 244
 245        l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN);
 246        lcd_device_unregister(priv->ld);
 247        spi_set_drvdata(spi, NULL);
 248
 249        return 0;
 250}
 251
 252static void l4f00242t03_shutdown(struct spi_device *spi)
 253{
 254        struct l4f00242t03_priv *priv = spi_get_drvdata(spi);
 255
 256        if (priv)
 257                l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN);
 258
 259}
 260
 261static struct spi_driver l4f00242t03_driver = {
 262        .driver = {
 263                .name   = "l4f00242t03",
 264                .owner  = THIS_MODULE,
 265        },
 266        .probe          = l4f00242t03_probe,
 267        .remove         = l4f00242t03_remove,
 268        .shutdown       = l4f00242t03_shutdown,
 269};
 270
 271module_spi_driver(l4f00242t03_driver);
 272
 273MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
 274MODULE_DESCRIPTION("EPSON L4F00242T03 LCD");
 275MODULE_LICENSE("GPL v2");
 276