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