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