root/drivers/gpu/drm/panel/panel-ilitek-ili9322.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. panel_to_ili9322
  2. ili9322_regmap_spi_write
  3. ili9322_regmap_spi_read
  4. ili9322_volatile_reg
  5. ili9322_writeable_reg
  6. ili9322_init
  7. ili9322_power_on
  8. ili9322_power_off
  9. ili9322_disable
  10. ili9322_unprepare
  11. ili9322_prepare
  12. ili9322_enable
  13. ili9322_get_modes
  14. ili9322_probe
  15. ili9322_remove

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

/* [<][>][^][v][top][bottom][index][help] */