Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[deliverable/linux.git] / drivers / video / backlight / hx8357.c
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 return -ENOMEM;
592
593 ret = spi_setup(spi);
594 if (ret < 0) {
595 dev_err(&spi->dev, "SPI setup failed.\n");
596 return ret;
597 }
598
599 lcd->spi = spi;
600
601 match = of_match_device(hx8357_dt_ids, &spi->dev);
602 if (!match || !match->data)
603 return -EINVAL;
604
605 lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
606 if (!gpio_is_valid(lcd->reset)) {
607 dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
608 return -EINVAL;
609 }
610
611 ret = devm_gpio_request_one(&spi->dev, lcd->reset,
612 GPIOF_OUT_INIT_HIGH,
613 "hx8357-reset");
614 if (ret) {
615 dev_err(&spi->dev,
616 "failed to request gpio %d: %d\n",
617 lcd->reset, ret);
618 return -EINVAL;
619 }
620
621 if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) {
622 lcd->use_im_pins = 1;
623
624 for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
625 lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
626 "im-gpios", i);
627 if (lcd->im_pins[i] == -EPROBE_DEFER) {
628 dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
629 return -EPROBE_DEFER;
630 }
631 if (!gpio_is_valid(lcd->im_pins[i])) {
632 dev_err(&spi->dev, "Missing dt property: im-gpios\n");
633 return -EINVAL;
634 }
635
636 ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
637 GPIOF_OUT_INIT_LOW,
638 "im_pins");
639 if (ret) {
640 dev_err(&spi->dev, "failed to request gpio %d: %d\n",
641 lcd->im_pins[i], ret);
642 return -EINVAL;
643 }
644 }
645 } else {
646 lcd->use_im_pins = 0;
647 }
648
649 lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd,
650 &hx8357_ops);
651 if (IS_ERR(lcdev)) {
652 ret = PTR_ERR(lcdev);
653 return ret;
654 }
655 spi_set_drvdata(spi, lcdev);
656
657 hx8357_lcd_reset(lcdev);
658
659 ret = ((int (*)(struct lcd_device *))match->data)(lcdev);
660 if (ret) {
661 dev_err(&spi->dev, "Couldn't initialize panel\n");
662 return ret;
663 }
664
665 dev_info(&spi->dev, "Panel probed\n");
666
667 return 0;
668 }
669
670 static struct spi_driver hx8357_driver = {
671 .probe = hx8357_probe,
672 .driver = {
673 .name = "hx8357",
674 .of_match_table = hx8357_dt_ids,
675 },
676 };
677
678 module_spi_driver(hx8357_driver);
679
680 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
681 MODULE_DESCRIPTION("Himax HX-8357 LCD Driver");
682 MODULE_LICENSE("GPL");
This page took 0.044513 seconds and 5 git commands to generate.