Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / video / backlight / hx8357.c
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
85 struct 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
93 static u8 hx8357_seq_power[] = {
94         HX8357_SET_POWER, 0x44, 0x41, 0x06,
95 };
96
97 static u8 hx8357_seq_vcom[] = {
98         HX8357_SET_VCOM, 0x40, 0x10,
99 };
100
101 static u8 hx8357_seq_power_normal[] = {
102         HX8357_SET_POWER_NORMAL, 0x05, 0x12,
103 };
104
105 static u8 hx8357_seq_panel_driving[] = {
106         HX8357_SET_PANEL_DRIVING, 0x14, 0x3b, 0x00, 0x02, 0x11,
107 };
108
109 static u8 hx8357_seq_display_frame[] = {
110         HX8357_SET_DISPLAY_FRAME, 0x0c,
111 };
112
113 static u8 hx8357_seq_panel_related[] = {
114         HX8357_SET_PANEL_RELATED, 0x01,
115 };
116
117 static u8 hx8357_seq_undefined1[] = {
118         0xea, 0x03, 0x00, 0x00,
119 };
120
121 static u8 hx8357_seq_undefined2[] = {
122         0xeb, 0x40, 0x54, 0x26, 0xdb,
123 };
124
125 static u8 hx8357_seq_gamma[] = {
126         HX8357_SET_GAMMA, 0x00, 0x15, 0x00, 0x22, 0x00,
127         0x08, 0x77, 0x26, 0x77, 0x22, 0x04, 0x00,
128 };
129
130 static u8 hx8357_seq_address_mode[] = {
131         HX8357_SET_ADDRESS_MODE, 0xc0,
132 };
133
134 static 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
140 static u8 hx8357_seq_column_address[] = {
141         HX8357_SET_COLUMN_ADDRESS, 0x00, 0x00, 0x01, 0x3f,
142 };
143
144 static u8 hx8357_seq_page_address[] = {
145         HX8357_SET_PAGE_ADDRESS, 0x00, 0x00, 0x01, 0xdf,
146 };
147
148 static u8 hx8357_seq_rgb[] = {
149         HX8357_SET_RGB, 0x02,
150 };
151
152 static 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
158 static u8 hx8369_seq_write_CABC_min_brightness[] = {
159         HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00,
160 };
161
162 static u8 hx8369_seq_write_CABC_control[] = {
163         HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24,
164 };
165
166 static u8 hx8369_seq_set_display_brightness[] = {
167         HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF,
168 };
169
170 static u8 hx8369_seq_write_CABC_control_setting[] = {
171         HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02,
172 };
173
174 static u8 hx8369_seq_extension_command[] = {
175         HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69,
176 };
177
178 static 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
183 static u8 hx8369_seq_panel_waveform_cycle[] = {
184         HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02,
185 };
186
187 static u8 hx8369_seq_set_address_mode[] = {
188         HX8357_SET_ADDRESS_MODE, 0x00,
189 };
190
191 static u8 hx8369_seq_vcom[] = {
192         HX8369_SET_VCOM, 0x3e, 0x3e,
193 };
194
195 static 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
201 static 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
206 static 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
213 static 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
263 static 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
269 static 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
275 static 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
298 static 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
319 static 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
334 static 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
446 static 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
538 static 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
556 static 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
563 static struct lcd_ops hx8357_ops = {
564         .set_power      = hx8357_set_power,
565         .get_power      = hx8357_get_power,
566 };
567
568 static 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 };
579 MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
580
581 static 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
669 static struct spi_driver hx8357_driver = {
670         .probe  = hx8357_probe,
671         .driver = {
672                 .name = "hx8357",
673                 .of_match_table = hx8357_dt_ids,
674         },
675 };
676
677 module_spi_driver(hx8357_driver);
678
679 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
680 MODULE_DESCRIPTION("Himax HX-8357 LCD Driver");
681 MODULE_LICENSE("GPL");