linux/drivers/video/backlight/vgg2432a4.c
<<
>>
Prefs
   1/* drivers/video/backlight/vgg2432a4.c
   2 *
   3 * VGG2432A4 (ILI9320) LCD controller driver.
   4 *
   5 * Copyright 2007 Simtec Electronics
   6 *      http://armlinux.simtec.co.uk/
   7 *      Ben Dooks <ben@simtec.co.uk>
   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/delay.h>
  15#include <linux/err.h>
  16#include <linux/fb.h>
  17#include <linux/init.h>
  18#include <linux/lcd.h>
  19#include <linux/module.h>
  20
  21#include <linux/spi/spi.h>
  22
  23#include <video/ili9320.h>
  24
  25#include "ili9320.h"
  26
  27/* Device initialisation sequences */
  28
  29static const struct ili9320_reg vgg_init1[] = {
  30        {
  31                .address = ILI9320_POWER1,
  32                .value   = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
  33        }, {
  34                .address = ILI9320_POWER2,
  35                .value   = (ILI9320_POWER2_VC(7) |
  36                            ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)),
  37        }, {
  38                .address = ILI9320_POWER3,
  39                .value   = ILI9320_POWER3_VRH(0),
  40        }, {
  41                .address = ILI9320_POWER4,
  42                .value   = ILI9320_POWER4_VREOUT(0),
  43        },
  44};
  45
  46static const struct ili9320_reg vgg_init2[] = {
  47        {
  48                .address = ILI9320_POWER1,
  49                .value   = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
  50                            ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP),
  51        }, {
  52                .address = ILI9320_POWER2,
  53                .value   = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3),
  54        }
  55};
  56
  57static const struct ili9320_reg vgg_gamma[] = {
  58        {
  59                .address = ILI9320_GAMMA1,
  60                .value   = 0x0000,
  61        }, {
  62                .address = ILI9320_GAMMA2,
  63                .value   = 0x0505,
  64        }, {
  65                .address = ILI9320_GAMMA3,
  66                .value   = 0x0004,
  67        }, {
  68                .address = ILI9320_GAMMA4,
  69                .value   = 0x0006,
  70        }, {
  71                .address = ILI9320_GAMMA5,
  72                .value   = 0x0707,
  73        }, {
  74                .address = ILI9320_GAMMA6,
  75                .value   = 0x0105,
  76        }, {
  77                .address = ILI9320_GAMMA7,
  78                .value   = 0x0002,
  79        }, {
  80                .address = ILI9320_GAMMA8,
  81                .value   = 0x0707,
  82        }, {
  83                .address = ILI9320_GAMMA9,
  84                .value   = 0x0704,
  85        }, {
  86                .address = ILI9320_GAMMA10,
  87                .value   = 0x807,
  88        }
  89
  90};
  91
  92static const struct ili9320_reg vgg_init0[] = {
  93        [0]     = {
  94                /* set direction and scan mode gate */
  95                .address = ILI9320_DRIVER,
  96                .value   = ILI9320_DRIVER_SS,
  97        }, {
  98                .address = ILI9320_DRIVEWAVE,
  99                .value   = (ILI9320_DRIVEWAVE_MUSTSET |
 100                            ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC),
 101        }, {
 102                .address = ILI9320_ENTRYMODE,
 103                .value   = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
 104        }, {
 105                .address = ILI9320_RESIZING,
 106                .value   = 0x0,
 107        },
 108};
 109
 110
 111static int vgg2432a4_lcd_init(struct ili9320 *lcd,
 112                              struct ili9320_platdata *cfg)
 113{
 114        unsigned int addr;
 115        int ret;
 116
 117        /* Set VCore before anything else (VGG243237-6UFLWA) */
 118        ret = ili9320_write(lcd, 0x00e5, 0x8000);
 119        if (ret)
 120                goto err_initial;
 121
 122        /* Start the oscillator up before we can do anything else. */
 123        ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
 124        if (ret)
 125                goto err_initial;
 126
 127        /* must wait at-lesat 10ms after starting */
 128        mdelay(15);
 129
 130        ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0));
 131        if (ret != 0)
 132                goto err_initial;
 133
 134        ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2);
 135        ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3);
 136        ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4);
 137
 138        ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1);
 139        ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0);
 140        ili9320_write(lcd, ILI9320_RGB_IF2, cfg->rgb_if2);
 141
 142        ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1));
 143        if (ret != 0)
 144                goto err_vgg;
 145
 146        mdelay(300);
 147
 148        ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2));
 149        if (ret != 0)
 150                goto err_vgg2;
 151
 152        mdelay(100);
 153
 154        ili9320_write(lcd, ILI9320_POWER3, 0x13c);
 155
 156        mdelay(100);
 157
 158        ili9320_write(lcd, ILI9320_POWER4, 0x1c00);
 159        ili9320_write(lcd, ILI9320_POWER7, 0x000e);
 160
 161        mdelay(100);
 162
 163        ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00);
 164        ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00);
 165
 166        ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma));
 167        if (ret != 0)
 168                goto err_vgg3;
 169
 170        ili9320_write(lcd, ILI9320_HORIZ_START, 0x0);
 171        ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1);
 172        ili9320_write(lcd, ILI9320_VERT_START, 0x0);
 173        ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1);
 174
 175        ili9320_write(lcd, ILI9320_DRIVER2,
 176                      ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D));
 177
 178        ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1);
 179        ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00);
 180
 181        for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END;
 182             addr++) {
 183                ili9320_write(lcd, addr, 0x0);
 184        }
 185
 186        ili9320_write(lcd, ILI9320_INTERFACE1, 0x10);
 187        ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2);
 188        ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3);
 189        ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4);
 190        ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5);
 191        ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6);
 192
 193        lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE |
 194                         ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE |
 195                         0x40);
 196
 197        ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
 198
 199        return 0;
 200
 201 err_vgg3:
 202 err_vgg2:
 203 err_vgg:
 204 err_initial:
 205        return ret;
 206}
 207
 208#ifdef CONFIG_PM_SLEEP
 209static int vgg2432a4_suspend(struct device *dev)
 210{
 211        return ili9320_suspend(dev_get_drvdata(dev));
 212}
 213static int vgg2432a4_resume(struct device *dev)
 214{
 215        return ili9320_resume(dev_get_drvdata(dev));
 216}
 217#endif
 218
 219static struct ili9320_client vgg2432a4_client = {
 220        .name   = "VGG2432A4",
 221        .init   = vgg2432a4_lcd_init,
 222};
 223
 224/* Device probe */
 225
 226static int vgg2432a4_probe(struct spi_device *spi)
 227{
 228        int ret;
 229
 230        ret = ili9320_probe_spi(spi, &vgg2432a4_client);
 231        if (ret != 0) {
 232                dev_err(&spi->dev, "failed to initialise ili9320\n");
 233                return ret;
 234        }
 235
 236        return 0;
 237}
 238
 239static int vgg2432a4_remove(struct spi_device *spi)
 240{
 241        return ili9320_remove(spi_get_drvdata(spi));
 242}
 243
 244static void vgg2432a4_shutdown(struct spi_device *spi)
 245{
 246        ili9320_shutdown(spi_get_drvdata(spi));
 247}
 248
 249static SIMPLE_DEV_PM_OPS(vgg2432a4_pm_ops, vgg2432a4_suspend, vgg2432a4_resume);
 250
 251static struct spi_driver vgg2432a4_driver = {
 252        .driver = {
 253                .name           = "VGG2432A4",
 254                .owner          = THIS_MODULE,
 255                .pm             = &vgg2432a4_pm_ops,
 256        },
 257        .probe          = vgg2432a4_probe,
 258        .remove         = vgg2432a4_remove,
 259        .shutdown       = vgg2432a4_shutdown,
 260};
 261
 262module_spi_driver(vgg2432a4_driver);
 263
 264MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
 265MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
 266MODULE_LICENSE("GPL v2");
 267MODULE_ALIAS("spi:VGG2432A4");
 268