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