linux/drivers/gpu/drm/panel/panel-ilitek-ili9322.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Ilitek ILI9322 TFT LCD drm_panel driver.
   4 *
   5 * This panel can be configured to support:
   6 * - 8-bit serial RGB interface
   7 * - 24-bit parallel RGB interface
   8 * - 8-bit ITU-R BT.601 interface
   9 * - 8-bit ITU-R BT.656 interface
  10 * - Up to 320RGBx240 dots resolution TFT LCD displays
  11 * - Scaling, brightness and contrast
  12 *
  13 * The scaling means that the display accepts a 640x480 or 720x480
  14 * input and rescales it to fit to the 320x240 display. So what we
  15 * present to the system is something else than what comes out on the
  16 * actual display.
  17 *
  18 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  19 * Derived from drivers/drm/gpu/panel/panel-samsung-ld9040.c
  20 */
  21
  22#include <linux/bitops.h>
  23#include <linux/gpio/consumer.h>
  24#include <linux/module.h>
  25#include <linux/of_device.h>
  26#include <linux/regmap.h>
  27#include <linux/regulator/consumer.h>
  28#include <linux/spi/spi.h>
  29
  30#include <video/mipi_display.h>
  31#include <video/of_videomode.h>
  32#include <video/videomode.h>
  33
  34#include <drm/drm_modes.h>
  35#include <drm/drm_panel.h>
  36
  37#define ILI9322_CHIP_ID                 0x00
  38#define ILI9322_CHIP_ID_MAGIC           0x96
  39
  40/*
  41 * Voltage on the communication interface, from 0.7 (0x00)
  42 * to 1.32 (0x1f) times the VREG1OUT voltage in 2% increments.
  43 * 1.00 (0x0f) is the default.
  44 */
  45#define ILI9322_VCOM_AMP                0x01
  46
  47/*
  48 * High voltage on the communication signals, from 0.37 (0x00) to
  49 * 1.0 (0x3f) times the VREGOUT1 voltage in 1% increments.
  50 * 0.83 (0x2e) is the default.
  51 */
  52#define ILI9322_VCOM_HIGH               0x02
  53
  54/*
  55 * VREG1 voltage regulator from 3.6V (0x00) to 6.0V (0x18) in 0.1V
  56 * increments. 5.4V (0x12) is the default. This is the reference
  57 * voltage for the VCOM levels and the greyscale level.
  58 */
  59#define ILI9322_VREG1_VOLTAGE           0x03
  60
  61/* Describes the incoming signal */
  62#define ILI9322_ENTRY                   0x06
  63/* 0 = right-to-left, 1 = left-to-right (default), horizontal flip */
  64#define ILI9322_ENTRY_HDIR              BIT(0)
  65/* 0 = down-to-up, 1 = up-to-down (default), vertical flip  */
  66#define ILI9322_ENTRY_VDIR              BIT(1)
  67/* NTSC, PAL or autodetect */
  68#define ILI9322_ENTRY_NTSC              (0 << 2)
  69#define ILI9322_ENTRY_PAL               (1 << 2)
  70#define ILI9322_ENTRY_AUTODETECT        (3 << 2)
  71/* Input format */
  72#define ILI9322_ENTRY_SERIAL_RGB_THROUGH (0 << 4)
  73#define ILI9322_ENTRY_SERIAL_RGB_ALIGNED (1 << 4)
  74#define ILI9322_ENTRY_SERIAL_RGB_DUMMY_320X240 (2 << 4)
  75#define ILI9322_ENTRY_SERIAL_RGB_DUMMY_360X240 (3 << 4)
  76#define ILI9322_ENTRY_DISABLE_1         (4 << 4)
  77#define ILI9322_ENTRY_PARALLEL_RGB_THROUGH (5 << 4)
  78#define ILI9322_ENTRY_PARALLEL_RGB_ALIGNED (6 << 4)
  79#define ILI9322_ENTRY_YUV_640Y_320CBCR_25_54_MHZ (7 << 4)
  80#define ILI9322_ENTRY_YUV_720Y_360CBCR_27_MHZ (8 << 4)
  81#define ILI9322_ENTRY_DISABLE_2         (9 << 4)
  82#define ILI9322_ENTRY_ITU_R_BT_656_720X360 (10 << 4)
  83#define ILI9322_ENTRY_ITU_R_BT_656_640X320 (11 << 4)
  84
  85/* Power control */
  86#define ILI9322_POW_CTRL                0x07
  87#define ILI9322_POW_CTRL_STB            BIT(0) /* 0 = standby, 1 = normal */
  88#define ILI9322_POW_CTRL_VGL            BIT(1) /* 0 = off, 1 = on  */
  89#define ILI9322_POW_CTRL_VGH            BIT(2) /* 0 = off, 1 = on  */
  90#define ILI9322_POW_CTRL_DDVDH          BIT(3) /* 0 = off, 1 = on  */
  91#define ILI9322_POW_CTRL_VCOM           BIT(4) /* 0 = off, 1 = on  */
  92#define ILI9322_POW_CTRL_VCL            BIT(5) /* 0 = off, 1 = on  */
  93#define ILI9322_POW_CTRL_AUTO           BIT(6) /* 0 = interactive, 1 = auto */
  94#define ILI9322_POW_CTRL_STANDBY        (ILI9322_POW_CTRL_VGL | \
  95                                         ILI9322_POW_CTRL_VGH | \
  96                                         ILI9322_POW_CTRL_DDVDH | \
  97                                         ILI9322_POW_CTRL_VCL | \
  98                                         ILI9322_POW_CTRL_AUTO | \
  99                                         BIT(7))
 100#define ILI9322_POW_CTRL_DEFAULT        (ILI9322_POW_CTRL_STANDBY | \
 101                                         ILI9322_POW_CTRL_STB)
 102
 103/* Vertical back porch bits 0..5 */
 104#define ILI9322_VBP                     0x08
 105
 106/* Horizontal back porch, 8 bits */
 107#define ILI9322_HBP                     0x09
 108
 109/*
 110 * Polarity settings:
 111 * 1 = positive polarity
 112 * 0 = negative polarity
 113 */
 114#define ILI9322_POL                     0x0a
 115#define ILI9322_POL_DCLK                BIT(0) /* 1 default */
 116#define ILI9322_POL_HSYNC               BIT(1) /* 0 default */
 117#define ILI9322_POL_VSYNC               BIT(2) /* 0 default */
 118#define ILI9322_POL_DE                  BIT(3) /* 1 default */
 119/*
 120 * 0 means YCBCR are ordered Cb0,Y0,Cr0,Y1,Cb2,Y2,Cr2,Y3 (default)
 121 *   in RGB mode this means RGB comes in RGBRGB
 122 * 1 means YCBCR are ordered Cr0,Y0,Cb0,Y1,Cr2,Y2,Cb2,Y3
 123 *   in RGB mode this means RGB comes in BGRBGR
 124 */
 125#define ILI9322_POL_YCBCR_MODE          BIT(4)
 126/* Formula A for YCbCR->RGB = 0, Formula B = 1 */
 127#define ILI9322_POL_FORMULA             BIT(5)
 128/* Reverse polarity: 0 = 0..255, 1 = 255..0 */
 129#define ILI9322_POL_REV                 BIT(6)
 130
 131#define ILI9322_IF_CTRL                 0x0b
 132#define ILI9322_IF_CTRL_HSYNC_VSYNC     0x00
 133#define ILI9322_IF_CTRL_HSYNC_VSYNC_DE  BIT(2)
 134#define ILI9322_IF_CTRL_DE_ONLY         BIT(3)
 135#define ILI9322_IF_CTRL_SYNC_DISABLED   (BIT(2) | BIT(3))
 136#define ILI9322_IF_CTRL_LINE_INVERSION  BIT(0) /* Not set means frame inv */
 137
 138#define ILI9322_GLOBAL_RESET            0x04
 139#define ILI9322_GLOBAL_RESET_ASSERT     0x00 /* bit 0 = 0 -> reset */
 140
 141/*
 142 * 4+4 bits of negative and positive gamma correction
 143 * Upper nybble, bits 4-7 are negative gamma
 144 * Lower nybble, bits 0-3 are positive gamma
 145 */
 146#define ILI9322_GAMMA_1                 0x10
 147#define ILI9322_GAMMA_2                 0x11
 148#define ILI9322_GAMMA_3                 0x12
 149#define ILI9322_GAMMA_4                 0x13
 150#define ILI9322_GAMMA_5                 0x14
 151#define ILI9322_GAMMA_6                 0x15
 152#define ILI9322_GAMMA_7                 0x16
 153#define ILI9322_GAMMA_8                 0x17
 154
 155/**
 156 * enum ili9322_input - the format of the incoming signal to the panel
 157 *
 158 * The panel can be connected to various input streams and four of them can
 159 * be selected by electronic straps on the display. However it is possible
 160 * to select another mode or override the electronic default with this
 161 * setting.
 162 */
 163enum ili9322_input {
 164        ILI9322_INPUT_SRGB_THROUGH = 0x0,
 165        ILI9322_INPUT_SRGB_ALIGNED = 0x1,
 166        ILI9322_INPUT_SRGB_DUMMY_320X240 = 0x2,
 167        ILI9322_INPUT_SRGB_DUMMY_360X240 = 0x3,
 168        ILI9322_INPUT_DISABLED_1 = 0x4,
 169        ILI9322_INPUT_PRGB_THROUGH = 0x5,
 170        ILI9322_INPUT_PRGB_ALIGNED = 0x6,
 171        ILI9322_INPUT_YUV_640X320_YCBCR = 0x7,
 172        ILI9322_INPUT_YUV_720X360_YCBCR = 0x8,
 173        ILI9322_INPUT_DISABLED_2 = 0x9,
 174        ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR = 0xa,
 175        ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR = 0xb,
 176        ILI9322_INPUT_UNKNOWN = 0xc,
 177};
 178
 179static const char * const ili9322_inputs[] = {
 180        "8 bit serial RGB through",
 181        "8 bit serial RGB aligned",
 182        "8 bit serial RGB dummy 320x240",
 183        "8 bit serial RGB dummy 360x240",
 184        "disabled 1",
 185        "24 bit parallel RGB through",
 186        "24 bit parallel RGB aligned",
 187        "24 bit YUV 640Y 320CbCr",
 188        "24 bit YUV 720Y 360CbCr",
 189        "disabled 2",
 190        "8 bit ITU-R BT.656 720Y 360CbCr",
 191        "8 bit ITU-R BT.656 640Y 320CbCr",
 192};
 193
 194/**
 195 * struct ili9322_config - the system specific ILI9322 configuration
 196 * @width_mm: physical panel width [mm]
 197 * @height_mm: physical panel height [mm]
 198 * @flip_horizontal: flip the image horizontally (right-to-left scan)
 199 * (only in RGB and YUV modes)
 200 * @flip_vertical: flip the image vertically (down-to-up scan)
 201 * (only in RGB and YUV modes)
 202 * @input: the input/entry type used in this system, if this is set to
 203 * ILI9322_INPUT_UNKNOWN the driver will try to figure it out by probing
 204 * the hardware
 205 * @vreg1out_mv: the output in microvolts for the VREGOUT1 regulator used
 206 * to drive the physical display. Valid ranges are 3600 thru 6000 in 100
 207 * microvolt increments. If not specified, hardware defaults will be
 208 * used (4.5V).
 209 * @vcom_high_percent: the percentage of VREGOUT1 used for the peak
 210 * voltage on the communications link. Valid ranges are 37 thru 100
 211 * percent. If not specified, hardware defaults will be used (91%).
 212 * @vcom_amplitude_percent: the percentage of VREGOUT1 used for the
 213 * peak-to-peak amplitude of the communcation signals to the physical
 214 * display. Valid ranges are 70 thru 132 percent in increments if two
 215 * percent. Odd percentages will be truncated. If not specified, hardware
 216 * defaults will be used (114%).
 217 * @dclk_active_high: data/pixel clock active high, data will be clocked
 218 * in on the rising edge of the DCLK (this is usually the case).
 219 * @syncmode: The synchronization mode, what sync signals are emitted.
 220 * See the enum for details.
 221 * @de_active_high: DE (data entry) is active high
 222 * @hsync_active_high: HSYNC is active high
 223 * @vsync_active_high: VSYNC is active high
 224 * @gamma_corr_pos: a set of 8 nybbles describing positive
 225 * gamma correction for voltages V1 thru V8. Valid range 0..15
 226 * @gamma_corr_neg: a set of 8 nybbles describing negative
 227 * gamma correction for voltages V1 thru V8. Valid range 0..15
 228 *
 229 * These adjust what grayscale voltage will be output for input data V1 = 0,
 230 * V2 = 16, V3 = 48, V4 = 96, V5 = 160, V6 = 208, V7 = 240 and V8 = 255.
 231 * The curve is shaped like this:
 232 *
 233 *  ^
 234 *  |                                                        V8
 235 *  |                                                   V7
 236 *  |                                          V6
 237 *  |                               V5
 238 *  |                    V4
 239 *  |            V3
 240 *  |     V2
 241 *  | V1
 242 *  +----------------------------------------------------------->
 243 *    0   16     48      96         160        208      240  255
 244 *
 245 * The negative and postive gamma values adjust the V1 thru V8 up/down
 246 * according to the datasheet specifications. This is a property of the
 247 * physical display connected to the display controller and may vary.
 248 * If defined, both arrays must be supplied in full. If the properties
 249 * are not supplied, hardware defaults will be used.
 250 */
 251struct ili9322_config {
 252        u32 width_mm;
 253        u32 height_mm;
 254        bool flip_horizontal;
 255        bool flip_vertical;
 256        enum ili9322_input input;
 257        u32 vreg1out_mv;
 258        u32 vcom_high_percent;
 259        u32 vcom_amplitude_percent;
 260        bool dclk_active_high;
 261        bool de_active_high;
 262        bool hsync_active_high;
 263        bool vsync_active_high;
 264        u8 syncmode;
 265        u8 gamma_corr_pos[8];
 266        u8 gamma_corr_neg[8];
 267};
 268
 269struct ili9322 {
 270        struct device *dev;
 271        const struct ili9322_config *conf;
 272        struct drm_panel panel;
 273        struct regmap *regmap;
 274        struct regulator_bulk_data supplies[3];
 275        struct gpio_desc *reset_gpio;
 276        enum ili9322_input input;
 277        struct videomode vm;
 278        u8 gamma[8];
 279        u8 vreg1out;
 280        u8 vcom_high;
 281        u8 vcom_amplitude;
 282};
 283
 284static inline struct ili9322 *panel_to_ili9322(struct drm_panel *panel)
 285{
 286        return container_of(panel, struct ili9322, panel);
 287}
 288
 289static int ili9322_regmap_spi_write(void *context, const void *data,
 290                                    size_t count)
 291{
 292        struct device *dev = context;
 293        struct spi_device *spi = to_spi_device(dev);
 294        u8 buf[2];
 295
 296        /* Clear bit 7 to write */
 297        memcpy(buf, data, 2);
 298        buf[0] &= ~0x80;
 299
 300        dev_dbg(dev, "WRITE: %02x %02x\n", buf[0], buf[1]);
 301        return spi_write_then_read(spi, buf, 2, NULL, 0);
 302}
 303
 304static int ili9322_regmap_spi_read(void *context, const void *reg,
 305                                   size_t reg_size, void *val, size_t val_size)
 306{
 307        struct device *dev = context;
 308        struct spi_device *spi = to_spi_device(dev);
 309        u8 buf[1];
 310
 311        /* Set bit 7 to 1 to read */
 312        memcpy(buf, reg, 1);
 313        dev_dbg(dev, "READ: %02x reg size = %zu, val size = %zu\n",
 314                buf[0], reg_size, val_size);
 315        buf[0] |= 0x80;
 316
 317        return spi_write_then_read(spi, buf, 1, val, 1);
 318}
 319
 320static struct regmap_bus ili9322_regmap_bus = {
 321        .write = ili9322_regmap_spi_write,
 322        .read = ili9322_regmap_spi_read,
 323        .reg_format_endian_default = REGMAP_ENDIAN_BIG,
 324        .val_format_endian_default = REGMAP_ENDIAN_BIG,
 325};
 326
 327static bool ili9322_volatile_reg(struct device *dev, unsigned int reg)
 328{
 329        return false;
 330}
 331
 332static bool ili9322_writeable_reg(struct device *dev, unsigned int reg)
 333{
 334        /* Just register 0 is read-only */
 335        if (reg == 0x00)
 336                return false;
 337        return true;
 338}
 339
 340static const struct regmap_config ili9322_regmap_config = {
 341        .reg_bits = 8,
 342        .val_bits = 8,
 343        .max_register = 0x44,
 344        .cache_type = REGCACHE_RBTREE,
 345        .volatile_reg = ili9322_volatile_reg,
 346        .writeable_reg = ili9322_writeable_reg,
 347};
 348
 349static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili)
 350{
 351        u8 reg;
 352        int ret;
 353        int i;
 354
 355        /* Reset display */
 356        ret = regmap_write(ili->regmap, ILI9322_GLOBAL_RESET,
 357                           ILI9322_GLOBAL_RESET_ASSERT);
 358        if (ret) {
 359                dev_err(ili->dev, "can't issue GRESET (%d)\n", ret);
 360                return ret;
 361        }
 362
 363        /* Set up the main voltage regulator */
 364        if (ili->vreg1out != U8_MAX) {
 365                ret = regmap_write(ili->regmap, ILI9322_VREG1_VOLTAGE,
 366                                   ili->vreg1out);
 367                if (ret) {
 368                        dev_err(ili->dev, "can't set up VREG1OUT (%d)\n", ret);
 369                        return ret;
 370                }
 371        }
 372
 373        if (ili->vcom_amplitude != U8_MAX) {
 374                ret = regmap_write(ili->regmap, ILI9322_VCOM_AMP,
 375                                   ili->vcom_amplitude);
 376                if (ret) {
 377                        dev_err(ili->dev,
 378                                "can't set up VCOM amplitude (%d)\n", ret);
 379                        return ret;
 380                }
 381        }
 382
 383        if (ili->vcom_high != U8_MAX) {
 384                ret = regmap_write(ili->regmap, ILI9322_VCOM_HIGH,
 385                                   ili->vcom_high);
 386                if (ret) {
 387                        dev_err(ili->dev, "can't set up VCOM high (%d)\n", ret);
 388                        return ret;
 389                }
 390        }
 391
 392        /* Set up gamma correction */
 393        for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
 394                ret = regmap_write(ili->regmap, ILI9322_GAMMA_1 + i,
 395                                   ili->gamma[i]);
 396                if (ret) {
 397                        dev_err(ili->dev,
 398                                "can't write gamma V%d to 0x%02x (%d)\n",
 399                                i + 1, ILI9322_GAMMA_1 + i, ret);
 400                        return ret;
 401                }
 402        }
 403
 404        /*
 405         * Polarity and inverted color order for RGB input.
 406         * None of this applies in the BT.656 mode.
 407         */
 408        reg = 0;
 409        if (ili->conf->dclk_active_high)
 410                reg = ILI9322_POL_DCLK;
 411        if (ili->conf->de_active_high)
 412                reg |= ILI9322_POL_DE;
 413        if (ili->conf->hsync_active_high)
 414                reg |= ILI9322_POL_HSYNC;
 415        if (ili->conf->vsync_active_high)
 416                reg |= ILI9322_POL_VSYNC;
 417        ret = regmap_write(ili->regmap, ILI9322_POL, reg);
 418        if (ret) {
 419                dev_err(ili->dev, "can't write POL register (%d)\n", ret);
 420                return ret;
 421        }
 422
 423        /*
 424         * Set up interface control.
 425         * This is not used in the BT.656 mode (no H/Vsync or DE signals).
 426         */
 427        reg = ili->conf->syncmode;
 428        reg |= ILI9322_IF_CTRL_LINE_INVERSION;
 429        ret = regmap_write(ili->regmap, ILI9322_IF_CTRL, reg);
 430        if (ret) {
 431                dev_err(ili->dev, "can't write IF CTRL register (%d)\n", ret);
 432                return ret;
 433        }
 434
 435        /* Set up the input mode */
 436        reg = (ili->input << 4);
 437        /* These are inverted, setting to 1 is the default, clearing flips */
 438        if (!ili->conf->flip_horizontal)
 439                reg |= ILI9322_ENTRY_HDIR;
 440        if (!ili->conf->flip_vertical)
 441                reg |= ILI9322_ENTRY_VDIR;
 442        reg |= ILI9322_ENTRY_AUTODETECT;
 443        ret = regmap_write(ili->regmap, ILI9322_ENTRY, reg);
 444        if (ret) {
 445                dev_err(ili->dev, "can't write ENTRY reg (%d)\n", ret);
 446                return ret;
 447        }
 448        dev_info(ili->dev, "display is in %s mode, syncmode %02x\n",
 449                 ili9322_inputs[ili->input],
 450                 ili->conf->syncmode);
 451
 452        dev_info(ili->dev, "initialized display\n");
 453
 454        return 0;
 455}
 456
 457/*
 458 * This power-on sequence if from the datasheet, page 57.
 459 */
 460static int ili9322_power_on(struct ili9322 *ili)
 461{
 462        int ret;
 463
 464        /* Assert RESET */
 465        gpiod_set_value(ili->reset_gpio, 1);
 466
 467        ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies), ili->supplies);
 468        if (ret < 0) {
 469                dev_err(ili->dev, "unable to enable regulators\n");
 470                return ret;
 471        }
 472        msleep(20);
 473
 474        /* De-assert RESET */
 475        gpiod_set_value(ili->reset_gpio, 0);
 476
 477        msleep(10);
 478
 479        return 0;
 480}
 481
 482static int ili9322_power_off(struct ili9322 *ili)
 483{
 484        return regulator_bulk_disable(ARRAY_SIZE(ili->supplies), ili->supplies);
 485}
 486
 487static int ili9322_disable(struct drm_panel *panel)
 488{
 489        struct ili9322 *ili = panel_to_ili9322(panel);
 490        int ret;
 491
 492        ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
 493                           ILI9322_POW_CTRL_STANDBY);
 494        if (ret) {
 495                dev_err(ili->dev, "unable to go to standby mode\n");
 496                return ret;
 497        }
 498
 499        return 0;
 500}
 501
 502static int ili9322_unprepare(struct drm_panel *panel)
 503{
 504        struct ili9322 *ili = panel_to_ili9322(panel);
 505
 506        return ili9322_power_off(ili);
 507}
 508
 509static int ili9322_prepare(struct drm_panel *panel)
 510{
 511        struct ili9322 *ili = panel_to_ili9322(panel);
 512        int ret;
 513
 514        ret = ili9322_power_on(ili);
 515        if (ret < 0)
 516                return ret;
 517
 518        ret = ili9322_init(panel, ili);
 519        if (ret < 0)
 520                ili9322_unprepare(panel);
 521
 522        return ret;
 523}
 524
 525static int ili9322_enable(struct drm_panel *panel)
 526{
 527        struct ili9322 *ili = panel_to_ili9322(panel);
 528        int ret;
 529
 530        ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
 531                           ILI9322_POW_CTRL_DEFAULT);
 532        if (ret) {
 533                dev_err(ili->dev, "unable to enable panel\n");
 534                return ret;
 535        }
 536
 537        return 0;
 538}
 539
 540/* Serial RGB modes */
 541static const struct drm_display_mode srgb_320x240_mode = {
 542        .clock = 24535,
 543        .hdisplay = 320,
 544        .hsync_start = 320 + 359,
 545        .hsync_end = 320 + 359 + 1,
 546        .htotal = 320 + 359 + 1 + 241,
 547        .vdisplay = 240,
 548        .vsync_start = 240 + 4,
 549        .vsync_end = 240 + 4 + 1,
 550        .vtotal = 262,
 551        .flags = 0,
 552};
 553
 554static const struct drm_display_mode srgb_360x240_mode = {
 555        .clock = 27000,
 556        .hdisplay = 360,
 557        .hsync_start = 360 + 35,
 558        .hsync_end = 360 + 35 + 1,
 559        .htotal = 360 + 35 + 1 + 241,
 560        .vdisplay = 240,
 561        .vsync_start = 240 + 21,
 562        .vsync_end = 240 + 21 + 1,
 563        .vtotal = 262,
 564        .flags = 0,
 565};
 566
 567/* This is the only mode listed for parallel RGB in the datasheet */
 568static const struct drm_display_mode prgb_320x240_mode = {
 569        .clock = 64000,
 570        .hdisplay = 320,
 571        .hsync_start = 320 + 38,
 572        .hsync_end = 320 + 38 + 1,
 573        .htotal = 320 + 38 + 1 + 50,
 574        .vdisplay = 240,
 575        .vsync_start = 240 + 4,
 576        .vsync_end = 240 + 4 + 1,
 577        .vtotal = 262,
 578        .flags = 0,
 579};
 580
 581/* YUV modes */
 582static const struct drm_display_mode yuv_640x320_mode = {
 583        .clock = 24540,
 584        .hdisplay = 640,
 585        .hsync_start = 640 + 252,
 586        .hsync_end = 640 + 252 + 1,
 587        .htotal = 640 + 252 + 1 + 28,
 588        .vdisplay = 320,
 589        .vsync_start = 320 + 4,
 590        .vsync_end = 320 + 4 + 1,
 591        .vtotal = 320 + 4 + 1 + 18,
 592        .flags = 0,
 593};
 594
 595static const struct drm_display_mode yuv_720x360_mode = {
 596        .clock = 27000,
 597        .hdisplay = 720,
 598        .hsync_start = 720 + 252,
 599        .hsync_end = 720 + 252 + 1,
 600        .htotal = 720 + 252 + 1 + 24,
 601        .vdisplay = 360,
 602        .vsync_start = 360 + 4,
 603        .vsync_end = 360 + 4 + 1,
 604        .vtotal = 360 + 4 + 1 + 18,
 605        .flags = 0,
 606};
 607
 608/* BT.656 VGA mode, 640x480 */
 609static const struct drm_display_mode itu_r_bt_656_640_mode = {
 610        .clock = 24540,
 611        .hdisplay = 640,
 612        .hsync_start = 640 + 3,
 613        .hsync_end = 640 + 3 + 1,
 614        .htotal = 640 + 3 + 1 + 272,
 615        .vdisplay = 480,
 616        .vsync_start = 480 + 4,
 617        .vsync_end = 480 + 4 + 1,
 618        .vtotal = 500,
 619        .flags = 0,
 620};
 621
 622/* BT.656 D1 mode 720x480 */
 623static const struct drm_display_mode itu_r_bt_656_720_mode = {
 624        .clock = 27000,
 625        .hdisplay = 720,
 626        .hsync_start = 720 + 3,
 627        .hsync_end = 720 + 3 + 1,
 628        .htotal = 720 + 3 + 1 + 272,
 629        .vdisplay = 480,
 630        .vsync_start = 480 + 4,
 631        .vsync_end = 480 + 4 + 1,
 632        .vtotal = 500,
 633        .flags = 0,
 634};
 635
 636static int ili9322_get_modes(struct drm_panel *panel,
 637                             struct drm_connector *connector)
 638{
 639        struct ili9322 *ili = panel_to_ili9322(panel);
 640        struct drm_device *drm = connector->dev;
 641        struct drm_display_mode *mode;
 642        struct drm_display_info *info;
 643
 644        info = &connector->display_info;
 645        info->width_mm = ili->conf->width_mm;
 646        info->height_mm = ili->conf->height_mm;
 647        if (ili->conf->dclk_active_high)
 648                info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
 649        else
 650                info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
 651
 652        if (ili->conf->de_active_high)
 653                info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
 654        else
 655                info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
 656
 657        switch (ili->input) {
 658        case ILI9322_INPUT_SRGB_DUMMY_320X240:
 659                mode = drm_mode_duplicate(drm, &srgb_320x240_mode);
 660                break;
 661        case ILI9322_INPUT_SRGB_DUMMY_360X240:
 662                mode = drm_mode_duplicate(drm, &srgb_360x240_mode);
 663                break;
 664        case ILI9322_INPUT_PRGB_THROUGH:
 665        case ILI9322_INPUT_PRGB_ALIGNED:
 666                mode = drm_mode_duplicate(drm, &prgb_320x240_mode);
 667                break;
 668        case ILI9322_INPUT_YUV_640X320_YCBCR:
 669                mode = drm_mode_duplicate(drm, &yuv_640x320_mode);
 670                break;
 671        case ILI9322_INPUT_YUV_720X360_YCBCR:
 672                mode = drm_mode_duplicate(drm, &yuv_720x360_mode);
 673                break;
 674        case ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR:
 675                mode = drm_mode_duplicate(drm, &itu_r_bt_656_720_mode);
 676                break;
 677        case ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR:
 678                mode = drm_mode_duplicate(drm, &itu_r_bt_656_640_mode);
 679                break;
 680        default:
 681                mode = NULL;
 682                break;
 683        }
 684        if (!mode) {
 685                dev_err(panel->dev, "bad mode or failed to add mode\n");
 686                return -EINVAL;
 687        }
 688        drm_mode_set_name(mode);
 689        /*
 690         * This is the preferred mode because most people are going
 691         * to want to use the display with VGA type graphics.
 692         */
 693        mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 694
 695        /* Set up the polarity */
 696        if (ili->conf->hsync_active_high)
 697                mode->flags |= DRM_MODE_FLAG_PHSYNC;
 698        else
 699                mode->flags |= DRM_MODE_FLAG_NHSYNC;
 700        if (ili->conf->vsync_active_high)
 701                mode->flags |= DRM_MODE_FLAG_PVSYNC;
 702        else
 703                mode->flags |= DRM_MODE_FLAG_NVSYNC;
 704
 705        mode->width_mm = ili->conf->width_mm;
 706        mode->height_mm = ili->conf->height_mm;
 707        drm_mode_probed_add(connector, mode);
 708
 709        return 1; /* Number of modes */
 710}
 711
 712static const struct drm_panel_funcs ili9322_drm_funcs = {
 713        .disable = ili9322_disable,
 714        .unprepare = ili9322_unprepare,
 715        .prepare = ili9322_prepare,
 716        .enable = ili9322_enable,
 717        .get_modes = ili9322_get_modes,
 718};
 719
 720static int ili9322_probe(struct spi_device *spi)
 721{
 722        struct device *dev = &spi->dev;
 723        struct ili9322 *ili;
 724        const struct regmap_config *regmap_config;
 725        u8 gamma;
 726        u32 val;
 727        int ret;
 728        int i;
 729
 730        ili = devm_kzalloc(dev, sizeof(struct ili9322), GFP_KERNEL);
 731        if (!ili)
 732                return -ENOMEM;
 733
 734        spi_set_drvdata(spi, ili);
 735
 736        ili->dev = dev;
 737
 738        /*
 739         * Every new incarnation of this display must have a unique
 740         * data entry for the system in this driver.
 741         */
 742        ili->conf = of_device_get_match_data(dev);
 743        if (!ili->conf) {
 744                dev_err(dev, "missing device configuration\n");
 745                return -ENODEV;
 746        }
 747
 748        val = ili->conf->vreg1out_mv;
 749        if (!val) {
 750                /* Default HW value, do not touch (should be 4.5V) */
 751                ili->vreg1out = U8_MAX;
 752        } else {
 753                if (val < 3600) {
 754                        dev_err(dev, "too low VREG1OUT\n");
 755                        return -EINVAL;
 756                }
 757                if (val > 6000) {
 758                        dev_err(dev, "too high VREG1OUT\n");
 759                        return -EINVAL;
 760                }
 761                if ((val % 100) != 0) {
 762                        dev_err(dev, "VREG1OUT is no even 100 microvolt\n");
 763                        return -EINVAL;
 764                }
 765                val -= 3600;
 766                val /= 100;
 767                dev_dbg(dev, "VREG1OUT = 0x%02x\n", val);
 768                ili->vreg1out = val;
 769        }
 770
 771        val = ili->conf->vcom_high_percent;
 772        if (!val) {
 773                /* Default HW value, do not touch (should be 91%) */
 774                ili->vcom_high = U8_MAX;
 775        } else {
 776                if (val < 37) {
 777                        dev_err(dev, "too low VCOM high\n");
 778                        return -EINVAL;
 779                }
 780                if (val > 100) {
 781                        dev_err(dev, "too high VCOM high\n");
 782                        return -EINVAL;
 783                }
 784                val -= 37;
 785                dev_dbg(dev, "VCOM high = 0x%02x\n", val);
 786                ili->vcom_high = val;
 787        }
 788
 789        val = ili->conf->vcom_amplitude_percent;
 790        if (!val) {
 791                /* Default HW value, do not touch (should be 114%) */
 792                ili->vcom_high = U8_MAX;
 793        } else {
 794                if (val < 70) {
 795                        dev_err(dev, "too low VCOM amplitude\n");
 796                        return -EINVAL;
 797                }
 798                if (val > 132) {
 799                        dev_err(dev, "too high VCOM amplitude\n");
 800                        return -EINVAL;
 801                }
 802                val -= 70;
 803                val >>= 1; /* Increments of 2% */
 804                dev_dbg(dev, "VCOM amplitude = 0x%02x\n", val);
 805                ili->vcom_amplitude = val;
 806        }
 807
 808        for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
 809                val = ili->conf->gamma_corr_neg[i];
 810                if (val > 15) {
 811                        dev_err(dev, "negative gamma %u > 15, capping\n", val);
 812                        val = 15;
 813                }
 814                gamma = val << 4;
 815                val = ili->conf->gamma_corr_pos[i];
 816                if (val > 15) {
 817                        dev_err(dev, "positive gamma %u > 15, capping\n", val);
 818                        val = 15;
 819                }
 820                gamma |= val;
 821                ili->gamma[i] = gamma;
 822                dev_dbg(dev, "gamma V%d: 0x%02x\n", i + 1, gamma);
 823        }
 824
 825        ili->supplies[0].supply = "vcc"; /* 2.7-3.6 V */
 826        ili->supplies[1].supply = "iovcc"; /* 1.65-3.6V */
 827        ili->supplies[2].supply = "vci"; /* 2.7-3.6V */
 828        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
 829                                      ili->supplies);
 830        if (ret < 0)
 831                return ret;
 832        ret = regulator_set_voltage(ili->supplies[0].consumer,
 833                                    2700000, 3600000);
 834        if (ret)
 835                return ret;
 836        ret = regulator_set_voltage(ili->supplies[1].consumer,
 837                                    1650000, 3600000);
 838        if (ret)
 839                return ret;
 840        ret = regulator_set_voltage(ili->supplies[2].consumer,
 841                                    2700000, 3600000);
 842        if (ret)
 843                return ret;
 844
 845        ili->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 846        if (IS_ERR(ili->reset_gpio)) {
 847                dev_err(dev, "failed to get RESET GPIO\n");
 848                return PTR_ERR(ili->reset_gpio);
 849        }
 850
 851        spi->bits_per_word = 8;
 852        ret = spi_setup(spi);
 853        if (ret < 0) {
 854                dev_err(dev, "spi setup failed.\n");
 855                return ret;
 856        }
 857        regmap_config = &ili9322_regmap_config;
 858        ili->regmap = devm_regmap_init(dev, &ili9322_regmap_bus, dev,
 859                                       regmap_config);
 860        if (IS_ERR(ili->regmap)) {
 861                dev_err(dev, "failed to allocate register map\n");
 862                return PTR_ERR(ili->regmap);
 863        }
 864
 865        ret = regmap_read(ili->regmap, ILI9322_CHIP_ID, &val);
 866        if (ret) {
 867                dev_err(dev, "can't get chip ID (%d)\n", ret);
 868                return ret;
 869        }
 870        if (val != ILI9322_CHIP_ID_MAGIC) {
 871                dev_err(dev, "chip ID 0x%0x2, expected 0x%02x\n", val,
 872                        ILI9322_CHIP_ID_MAGIC);
 873                return -ENODEV;
 874        }
 875
 876        /* Probe the system to find the display setting */
 877        if (ili->conf->input == ILI9322_INPUT_UNKNOWN) {
 878                ret = regmap_read(ili->regmap, ILI9322_ENTRY, &val);
 879                if (ret) {
 880                        dev_err(dev, "can't get entry setting (%d)\n", ret);
 881                        return ret;
 882                }
 883                /* Input enum corresponds to HW setting */
 884                ili->input = (val >> 4) & 0x0f;
 885                if (ili->input >= ILI9322_INPUT_UNKNOWN)
 886                        ili->input = ILI9322_INPUT_UNKNOWN;
 887        } else {
 888                ili->input = ili->conf->input;
 889        }
 890
 891        drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs,
 892                       DRM_MODE_CONNECTOR_DPI);
 893
 894        drm_panel_add(&ili->panel);
 895
 896        return 0;
 897}
 898
 899static int ili9322_remove(struct spi_device *spi)
 900{
 901        struct ili9322 *ili = spi_get_drvdata(spi);
 902
 903        ili9322_power_off(ili);
 904        drm_panel_remove(&ili->panel);
 905
 906        return 0;
 907}
 908
 909/*
 910 * The D-Link DIR-685 panel is marked LM918A01-1A SY-B4-091116-E0199
 911 */
 912static const struct ili9322_config ili9322_dir_685 = {
 913        .width_mm = 65,
 914        .height_mm = 50,
 915        .input = ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR,
 916        .vreg1out_mv = 4600,
 917        .vcom_high_percent = 91,
 918        .vcom_amplitude_percent = 114,
 919        .syncmode = ILI9322_IF_CTRL_SYNC_DISABLED,
 920        .dclk_active_high = true,
 921        .gamma_corr_neg = { 0xa, 0x5, 0x7, 0x7, 0x7, 0x5, 0x1, 0x6 },
 922        .gamma_corr_pos = { 0x7, 0x7, 0x3, 0x2, 0x3, 0x5, 0x7, 0x2 },
 923};
 924
 925static const struct of_device_id ili9322_of_match[] = {
 926        {
 927                .compatible = "dlink,dir-685-panel",
 928                .data = &ili9322_dir_685,
 929        },
 930        {
 931                .compatible = "ilitek,ili9322",
 932                .data = NULL,
 933        },
 934        { }
 935};
 936MODULE_DEVICE_TABLE(of, ili9322_of_match);
 937
 938static struct spi_driver ili9322_driver = {
 939        .probe = ili9322_probe,
 940        .remove = ili9322_remove,
 941        .driver = {
 942                .name = "panel-ilitek-ili9322",
 943                .of_match_table = ili9322_of_match,
 944        },
 945};
 946module_spi_driver(ili9322_driver);
 947
 948MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 949MODULE_DESCRIPTION("ILI9322 LCD panel driver");
 950MODULE_LICENSE("GPL v2");
 951