0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/lcd.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_device.h>
0013 #include <linux/of_gpio.h>
0014 #include <linux/spi/spi.h>
0015
0016 #define HX8357_NUM_IM_PINS 3
0017
0018 #define HX8357_SWRESET 0x01
0019 #define HX8357_GET_RED_CHANNEL 0x06
0020 #define HX8357_GET_GREEN_CHANNEL 0x07
0021 #define HX8357_GET_BLUE_CHANNEL 0x08
0022 #define HX8357_GET_POWER_MODE 0x0a
0023 #define HX8357_GET_MADCTL 0x0b
0024 #define HX8357_GET_PIXEL_FORMAT 0x0c
0025 #define HX8357_GET_DISPLAY_MODE 0x0d
0026 #define HX8357_GET_SIGNAL_MODE 0x0e
0027 #define HX8357_GET_DIAGNOSTIC_RESULT 0x0f
0028 #define HX8357_ENTER_SLEEP_MODE 0x10
0029 #define HX8357_EXIT_SLEEP_MODE 0x11
0030 #define HX8357_ENTER_PARTIAL_MODE 0x12
0031 #define HX8357_ENTER_NORMAL_MODE 0x13
0032 #define HX8357_EXIT_INVERSION_MODE 0x20
0033 #define HX8357_ENTER_INVERSION_MODE 0x21
0034 #define HX8357_SET_DISPLAY_OFF 0x28
0035 #define HX8357_SET_DISPLAY_ON 0x29
0036 #define HX8357_SET_COLUMN_ADDRESS 0x2a
0037 #define HX8357_SET_PAGE_ADDRESS 0x2b
0038 #define HX8357_WRITE_MEMORY_START 0x2c
0039 #define HX8357_READ_MEMORY_START 0x2e
0040 #define HX8357_SET_PARTIAL_AREA 0x30
0041 #define HX8357_SET_SCROLL_AREA 0x33
0042 #define HX8357_SET_TEAR_OFF 0x34
0043 #define HX8357_SET_TEAR_ON 0x35
0044 #define HX8357_SET_ADDRESS_MODE 0x36
0045 #define HX8357_SET_SCROLL_START 0x37
0046 #define HX8357_EXIT_IDLE_MODE 0x38
0047 #define HX8357_ENTER_IDLE_MODE 0x39
0048 #define HX8357_SET_PIXEL_FORMAT 0x3a
0049 #define HX8357_SET_PIXEL_FORMAT_DBI_3BIT (0x1)
0050 #define HX8357_SET_PIXEL_FORMAT_DBI_16BIT (0x5)
0051 #define HX8357_SET_PIXEL_FORMAT_DBI_18BIT (0x6)
0052 #define HX8357_SET_PIXEL_FORMAT_DPI_3BIT (0x1 << 4)
0053 #define HX8357_SET_PIXEL_FORMAT_DPI_16BIT (0x5 << 4)
0054 #define HX8357_SET_PIXEL_FORMAT_DPI_18BIT (0x6 << 4)
0055 #define HX8357_WRITE_MEMORY_CONTINUE 0x3c
0056 #define HX8357_READ_MEMORY_CONTINUE 0x3e
0057 #define HX8357_SET_TEAR_SCAN_LINES 0x44
0058 #define HX8357_GET_SCAN_LINES 0x45
0059 #define HX8357_READ_DDB_START 0xa1
0060 #define HX8357_SET_DISPLAY_MODE 0xb4
0061 #define HX8357_SET_DISPLAY_MODE_RGB_THROUGH (0x3)
0062 #define HX8357_SET_DISPLAY_MODE_RGB_INTERFACE (1 << 4)
0063 #define HX8357_SET_PANEL_DRIVING 0xc0
0064 #define HX8357_SET_DISPLAY_FRAME 0xc5
0065 #define HX8357_SET_RGB 0xc6
0066 #define HX8357_SET_RGB_ENABLE_HIGH (1 << 1)
0067 #define HX8357_SET_GAMMA 0xc8
0068 #define HX8357_SET_POWER 0xd0
0069 #define HX8357_SET_VCOM 0xd1
0070 #define HX8357_SET_POWER_NORMAL 0xd2
0071 #define HX8357_SET_PANEL_RELATED 0xe9
0072
0073 #define HX8369_SET_DISPLAY_BRIGHTNESS 0x51
0074 #define HX8369_WRITE_CABC_DISPLAY_VALUE 0x53
0075 #define HX8369_WRITE_CABC_BRIGHT_CTRL 0x55
0076 #define HX8369_WRITE_CABC_MIN_BRIGHTNESS 0x5e
0077 #define HX8369_SET_POWER 0xb1
0078 #define HX8369_SET_DISPLAY_MODE 0xb2
0079 #define HX8369_SET_DISPLAY_WAVEFORM_CYC 0xb4
0080 #define HX8369_SET_VCOM 0xb6
0081 #define HX8369_SET_EXTENSION_COMMAND 0xb9
0082 #define HX8369_SET_GIP 0xd5
0083 #define HX8369_SET_GAMMA_CURVE_RELATED 0xe0
0084
0085 struct hx8357_data {
0086 unsigned im_pins[HX8357_NUM_IM_PINS];
0087 unsigned reset;
0088 struct spi_device *spi;
0089 int state;
0090 bool use_im_pins;
0091 };
0092
0093 static u8 hx8357_seq_power[] = {
0094 HX8357_SET_POWER, 0x44, 0x41, 0x06,
0095 };
0096
0097 static u8 hx8357_seq_vcom[] = {
0098 HX8357_SET_VCOM, 0x40, 0x10,
0099 };
0100
0101 static u8 hx8357_seq_power_normal[] = {
0102 HX8357_SET_POWER_NORMAL, 0x05, 0x12,
0103 };
0104
0105 static u8 hx8357_seq_panel_driving[] = {
0106 HX8357_SET_PANEL_DRIVING, 0x14, 0x3b, 0x00, 0x02, 0x11,
0107 };
0108
0109 static u8 hx8357_seq_display_frame[] = {
0110 HX8357_SET_DISPLAY_FRAME, 0x0c,
0111 };
0112
0113 static u8 hx8357_seq_panel_related[] = {
0114 HX8357_SET_PANEL_RELATED, 0x01,
0115 };
0116
0117 static u8 hx8357_seq_undefined1[] = {
0118 0xea, 0x03, 0x00, 0x00,
0119 };
0120
0121 static u8 hx8357_seq_undefined2[] = {
0122 0xeb, 0x40, 0x54, 0x26, 0xdb,
0123 };
0124
0125 static u8 hx8357_seq_gamma[] = {
0126 HX8357_SET_GAMMA, 0x00, 0x15, 0x00, 0x22, 0x00,
0127 0x08, 0x77, 0x26, 0x77, 0x22, 0x04, 0x00,
0128 };
0129
0130 static u8 hx8357_seq_address_mode[] = {
0131 HX8357_SET_ADDRESS_MODE, 0xc0,
0132 };
0133
0134 static u8 hx8357_seq_pixel_format[] = {
0135 HX8357_SET_PIXEL_FORMAT,
0136 HX8357_SET_PIXEL_FORMAT_DPI_18BIT |
0137 HX8357_SET_PIXEL_FORMAT_DBI_18BIT,
0138 };
0139
0140 static u8 hx8357_seq_column_address[] = {
0141 HX8357_SET_COLUMN_ADDRESS, 0x00, 0x00, 0x01, 0x3f,
0142 };
0143
0144 static u8 hx8357_seq_page_address[] = {
0145 HX8357_SET_PAGE_ADDRESS, 0x00, 0x00, 0x01, 0xdf,
0146 };
0147
0148 static u8 hx8357_seq_rgb[] = {
0149 HX8357_SET_RGB, 0x02,
0150 };
0151
0152 static u8 hx8357_seq_display_mode[] = {
0153 HX8357_SET_DISPLAY_MODE,
0154 HX8357_SET_DISPLAY_MODE_RGB_THROUGH |
0155 HX8357_SET_DISPLAY_MODE_RGB_INTERFACE,
0156 };
0157
0158 static u8 hx8369_seq_write_CABC_min_brightness[] = {
0159 HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00,
0160 };
0161
0162 static u8 hx8369_seq_write_CABC_control[] = {
0163 HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24,
0164 };
0165
0166 static u8 hx8369_seq_set_display_brightness[] = {
0167 HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF,
0168 };
0169
0170 static u8 hx8369_seq_write_CABC_control_setting[] = {
0171 HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02,
0172 };
0173
0174 static u8 hx8369_seq_extension_command[] = {
0175 HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69,
0176 };
0177
0178 static u8 hx8369_seq_display_related[] = {
0179 HX8369_SET_DISPLAY_MODE, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00,
0180 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x01,
0181 };
0182
0183 static u8 hx8369_seq_panel_waveform_cycle[] = {
0184 HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02,
0185 };
0186
0187 static u8 hx8369_seq_set_address_mode[] = {
0188 HX8357_SET_ADDRESS_MODE, 0x00,
0189 };
0190
0191 static u8 hx8369_seq_vcom[] = {
0192 HX8369_SET_VCOM, 0x3e, 0x3e,
0193 };
0194
0195 static u8 hx8369_seq_gip[] = {
0196 HX8369_SET_GIP, 0x00, 0x01, 0x03, 0x25, 0x01, 0x02, 0x28, 0x70,
0197 0x11, 0x13, 0x00, 0x00, 0x40, 0x26, 0x51, 0x37, 0x00, 0x00, 0x71,
0198 0x35, 0x60, 0x24, 0x07, 0x0f, 0x04, 0x04,
0199 };
0200
0201 static u8 hx8369_seq_power[] = {
0202 HX8369_SET_POWER, 0x01, 0x00, 0x34, 0x03, 0x00, 0x11, 0x11, 0x32,
0203 0x2f, 0x3f, 0x3f, 0x01, 0x3a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
0204 };
0205
0206 static u8 hx8369_seq_gamma_curve_related[] = {
0207 HX8369_SET_GAMMA_CURVE_RELATED, 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d,
0208 0x2e, 0x4a, 0x08, 0x0e, 0x0f, 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
0209 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 0x2e, 0x4a, 0x08, 0x0e, 0x0f,
0210 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e,
0211 };
0212
0213 static int hx8357_spi_write_then_read(struct lcd_device *lcdev,
0214 u8 *txbuf, u16 txlen,
0215 u8 *rxbuf, u16 rxlen)
0216 {
0217 struct hx8357_data *lcd = lcd_get_data(lcdev);
0218 struct spi_message msg;
0219 struct spi_transfer xfer[2];
0220 u16 *local_txbuf = NULL;
0221 int ret = 0;
0222
0223 memset(xfer, 0, sizeof(xfer));
0224 spi_message_init(&msg);
0225
0226 if (txlen) {
0227 int i;
0228
0229 local_txbuf = kcalloc(txlen, sizeof(*local_txbuf), GFP_KERNEL);
0230
0231 if (!local_txbuf)
0232 return -ENOMEM;
0233
0234 for (i = 0; i < txlen; i++) {
0235 local_txbuf[i] = txbuf[i];
0236 if (i > 0)
0237 local_txbuf[i] |= 1 << 8;
0238 }
0239
0240 xfer[0].len = 2 * txlen;
0241 xfer[0].bits_per_word = 9;
0242 xfer[0].tx_buf = local_txbuf;
0243 spi_message_add_tail(&xfer[0], &msg);
0244 }
0245
0246 if (rxlen) {
0247 xfer[1].len = rxlen;
0248 xfer[1].bits_per_word = 8;
0249 xfer[1].rx_buf = rxbuf;
0250 spi_message_add_tail(&xfer[1], &msg);
0251 }
0252
0253 ret = spi_sync(lcd->spi, &msg);
0254 if (ret < 0)
0255 dev_err(&lcdev->dev, "Couldn't send SPI data\n");
0256
0257 if (txlen)
0258 kfree(local_txbuf);
0259
0260 return ret;
0261 }
0262
0263 static inline int hx8357_spi_write_array(struct lcd_device *lcdev,
0264 u8 *value, u8 len)
0265 {
0266 return hx8357_spi_write_then_read(lcdev, value, len, NULL, 0);
0267 }
0268
0269 static inline int hx8357_spi_write_byte(struct lcd_device *lcdev,
0270 u8 value)
0271 {
0272 return hx8357_spi_write_then_read(lcdev, &value, 1, NULL, 0);
0273 }
0274
0275 static int hx8357_enter_standby(struct lcd_device *lcdev)
0276 {
0277 int ret;
0278
0279 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_OFF);
0280 if (ret < 0)
0281 return ret;
0282
0283 usleep_range(10000, 12000);
0284
0285 ret = hx8357_spi_write_byte(lcdev, HX8357_ENTER_SLEEP_MODE);
0286 if (ret < 0)
0287 return ret;
0288
0289
0290
0291
0292
0293 msleep(120);
0294
0295 return 0;
0296 }
0297
0298 static int hx8357_exit_standby(struct lcd_device *lcdev)
0299 {
0300 int ret;
0301
0302 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
0303 if (ret < 0)
0304 return ret;
0305
0306
0307
0308
0309
0310 msleep(120);
0311
0312 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
0313 if (ret < 0)
0314 return ret;
0315
0316 return 0;
0317 }
0318
0319 static void hx8357_lcd_reset(struct lcd_device *lcdev)
0320 {
0321 struct hx8357_data *lcd = lcd_get_data(lcdev);
0322
0323
0324 gpio_set_value(lcd->reset, 1);
0325 usleep_range(10000, 12000);
0326 gpio_set_value(lcd->reset, 0);
0327 usleep_range(10000, 12000);
0328 gpio_set_value(lcd->reset, 1);
0329
0330
0331 msleep(120);
0332 }
0333
0334 static int hx8357_lcd_init(struct lcd_device *lcdev)
0335 {
0336 struct hx8357_data *lcd = lcd_get_data(lcdev);
0337 int ret;
0338
0339
0340
0341
0342
0343 if (lcd->use_im_pins) {
0344 gpio_set_value_cansleep(lcd->im_pins[0], 1);
0345 gpio_set_value_cansleep(lcd->im_pins[1], 0);
0346 gpio_set_value_cansleep(lcd->im_pins[2], 1);
0347 }
0348
0349 ret = hx8357_spi_write_array(lcdev, hx8357_seq_power,
0350 ARRAY_SIZE(hx8357_seq_power));
0351 if (ret < 0)
0352 return ret;
0353
0354 ret = hx8357_spi_write_array(lcdev, hx8357_seq_vcom,
0355 ARRAY_SIZE(hx8357_seq_vcom));
0356 if (ret < 0)
0357 return ret;
0358
0359 ret = hx8357_spi_write_array(lcdev, hx8357_seq_power_normal,
0360 ARRAY_SIZE(hx8357_seq_power_normal));
0361 if (ret < 0)
0362 return ret;
0363
0364 ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_driving,
0365 ARRAY_SIZE(hx8357_seq_panel_driving));
0366 if (ret < 0)
0367 return ret;
0368
0369 ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_frame,
0370 ARRAY_SIZE(hx8357_seq_display_frame));
0371 if (ret < 0)
0372 return ret;
0373
0374 ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_related,
0375 ARRAY_SIZE(hx8357_seq_panel_related));
0376 if (ret < 0)
0377 return ret;
0378
0379 ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined1,
0380 ARRAY_SIZE(hx8357_seq_undefined1));
0381 if (ret < 0)
0382 return ret;
0383
0384 ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined2,
0385 ARRAY_SIZE(hx8357_seq_undefined2));
0386 if (ret < 0)
0387 return ret;
0388
0389 ret = hx8357_spi_write_array(lcdev, hx8357_seq_gamma,
0390 ARRAY_SIZE(hx8357_seq_gamma));
0391 if (ret < 0)
0392 return ret;
0393
0394 ret = hx8357_spi_write_array(lcdev, hx8357_seq_address_mode,
0395 ARRAY_SIZE(hx8357_seq_address_mode));
0396 if (ret < 0)
0397 return ret;
0398
0399 ret = hx8357_spi_write_array(lcdev, hx8357_seq_pixel_format,
0400 ARRAY_SIZE(hx8357_seq_pixel_format));
0401 if (ret < 0)
0402 return ret;
0403
0404 ret = hx8357_spi_write_array(lcdev, hx8357_seq_column_address,
0405 ARRAY_SIZE(hx8357_seq_column_address));
0406 if (ret < 0)
0407 return ret;
0408
0409 ret = hx8357_spi_write_array(lcdev, hx8357_seq_page_address,
0410 ARRAY_SIZE(hx8357_seq_page_address));
0411 if (ret < 0)
0412 return ret;
0413
0414 ret = hx8357_spi_write_array(lcdev, hx8357_seq_rgb,
0415 ARRAY_SIZE(hx8357_seq_rgb));
0416 if (ret < 0)
0417 return ret;
0418
0419 ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_mode,
0420 ARRAY_SIZE(hx8357_seq_display_mode));
0421 if (ret < 0)
0422 return ret;
0423
0424 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
0425 if (ret < 0)
0426 return ret;
0427
0428
0429
0430
0431 msleep(120);
0432
0433 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
0434 if (ret < 0)
0435 return ret;
0436
0437 usleep_range(5000, 7000);
0438
0439 ret = hx8357_spi_write_byte(lcdev, HX8357_WRITE_MEMORY_START);
0440 if (ret < 0)
0441 return ret;
0442
0443 return 0;
0444 }
0445
0446 static int hx8369_lcd_init(struct lcd_device *lcdev)
0447 {
0448 int ret;
0449
0450 ret = hx8357_spi_write_array(lcdev, hx8369_seq_extension_command,
0451 ARRAY_SIZE(hx8369_seq_extension_command));
0452 if (ret < 0)
0453 return ret;
0454 usleep_range(10000, 12000);
0455
0456 ret = hx8357_spi_write_array(lcdev, hx8369_seq_display_related,
0457 ARRAY_SIZE(hx8369_seq_display_related));
0458 if (ret < 0)
0459 return ret;
0460
0461 ret = hx8357_spi_write_array(lcdev, hx8369_seq_panel_waveform_cycle,
0462 ARRAY_SIZE(hx8369_seq_panel_waveform_cycle));
0463 if (ret < 0)
0464 return ret;
0465
0466 ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_address_mode,
0467 ARRAY_SIZE(hx8369_seq_set_address_mode));
0468 if (ret < 0)
0469 return ret;
0470
0471 ret = hx8357_spi_write_array(lcdev, hx8369_seq_vcom,
0472 ARRAY_SIZE(hx8369_seq_vcom));
0473 if (ret < 0)
0474 return ret;
0475
0476 ret = hx8357_spi_write_array(lcdev, hx8369_seq_gip,
0477 ARRAY_SIZE(hx8369_seq_gip));
0478 if (ret < 0)
0479 return ret;
0480
0481 ret = hx8357_spi_write_array(lcdev, hx8369_seq_power,
0482 ARRAY_SIZE(hx8369_seq_power));
0483 if (ret < 0)
0484 return ret;
0485
0486 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
0487 if (ret < 0)
0488 return ret;
0489
0490
0491
0492
0493 msleep(120);
0494
0495 ret = hx8357_spi_write_array(lcdev, hx8369_seq_gamma_curve_related,
0496 ARRAY_SIZE(hx8369_seq_gamma_curve_related));
0497 if (ret < 0)
0498 return ret;
0499
0500 ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
0501 if (ret < 0)
0502 return ret;
0503 usleep_range(1000, 1200);
0504
0505 ret = hx8357_spi_write_array(lcdev, hx8369_seq_write_CABC_control,
0506 ARRAY_SIZE(hx8369_seq_write_CABC_control));
0507 if (ret < 0)
0508 return ret;
0509 usleep_range(10000, 12000);
0510
0511 ret = hx8357_spi_write_array(lcdev,
0512 hx8369_seq_write_CABC_control_setting,
0513 ARRAY_SIZE(hx8369_seq_write_CABC_control_setting));
0514 if (ret < 0)
0515 return ret;
0516
0517 ret = hx8357_spi_write_array(lcdev,
0518 hx8369_seq_write_CABC_min_brightness,
0519 ARRAY_SIZE(hx8369_seq_write_CABC_min_brightness));
0520 if (ret < 0)
0521 return ret;
0522 usleep_range(10000, 12000);
0523
0524 ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_display_brightness,
0525 ARRAY_SIZE(hx8369_seq_set_display_brightness));
0526 if (ret < 0)
0527 return ret;
0528
0529 ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
0530 if (ret < 0)
0531 return ret;
0532
0533 return 0;
0534 }
0535
0536 #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
0537
0538 static int hx8357_set_power(struct lcd_device *lcdev, int power)
0539 {
0540 struct hx8357_data *lcd = lcd_get_data(lcdev);
0541 int ret = 0;
0542
0543 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->state))
0544 ret = hx8357_exit_standby(lcdev);
0545 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->state))
0546 ret = hx8357_enter_standby(lcdev);
0547
0548 if (ret == 0)
0549 lcd->state = power;
0550 else
0551 dev_warn(&lcdev->dev, "failed to set power mode %d\n", power);
0552
0553 return ret;
0554 }
0555
0556 static int hx8357_get_power(struct lcd_device *lcdev)
0557 {
0558 struct hx8357_data *lcd = lcd_get_data(lcdev);
0559
0560 return lcd->state;
0561 }
0562
0563 static struct lcd_ops hx8357_ops = {
0564 .set_power = hx8357_set_power,
0565 .get_power = hx8357_get_power,
0566 };
0567
0568 static const struct of_device_id hx8357_dt_ids[] = {
0569 {
0570 .compatible = "himax,hx8357",
0571 .data = hx8357_lcd_init,
0572 },
0573 {
0574 .compatible = "himax,hx8369",
0575 .data = hx8369_lcd_init,
0576 },
0577 {},
0578 };
0579 MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
0580
0581 static int hx8357_probe(struct spi_device *spi)
0582 {
0583 struct lcd_device *lcdev;
0584 struct hx8357_data *lcd;
0585 const struct of_device_id *match;
0586 int i, ret;
0587
0588 lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
0589 if (!lcd)
0590 return -ENOMEM;
0591
0592 ret = spi_setup(spi);
0593 if (ret < 0) {
0594 dev_err(&spi->dev, "SPI setup failed.\n");
0595 return ret;
0596 }
0597
0598 lcd->spi = spi;
0599
0600 match = of_match_device(hx8357_dt_ids, &spi->dev);
0601 if (!match || !match->data)
0602 return -EINVAL;
0603
0604 lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
0605 if (!gpio_is_valid(lcd->reset)) {
0606 dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
0607 return -EINVAL;
0608 }
0609
0610 ret = devm_gpio_request_one(&spi->dev, lcd->reset,
0611 GPIOF_OUT_INIT_HIGH,
0612 "hx8357-reset");
0613 if (ret) {
0614 dev_err(&spi->dev,
0615 "failed to request gpio %d: %d\n",
0616 lcd->reset, ret);
0617 return -EINVAL;
0618 }
0619
0620 if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) {
0621 lcd->use_im_pins = 1;
0622
0623 for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
0624 lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
0625 "im-gpios", i);
0626 if (lcd->im_pins[i] == -EPROBE_DEFER) {
0627 dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
0628 return -EPROBE_DEFER;
0629 }
0630 if (!gpio_is_valid(lcd->im_pins[i])) {
0631 dev_err(&spi->dev, "Missing dt property: im-gpios\n");
0632 return -EINVAL;
0633 }
0634
0635 ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
0636 GPIOF_OUT_INIT_LOW,
0637 "im_pins");
0638 if (ret) {
0639 dev_err(&spi->dev, "failed to request gpio %d: %d\n",
0640 lcd->im_pins[i], ret);
0641 return -EINVAL;
0642 }
0643 }
0644 } else {
0645 lcd->use_im_pins = 0;
0646 }
0647
0648 lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd,
0649 &hx8357_ops);
0650 if (IS_ERR(lcdev)) {
0651 ret = PTR_ERR(lcdev);
0652 return ret;
0653 }
0654 spi_set_drvdata(spi, lcdev);
0655
0656 hx8357_lcd_reset(lcdev);
0657
0658 ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
0659 if (ret) {
0660 dev_err(&spi->dev, "Couldn't initialize panel\n");
0661 return ret;
0662 }
0663
0664 dev_info(&spi->dev, "Panel probed\n");
0665
0666 return 0;
0667 }
0668
0669 static struct spi_driver hx8357_driver = {
0670 .probe = hx8357_probe,
0671 .driver = {
0672 .name = "hx8357",
0673 .of_match_table = hx8357_dt_ids,
0674 },
0675 };
0676
0677 module_spi_driver(hx8357_driver);
0678
0679 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
0680 MODULE_DESCRIPTION("Himax HX-8357 LCD Driver");
0681 MODULE_LICENSE("GPL");