1 /* 2 * Driver for the Himax HX-8357 LCD Controller 3 * 4 * Copyright 2012 Free Electrons 5 * 6 * Licensed under the GPLv2 or later. 7 */ 8 9 #include <linux/delay.h> 10 #include <linux/lcd.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/of_device.h> 14 #include <linux/of_gpio.h> 15 #include <linux/spi/spi.h> 16 17 #define HX8357_NUM_IM_PINS 3 18 19 #define HX8357_SWRESET 0x01 20 #define HX8357_GET_RED_CHANNEL 0x06 21 #define HX8357_GET_GREEN_CHANNEL 0x07 22 #define HX8357_GET_BLUE_CHANNEL 0x08 23 #define HX8357_GET_POWER_MODE 0x0a 24 #define HX8357_GET_MADCTL 0x0b 25 #define HX8357_GET_PIXEL_FORMAT 0x0c 26 #define HX8357_GET_DISPLAY_MODE 0x0d 27 #define HX8357_GET_SIGNAL_MODE 0x0e 28 #define HX8357_GET_DIAGNOSTIC_RESULT 0x0f 29 #define HX8357_ENTER_SLEEP_MODE 0x10 30 #define HX8357_EXIT_SLEEP_MODE 0x11 31 #define HX8357_ENTER_PARTIAL_MODE 0x12 32 #define HX8357_ENTER_NORMAL_MODE 0x13 33 #define HX8357_EXIT_INVERSION_MODE 0x20 34 #define HX8357_ENTER_INVERSION_MODE 0x21 35 #define HX8357_SET_DISPLAY_OFF 0x28 36 #define HX8357_SET_DISPLAY_ON 0x29 37 #define HX8357_SET_COLUMN_ADDRESS 0x2a 38 #define HX8357_SET_PAGE_ADDRESS 0x2b 39 #define HX8357_WRITE_MEMORY_START 0x2c 40 #define HX8357_READ_MEMORY_START 0x2e 41 #define HX8357_SET_PARTIAL_AREA 0x30 42 #define HX8357_SET_SCROLL_AREA 0x33 43 #define HX8357_SET_TEAR_OFF 0x34 44 #define HX8357_SET_TEAR_ON 0x35 45 #define HX8357_SET_ADDRESS_MODE 0x36 46 #define HX8357_SET_SCROLL_START 0x37 47 #define HX8357_EXIT_IDLE_MODE 0x38 48 #define HX8357_ENTER_IDLE_MODE 0x39 49 #define HX8357_SET_PIXEL_FORMAT 0x3a 50 #define HX8357_SET_PIXEL_FORMAT_DBI_3BIT (0x1) 51 #define HX8357_SET_PIXEL_FORMAT_DBI_16BIT (0x5) 52 #define HX8357_SET_PIXEL_FORMAT_DBI_18BIT (0x6) 53 #define HX8357_SET_PIXEL_FORMAT_DPI_3BIT (0x1 << 4) 54 #define HX8357_SET_PIXEL_FORMAT_DPI_16BIT (0x5 << 4) 55 #define HX8357_SET_PIXEL_FORMAT_DPI_18BIT (0x6 << 4) 56 #define HX8357_WRITE_MEMORY_CONTINUE 0x3c 57 #define HX8357_READ_MEMORY_CONTINUE 0x3e 58 #define HX8357_SET_TEAR_SCAN_LINES 0x44 59 #define HX8357_GET_SCAN_LINES 0x45 60 #define HX8357_READ_DDB_START 0xa1 61 #define HX8357_SET_DISPLAY_MODE 0xb4 62 #define HX8357_SET_DISPLAY_MODE_RGB_THROUGH (0x3) 63 #define HX8357_SET_DISPLAY_MODE_RGB_INTERFACE (1 << 4) 64 #define HX8357_SET_PANEL_DRIVING 0xc0 65 #define HX8357_SET_DISPLAY_FRAME 0xc5 66 #define HX8357_SET_RGB 0xc6 67 #define HX8357_SET_RGB_ENABLE_HIGH (1 << 1) 68 #define HX8357_SET_GAMMA 0xc8 69 #define HX8357_SET_POWER 0xd0 70 #define HX8357_SET_VCOM 0xd1 71 #define HX8357_SET_POWER_NORMAL 0xd2 72 #define HX8357_SET_PANEL_RELATED 0xe9 73 74 #define HX8369_SET_DISPLAY_BRIGHTNESS 0x51 75 #define HX8369_WRITE_CABC_DISPLAY_VALUE 0x53 76 #define HX8369_WRITE_CABC_BRIGHT_CTRL 0x55 77 #define HX8369_WRITE_CABC_MIN_BRIGHTNESS 0x5e 78 #define HX8369_SET_POWER 0xb1 79 #define HX8369_SET_DISPLAY_MODE 0xb2 80 #define HX8369_SET_DISPLAY_WAVEFORM_CYC 0xb4 81 #define HX8369_SET_VCOM 0xb6 82 #define HX8369_SET_EXTENSION_COMMAND 0xb9 83 #define HX8369_SET_GIP 0xd5 84 #define HX8369_SET_GAMMA_CURVE_RELATED 0xe0 85 86 struct hx8357_data { 87 unsigned im_pins[HX8357_NUM_IM_PINS]; 88 unsigned reset; 89 struct spi_device *spi; 90 int state; 91 bool use_im_pins; 92 }; 93 94 static u8 hx8357_seq_power[] = { 95 HX8357_SET_POWER, 0x44, 0x41, 0x06, 96 }; 97 98 static u8 hx8357_seq_vcom[] = { 99 HX8357_SET_VCOM, 0x40, 0x10, 100 }; 101 102 static u8 hx8357_seq_power_normal[] = { 103 HX8357_SET_POWER_NORMAL, 0x05, 0x12, 104 }; 105 106 static u8 hx8357_seq_panel_driving[] = { 107 HX8357_SET_PANEL_DRIVING, 0x14, 0x3b, 0x00, 0x02, 0x11, 108 }; 109 110 static u8 hx8357_seq_display_frame[] = { 111 HX8357_SET_DISPLAY_FRAME, 0x0c, 112 }; 113 114 static u8 hx8357_seq_panel_related[] = { 115 HX8357_SET_PANEL_RELATED, 0x01, 116 }; 117 118 static u8 hx8357_seq_undefined1[] = { 119 0xea, 0x03, 0x00, 0x00, 120 }; 121 122 static u8 hx8357_seq_undefined2[] = { 123 0xeb, 0x40, 0x54, 0x26, 0xdb, 124 }; 125 126 static u8 hx8357_seq_gamma[] = { 127 HX8357_SET_GAMMA, 0x00, 0x15, 0x00, 0x22, 0x00, 128 0x08, 0x77, 0x26, 0x77, 0x22, 0x04, 0x00, 129 }; 130 131 static u8 hx8357_seq_address_mode[] = { 132 HX8357_SET_ADDRESS_MODE, 0xc0, 133 }; 134 135 static u8 hx8357_seq_pixel_format[] = { 136 HX8357_SET_PIXEL_FORMAT, 137 HX8357_SET_PIXEL_FORMAT_DPI_18BIT | 138 HX8357_SET_PIXEL_FORMAT_DBI_18BIT, 139 }; 140 141 static u8 hx8357_seq_column_address[] = { 142 HX8357_SET_COLUMN_ADDRESS, 0x00, 0x00, 0x01, 0x3f, 143 }; 144 145 static u8 hx8357_seq_page_address[] = { 146 HX8357_SET_PAGE_ADDRESS, 0x00, 0x00, 0x01, 0xdf, 147 }; 148 149 static u8 hx8357_seq_rgb[] = { 150 HX8357_SET_RGB, 0x02, 151 }; 152 153 static u8 hx8357_seq_display_mode[] = { 154 HX8357_SET_DISPLAY_MODE, 155 HX8357_SET_DISPLAY_MODE_RGB_THROUGH | 156 HX8357_SET_DISPLAY_MODE_RGB_INTERFACE, 157 }; 158 159 static u8 hx8369_seq_write_CABC_min_brightness[] = { 160 HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00, 161 }; 162 163 static u8 hx8369_seq_write_CABC_control[] = { 164 HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24, 165 }; 166 167 static u8 hx8369_seq_set_display_brightness[] = { 168 HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF, 169 }; 170 171 static u8 hx8369_seq_write_CABC_control_setting[] = { 172 HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02, 173 }; 174 175 static u8 hx8369_seq_extension_command[] = { 176 HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69, 177 }; 178 179 static u8 hx8369_seq_display_related[] = { 180 HX8369_SET_DISPLAY_MODE, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00, 181 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x01, 182 }; 183 184 static u8 hx8369_seq_panel_waveform_cycle[] = { 185 HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02, 186 }; 187 188 static u8 hx8369_seq_set_address_mode[] = { 189 HX8357_SET_ADDRESS_MODE, 0x00, 190 }; 191 192 static u8 hx8369_seq_vcom[] = { 193 HX8369_SET_VCOM, 0x3e, 0x3e, 194 }; 195 196 static u8 hx8369_seq_gip[] = { 197 HX8369_SET_GIP, 0x00, 0x01, 0x03, 0x25, 0x01, 0x02, 0x28, 0x70, 198 0x11, 0x13, 0x00, 0x00, 0x40, 0x26, 0x51, 0x37, 0x00, 0x00, 0x71, 199 0x35, 0x60, 0x24, 0x07, 0x0f, 0x04, 0x04, 200 }; 201 202 static u8 hx8369_seq_power[] = { 203 HX8369_SET_POWER, 0x01, 0x00, 0x34, 0x03, 0x00, 0x11, 0x11, 0x32, 204 0x2f, 0x3f, 0x3f, 0x01, 0x3a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 205 }; 206 207 static u8 hx8369_seq_gamma_curve_related[] = { 208 HX8369_SET_GAMMA_CURVE_RELATED, 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 209 0x2e, 0x4a, 0x08, 0x0e, 0x0f, 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e, 210 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 0x2e, 0x4a, 0x08, 0x0e, 0x0f, 211 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e, 212 }; 213 214 static int hx8357_spi_write_then_read(struct lcd_device *lcdev, 215 u8 *txbuf, u16 txlen, 216 u8 *rxbuf, u16 rxlen) 217 { 218 struct hx8357_data *lcd = lcd_get_data(lcdev); 219 struct spi_message msg; 220 struct spi_transfer xfer[2]; 221 u16 *local_txbuf = NULL; 222 int ret = 0; 223 224 memset(xfer, 0, sizeof(xfer)); 225 spi_message_init(&msg); 226 227 if (txlen) { 228 int i; 229 230 local_txbuf = kcalloc(txlen, sizeof(*local_txbuf), GFP_KERNEL); 231 232 if (!local_txbuf) 233 return -ENOMEM; 234 235 for (i = 0; i < txlen; i++) { 236 local_txbuf[i] = txbuf[i]; 237 if (i > 0) 238 local_txbuf[i] |= 1 << 8; 239 } 240 241 xfer[0].len = 2 * txlen; 242 xfer[0].bits_per_word = 9; 243 xfer[0].tx_buf = local_txbuf; 244 spi_message_add_tail(&xfer[0], &msg); 245 } 246 247 if (rxlen) { 248 xfer[1].len = rxlen; 249 xfer[1].bits_per_word = 8; 250 xfer[1].rx_buf = rxbuf; 251 spi_message_add_tail(&xfer[1], &msg); 252 } 253 254 ret = spi_sync(lcd->spi, &msg); 255 if (ret < 0) 256 dev_err(&lcdev->dev, "Couldn't send SPI data\n"); 257 258 if (txlen) 259 kfree(local_txbuf); 260 261 return ret; 262 } 263 264 static inline int hx8357_spi_write_array(struct lcd_device *lcdev, 265 u8 *value, u8 len) 266 { 267 return hx8357_spi_write_then_read(lcdev, value, len, NULL, 0); 268 } 269 270 static inline int hx8357_spi_write_byte(struct lcd_device *lcdev, 271 u8 value) 272 { 273 return hx8357_spi_write_then_read(lcdev, &value, 1, NULL, 0); 274 } 275 276 static int hx8357_enter_standby(struct lcd_device *lcdev) 277 { 278 int ret; 279 280 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_OFF); 281 if (ret < 0) 282 return ret; 283 284 usleep_range(10000, 12000); 285 286 ret = hx8357_spi_write_byte(lcdev, HX8357_ENTER_SLEEP_MODE); 287 if (ret < 0) 288 return ret; 289 290 /* 291 * The controller needs 120ms when entering in sleep mode before we can 292 * send the command to go off sleep mode 293 */ 294 msleep(120); 295 296 return 0; 297 } 298 299 static int hx8357_exit_standby(struct lcd_device *lcdev) 300 { 301 int ret; 302 303 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); 304 if (ret < 0) 305 return ret; 306 307 /* 308 * The controller needs 120ms when exiting from sleep mode before we 309 * can send the command to enter in sleep mode 310 */ 311 msleep(120); 312 313 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); 314 if (ret < 0) 315 return ret; 316 317 return 0; 318 } 319 320 static void hx8357_lcd_reset(struct lcd_device *lcdev) 321 { 322 struct hx8357_data *lcd = lcd_get_data(lcdev); 323 324 /* Reset the screen */ 325 gpio_set_value(lcd->reset, 1); 326 usleep_range(10000, 12000); 327 gpio_set_value(lcd->reset, 0); 328 usleep_range(10000, 12000); 329 gpio_set_value(lcd->reset, 1); 330 331 /* The controller needs 120ms to recover from reset */ 332 msleep(120); 333 } 334 335 static int hx8357_lcd_init(struct lcd_device *lcdev) 336 { 337 struct hx8357_data *lcd = lcd_get_data(lcdev); 338 int ret; 339 340 /* 341 * Set the interface selection pins to SPI mode, with three 342 * wires 343 */ 344 if (lcd->use_im_pins) { 345 gpio_set_value_cansleep(lcd->im_pins[0], 1); 346 gpio_set_value_cansleep(lcd->im_pins[1], 0); 347 gpio_set_value_cansleep(lcd->im_pins[2], 1); 348 } 349 350 ret = hx8357_spi_write_array(lcdev, hx8357_seq_power, 351 ARRAY_SIZE(hx8357_seq_power)); 352 if (ret < 0) 353 return ret; 354 355 ret = hx8357_spi_write_array(lcdev, hx8357_seq_vcom, 356 ARRAY_SIZE(hx8357_seq_vcom)); 357 if (ret < 0) 358 return ret; 359 360 ret = hx8357_spi_write_array(lcdev, hx8357_seq_power_normal, 361 ARRAY_SIZE(hx8357_seq_power_normal)); 362 if (ret < 0) 363 return ret; 364 365 ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_driving, 366 ARRAY_SIZE(hx8357_seq_panel_driving)); 367 if (ret < 0) 368 return ret; 369 370 ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_frame, 371 ARRAY_SIZE(hx8357_seq_display_frame)); 372 if (ret < 0) 373 return ret; 374 375 ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_related, 376 ARRAY_SIZE(hx8357_seq_panel_related)); 377 if (ret < 0) 378 return ret; 379 380 ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined1, 381 ARRAY_SIZE(hx8357_seq_undefined1)); 382 if (ret < 0) 383 return ret; 384 385 ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined2, 386 ARRAY_SIZE(hx8357_seq_undefined2)); 387 if (ret < 0) 388 return ret; 389 390 ret = hx8357_spi_write_array(lcdev, hx8357_seq_gamma, 391 ARRAY_SIZE(hx8357_seq_gamma)); 392 if (ret < 0) 393 return ret; 394 395 ret = hx8357_spi_write_array(lcdev, hx8357_seq_address_mode, 396 ARRAY_SIZE(hx8357_seq_address_mode)); 397 if (ret < 0) 398 return ret; 399 400 ret = hx8357_spi_write_array(lcdev, hx8357_seq_pixel_format, 401 ARRAY_SIZE(hx8357_seq_pixel_format)); 402 if (ret < 0) 403 return ret; 404 405 ret = hx8357_spi_write_array(lcdev, hx8357_seq_column_address, 406 ARRAY_SIZE(hx8357_seq_column_address)); 407 if (ret < 0) 408 return ret; 409 410 ret = hx8357_spi_write_array(lcdev, hx8357_seq_page_address, 411 ARRAY_SIZE(hx8357_seq_page_address)); 412 if (ret < 0) 413 return ret; 414 415 ret = hx8357_spi_write_array(lcdev, hx8357_seq_rgb, 416 ARRAY_SIZE(hx8357_seq_rgb)); 417 if (ret < 0) 418 return ret; 419 420 ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_mode, 421 ARRAY_SIZE(hx8357_seq_display_mode)); 422 if (ret < 0) 423 return ret; 424 425 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); 426 if (ret < 0) 427 return ret; 428 429 /* 430 * The controller needs 120ms to fully recover from exiting sleep mode 431 */ 432 msleep(120); 433 434 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); 435 if (ret < 0) 436 return ret; 437 438 usleep_range(5000, 7000); 439 440 ret = hx8357_spi_write_byte(lcdev, HX8357_WRITE_MEMORY_START); 441 if (ret < 0) 442 return ret; 443 444 return 0; 445 } 446 447 static int hx8369_lcd_init(struct lcd_device *lcdev) 448 { 449 int ret; 450 451 ret = hx8357_spi_write_array(lcdev, hx8369_seq_extension_command, 452 ARRAY_SIZE(hx8369_seq_extension_command)); 453 if (ret < 0) 454 return ret; 455 usleep_range(10000, 12000); 456 457 ret = hx8357_spi_write_array(lcdev, hx8369_seq_display_related, 458 ARRAY_SIZE(hx8369_seq_display_related)); 459 if (ret < 0) 460 return ret; 461 462 ret = hx8357_spi_write_array(lcdev, hx8369_seq_panel_waveform_cycle, 463 ARRAY_SIZE(hx8369_seq_panel_waveform_cycle)); 464 if (ret < 0) 465 return ret; 466 467 ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_address_mode, 468 ARRAY_SIZE(hx8369_seq_set_address_mode)); 469 if (ret < 0) 470 return ret; 471 472 ret = hx8357_spi_write_array(lcdev, hx8369_seq_vcom, 473 ARRAY_SIZE(hx8369_seq_vcom)); 474 if (ret < 0) 475 return ret; 476 477 ret = hx8357_spi_write_array(lcdev, hx8369_seq_gip, 478 ARRAY_SIZE(hx8369_seq_gip)); 479 if (ret < 0) 480 return ret; 481 482 ret = hx8357_spi_write_array(lcdev, hx8369_seq_power, 483 ARRAY_SIZE(hx8369_seq_power)); 484 if (ret < 0) 485 return ret; 486 487 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); 488 if (ret < 0) 489 return ret; 490 491 /* 492 * The controller needs 120ms to fully recover from exiting sleep mode 493 */ 494 msleep(120); 495 496 ret = hx8357_spi_write_array(lcdev, hx8369_seq_gamma_curve_related, 497 ARRAY_SIZE(hx8369_seq_gamma_curve_related)); 498 if (ret < 0) 499 return ret; 500 501 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); 502 if (ret < 0) 503 return ret; 504 usleep_range(1000, 1200); 505 506 ret = hx8357_spi_write_array(lcdev, hx8369_seq_write_CABC_control, 507 ARRAY_SIZE(hx8369_seq_write_CABC_control)); 508 if (ret < 0) 509 return ret; 510 usleep_range(10000, 12000); 511 512 ret = hx8357_spi_write_array(lcdev, 513 hx8369_seq_write_CABC_control_setting, 514 ARRAY_SIZE(hx8369_seq_write_CABC_control_setting)); 515 if (ret < 0) 516 return ret; 517 518 ret = hx8357_spi_write_array(lcdev, 519 hx8369_seq_write_CABC_min_brightness, 520 ARRAY_SIZE(hx8369_seq_write_CABC_min_brightness)); 521 if (ret < 0) 522 return ret; 523 usleep_range(10000, 12000); 524 525 ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_display_brightness, 526 ARRAY_SIZE(hx8369_seq_set_display_brightness)); 527 if (ret < 0) 528 return ret; 529 530 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); 531 if (ret < 0) 532 return ret; 533 534 return 0; 535 } 536 537 #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) 538 539 static int hx8357_set_power(struct lcd_device *lcdev, int power) 540 { 541 struct hx8357_data *lcd = lcd_get_data(lcdev); 542 int ret = 0; 543 544 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->state)) 545 ret = hx8357_exit_standby(lcdev); 546 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->state)) 547 ret = hx8357_enter_standby(lcdev); 548 549 if (ret == 0) 550 lcd->state = power; 551 else 552 dev_warn(&lcdev->dev, "failed to set power mode %d\n", power); 553 554 return ret; 555 } 556 557 static int hx8357_get_power(struct lcd_device *lcdev) 558 { 559 struct hx8357_data *lcd = lcd_get_data(lcdev); 560 561 return lcd->state; 562 } 563 564 static struct lcd_ops hx8357_ops = { 565 .set_power = hx8357_set_power, 566 .get_power = hx8357_get_power, 567 }; 568 569 static const struct of_device_id hx8357_dt_ids[] = { 570 { 571 .compatible = "himax,hx8357", 572 .data = hx8357_lcd_init, 573 }, 574 { 575 .compatible = "himax,hx8369", 576 .data = hx8369_lcd_init, 577 }, 578 {}, 579 }; 580 MODULE_DEVICE_TABLE(of, hx8357_dt_ids); 581 582 static int hx8357_probe(struct spi_device *spi) 583 { 584 struct lcd_device *lcdev; 585 struct hx8357_data *lcd; 586 const struct of_device_id *match; 587 int i, ret; 588 589 lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL); 590 if (!lcd) { 591 dev_err(&spi->dev, "Couldn't allocate lcd internal structure!\n"); 592 return -ENOMEM; 593 } 594 595 ret = spi_setup(spi); 596 if (ret < 0) { 597 dev_err(&spi->dev, "SPI setup failed.\n"); 598 return ret; 599 } 600 601 lcd->spi = spi; 602 603 match = of_match_device(hx8357_dt_ids, &spi->dev); 604 if (!match || !match->data) 605 return -EINVAL; 606 607 lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0); 608 if (!gpio_is_valid(lcd->reset)) { 609 dev_err(&spi->dev, "Missing dt property: gpios-reset\n"); 610 return -EINVAL; 611 } 612 613 ret = devm_gpio_request_one(&spi->dev, lcd->reset, 614 GPIOF_OUT_INIT_HIGH, 615 "hx8357-reset"); 616 if (ret) { 617 dev_err(&spi->dev, 618 "failed to request gpio %d: %d\n", 619 lcd->reset, ret); 620 return -EINVAL; 621 } 622 623 if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) { 624 lcd->use_im_pins = 1; 625 626 for (i = 0; i < HX8357_NUM_IM_PINS; i++) { 627 lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node, 628 "im-gpios", i); 629 if (lcd->im_pins[i] == -EPROBE_DEFER) { 630 dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n"); 631 return -EPROBE_DEFER; 632 } 633 if (!gpio_is_valid(lcd->im_pins[i])) { 634 dev_err(&spi->dev, "Missing dt property: im-gpios\n"); 635 return -EINVAL; 636 } 637 638 ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i], 639 GPIOF_OUT_INIT_LOW, 640 "im_pins"); 641 if (ret) { 642 dev_err(&spi->dev, "failed to request gpio %d: %d\n", 643 lcd->im_pins[i], ret); 644 return -EINVAL; 645 } 646 } 647 } else { 648 lcd->use_im_pins = 0; 649 } 650 651 lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd, 652 &hx8357_ops); 653 if (IS_ERR(lcdev)) { 654 ret = PTR_ERR(lcdev); 655 return ret; 656 } 657 spi_set_drvdata(spi, lcdev); 658 659 hx8357_lcd_reset(lcdev); 660 661 ret = ((int (*)(struct lcd_device *))match->data)(lcdev); 662 if (ret) { 663 dev_err(&spi->dev, "Couldn't initialize panel\n"); 664 return ret; 665 } 666 667 dev_info(&spi->dev, "Panel probed\n"); 668 669 return 0; 670 } 671 672 static struct spi_driver hx8357_driver = { 673 .probe = hx8357_probe, 674 .driver = { 675 .name = "hx8357", 676 .of_match_table = hx8357_dt_ids, 677 }, 678 }; 679 680 module_spi_driver(hx8357_driver); 681 682 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 683 MODULE_DESCRIPTION("Himax HX-8357 LCD Driver"); 684 MODULE_LICENSE("GPL"); 685