Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/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");
683 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us