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