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