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