• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ld9040 AMOLED LCD panel driver.
3  *
4  * Copyright (c) 2011 Samsung Electronics
5  * Author: Donghwa Lee  <dh09.lee@samsung.com>
6  * Derived from drivers/video/backlight/s6e63m0.c
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  */
13 
14 #include <linux/backlight.h>
15 #include <linux/delay.h>
16 #include <linux/fb.h>
17 #include <linux/gpio.h>
18 #include <linux/interrupt.h>
19 #include <linux/irq.h>
20 #include <linux/kernel.h>
21 #include <linux/lcd.h>
22 #include <linux/module.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/spi/spi.h>
25 #include <linux/wait.h>
26 
27 #include "ld9040_gamma.h"
28 
29 #define SLEEPMSEC		0x1000
30 #define ENDDEF			0x2000
31 #define	DEFMASK			0xFF00
32 #define COMMAND_ONLY		0xFE
33 #define DATA_ONLY		0xFF
34 
35 #define MIN_BRIGHTNESS		0
36 #define MAX_BRIGHTNESS		24
37 
38 struct ld9040 {
39 	struct device			*dev;
40 	struct spi_device		*spi;
41 	unsigned int			power;
42 	unsigned int			current_brightness;
43 
44 	struct lcd_device		*ld;
45 	struct backlight_device		*bd;
46 	struct lcd_platform_data	*lcd_pd;
47 
48 	struct mutex			lock;
49 	bool  enabled;
50 };
51 
52 static struct regulator_bulk_data supplies[] = {
53 	{ .supply = "vdd3", },
54 	{ .supply = "vci", },
55 };
56 
ld9040_regulator_enable(struct ld9040 * lcd)57 static void ld9040_regulator_enable(struct ld9040 *lcd)
58 {
59 	int ret = 0;
60 	struct lcd_platform_data *pd = NULL;
61 
62 	pd = lcd->lcd_pd;
63 	mutex_lock(&lcd->lock);
64 	if (!lcd->enabled) {
65 		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
66 		if (ret)
67 			goto out;
68 
69 		lcd->enabled = true;
70 	}
71 	msleep(pd->power_on_delay);
72 out:
73 	mutex_unlock(&lcd->lock);
74 }
75 
ld9040_regulator_disable(struct ld9040 * lcd)76 static void ld9040_regulator_disable(struct ld9040 *lcd)
77 {
78 	int ret = 0;
79 
80 	mutex_lock(&lcd->lock);
81 	if (lcd->enabled) {
82 		ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
83 		if (ret)
84 			goto out;
85 
86 		lcd->enabled = false;
87 	}
88 out:
89 	mutex_unlock(&lcd->lock);
90 }
91 
92 static const unsigned short seq_swreset[] = {
93 	0x01, COMMAND_ONLY,
94 	ENDDEF, 0x00
95 };
96 
97 static const unsigned short seq_user_setting[] = {
98 	0xF0, 0x5A,
99 
100 	DATA_ONLY, 0x5A,
101 	ENDDEF, 0x00
102 };
103 
104 static const unsigned short seq_elvss_on[] = {
105 	0xB1, 0x0D,
106 
107 	DATA_ONLY, 0x00,
108 	DATA_ONLY, 0x16,
109 	ENDDEF, 0x00
110 };
111 
112 static const unsigned short seq_gtcon[] = {
113 	0xF7, 0x09,
114 
115 	DATA_ONLY, 0x00,
116 	DATA_ONLY, 0x00,
117 	ENDDEF, 0x00
118 };
119 
120 static const unsigned short seq_panel_condition[] = {
121 	0xF8, 0x05,
122 
123 	DATA_ONLY, 0x65,
124 	DATA_ONLY, 0x96,
125 	DATA_ONLY, 0x71,
126 	DATA_ONLY, 0x7D,
127 	DATA_ONLY, 0x19,
128 	DATA_ONLY, 0x3B,
129 	DATA_ONLY, 0x0D,
130 	DATA_ONLY, 0x19,
131 	DATA_ONLY, 0x7E,
132 	DATA_ONLY, 0x0D,
133 	DATA_ONLY, 0xE2,
134 	DATA_ONLY, 0x00,
135 	DATA_ONLY, 0x00,
136 	DATA_ONLY, 0x7E,
137 	DATA_ONLY, 0x7D,
138 	DATA_ONLY, 0x07,
139 	DATA_ONLY, 0x07,
140 	DATA_ONLY, 0x20,
141 	DATA_ONLY, 0x20,
142 	DATA_ONLY, 0x20,
143 	DATA_ONLY, 0x02,
144 	DATA_ONLY, 0x02,
145 	ENDDEF, 0x00
146 };
147 
148 static const unsigned short seq_gamma_set1[] = {
149 	0xF9, 0x00,
150 
151 	DATA_ONLY, 0xA7,
152 	DATA_ONLY, 0xB4,
153 	DATA_ONLY, 0xAE,
154 	DATA_ONLY, 0xBF,
155 	DATA_ONLY, 0x00,
156 	DATA_ONLY, 0x91,
157 	DATA_ONLY, 0x00,
158 	DATA_ONLY, 0xB2,
159 	DATA_ONLY, 0xB4,
160 	DATA_ONLY, 0xAA,
161 	DATA_ONLY, 0xBB,
162 	DATA_ONLY, 0x00,
163 	DATA_ONLY, 0xAC,
164 	DATA_ONLY, 0x00,
165 	DATA_ONLY, 0xB3,
166 	DATA_ONLY, 0xB1,
167 	DATA_ONLY, 0xAA,
168 	DATA_ONLY, 0xBC,
169 	DATA_ONLY, 0x00,
170 	DATA_ONLY, 0xB3,
171 	ENDDEF, 0x00
172 };
173 
174 static const unsigned short seq_gamma_ctrl[] = {
175 	0xFB, 0x02,
176 
177 	DATA_ONLY, 0x5A,
178 	ENDDEF, 0x00
179 };
180 
181 static const unsigned short seq_gamma_start[] = {
182 	0xF9, COMMAND_ONLY,
183 
184 	ENDDEF, 0x00
185 };
186 
187 static const unsigned short seq_apon[] = {
188 	0xF3, 0x00,
189 
190 	DATA_ONLY, 0x00,
191 	DATA_ONLY, 0x00,
192 	DATA_ONLY, 0x0A,
193 	DATA_ONLY, 0x02,
194 	ENDDEF, 0x00
195 };
196 
197 static const unsigned short seq_display_ctrl[] = {
198 	0xF2, 0x02,
199 
200 	DATA_ONLY, 0x08,
201 	DATA_ONLY, 0x08,
202 	DATA_ONLY, 0x10,
203 	DATA_ONLY, 0x10,
204 	ENDDEF, 0x00
205 };
206 
207 static const unsigned short seq_manual_pwr[] = {
208 	0xB0, 0x04,
209 	ENDDEF, 0x00
210 };
211 
212 static const unsigned short seq_pwr_ctrl[] = {
213 	0xF4, 0x0A,
214 
215 	DATA_ONLY, 0x87,
216 	DATA_ONLY, 0x25,
217 	DATA_ONLY, 0x6A,
218 	DATA_ONLY, 0x44,
219 	DATA_ONLY, 0x02,
220 	DATA_ONLY, 0x88,
221 	ENDDEF, 0x00
222 };
223 
224 static const unsigned short seq_sleep_out[] = {
225 	0x11, COMMAND_ONLY,
226 	ENDDEF, 0x00
227 };
228 
229 static const unsigned short seq_sleep_in[] = {
230 	0x10, COMMAND_ONLY,
231 	ENDDEF, 0x00
232 };
233 
234 static const unsigned short seq_display_on[] = {
235 	0x29, COMMAND_ONLY,
236 	ENDDEF, 0x00
237 };
238 
239 static const unsigned short seq_display_off[] = {
240 	0x28, COMMAND_ONLY,
241 	ENDDEF, 0x00
242 };
243 
244 static const unsigned short seq_vci1_1st_en[] = {
245 	0xF3, 0x10,
246 
247 	DATA_ONLY, 0x00,
248 	DATA_ONLY, 0x00,
249 	DATA_ONLY, 0x00,
250 	DATA_ONLY, 0x02,
251 	ENDDEF, 0x00
252 };
253 
254 static const unsigned short seq_vl1_en[] = {
255 	0xF3, 0x11,
256 
257 	DATA_ONLY, 0x00,
258 	DATA_ONLY, 0x00,
259 	DATA_ONLY, 0x00,
260 	DATA_ONLY, 0x02,
261 	ENDDEF, 0x00
262 };
263 
264 static const unsigned short seq_vl2_en[] = {
265 	0xF3, 0x13,
266 
267 	DATA_ONLY, 0x00,
268 	DATA_ONLY, 0x00,
269 	DATA_ONLY, 0x00,
270 	DATA_ONLY, 0x02,
271 	ENDDEF, 0x00
272 };
273 
274 static const unsigned short seq_vci1_2nd_en[] = {
275 	0xF3, 0x33,
276 
277 	DATA_ONLY, 0x00,
278 	DATA_ONLY, 0x00,
279 	DATA_ONLY, 0x00,
280 	DATA_ONLY, 0x02,
281 	ENDDEF, 0x00
282 };
283 
284 static const unsigned short seq_vl3_en[] = {
285 	0xF3, 0x37,
286 
287 	DATA_ONLY, 0x00,
288 	DATA_ONLY, 0x00,
289 	DATA_ONLY, 0x00,
290 	DATA_ONLY, 0x02,
291 	ENDDEF, 0x00
292 };
293 
294 static const unsigned short seq_vreg1_amp_en[] = {
295 	0xF3, 0x37,
296 
297 	DATA_ONLY, 0x01,
298 	DATA_ONLY, 0x00,
299 	DATA_ONLY, 0x00,
300 	DATA_ONLY, 0x02,
301 	ENDDEF, 0x00
302 };
303 
304 static const unsigned short seq_vgh_amp_en[] = {
305 	0xF3, 0x37,
306 
307 	DATA_ONLY, 0x11,
308 	DATA_ONLY, 0x00,
309 	DATA_ONLY, 0x00,
310 	DATA_ONLY, 0x02,
311 	ENDDEF, 0x00
312 };
313 
314 static const unsigned short seq_vgl_amp_en[] = {
315 	0xF3, 0x37,
316 
317 	DATA_ONLY, 0x31,
318 	DATA_ONLY, 0x00,
319 	DATA_ONLY, 0x00,
320 	DATA_ONLY, 0x02,
321 	ENDDEF, 0x00
322 };
323 
324 static const unsigned short seq_vmos_amp_en[] = {
325 	0xF3, 0x37,
326 
327 	DATA_ONLY, 0xB1,
328 	DATA_ONLY, 0x00,
329 	DATA_ONLY, 0x00,
330 	DATA_ONLY, 0x03,
331 	ENDDEF, 0x00
332 };
333 
334 static const unsigned short seq_vint_amp_en[] = {
335 	0xF3, 0x37,
336 
337 	DATA_ONLY, 0xF1,
338 	/* DATA_ONLY, 0x71,	VMOS/VBL/VBH not used */
339 	DATA_ONLY, 0x00,
340 	DATA_ONLY, 0x00,
341 	DATA_ONLY, 0x03,
342 	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
343 	ENDDEF, 0x00
344 };
345 
346 static const unsigned short seq_vbh_amp_en[] = {
347 	0xF3, 0x37,
348 
349 	DATA_ONLY, 0xF9,
350 	DATA_ONLY, 0x00,
351 	DATA_ONLY, 0x00,
352 	DATA_ONLY, 0x03,
353 	ENDDEF, 0x00
354 };
355 
356 static const unsigned short seq_vbl_amp_en[] = {
357 	0xF3, 0x37,
358 
359 	DATA_ONLY, 0xFD,
360 	DATA_ONLY, 0x00,
361 	DATA_ONLY, 0x00,
362 	DATA_ONLY, 0x03,
363 	ENDDEF, 0x00
364 };
365 
366 static const unsigned short seq_gam_amp_en[] = {
367 	0xF3, 0x37,
368 
369 	DATA_ONLY, 0xFF,
370 	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
371 	DATA_ONLY, 0x00,
372 	DATA_ONLY, 0x00,
373 	DATA_ONLY, 0x03,
374 	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
375 	ENDDEF, 0x00
376 };
377 
378 static const unsigned short seq_sd_amp_en[] = {
379 	0xF3, 0x37,
380 
381 	DATA_ONLY, 0xFF,
382 	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
383 	DATA_ONLY, 0x80,
384 	DATA_ONLY, 0x00,
385 	DATA_ONLY, 0x03,
386 	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
387 	ENDDEF, 0x00
388 };
389 
390 static const unsigned short seq_gls_en[] = {
391 	0xF3, 0x37,
392 
393 	DATA_ONLY, 0xFF,
394 	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
395 	DATA_ONLY, 0x81,
396 	DATA_ONLY, 0x00,
397 	DATA_ONLY, 0x03,
398 	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
399 	ENDDEF, 0x00
400 };
401 
402 static const unsigned short seq_els_en[] = {
403 	0xF3, 0x37,
404 
405 	DATA_ONLY, 0xFF,
406 	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
407 	DATA_ONLY, 0x83,
408 	DATA_ONLY, 0x00,
409 	DATA_ONLY, 0x03,
410 	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
411 	ENDDEF, 0x00
412 };
413 
414 static const unsigned short seq_el_on[] = {
415 	0xF3, 0x37,
416 
417 	DATA_ONLY, 0xFF,
418 	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
419 	DATA_ONLY, 0x87,
420 	DATA_ONLY, 0x00,
421 	DATA_ONLY, 0x03,
422 	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
423 	ENDDEF, 0x00
424 };
425 
ld9040_spi_write_byte(struct ld9040 * lcd,int addr,int data)426 static int ld9040_spi_write_byte(struct ld9040 *lcd, int addr, int data)
427 {
428 	u16 buf[1];
429 	struct spi_message msg;
430 
431 	struct spi_transfer xfer = {
432 		.len		= 2,
433 		.tx_buf		= buf,
434 	};
435 
436 	buf[0] = (addr << 8) | data;
437 
438 	spi_message_init(&msg);
439 	spi_message_add_tail(&xfer, &msg);
440 
441 	return spi_sync(lcd->spi, &msg);
442 }
443 
ld9040_spi_write(struct ld9040 * lcd,unsigned char address,unsigned char command)444 static int ld9040_spi_write(struct ld9040 *lcd, unsigned char address,
445 	unsigned char command)
446 {
447 	int ret = 0;
448 
449 	if (address != DATA_ONLY)
450 		ret = ld9040_spi_write_byte(lcd, 0x0, address);
451 	if (command != COMMAND_ONLY)
452 		ret = ld9040_spi_write_byte(lcd, 0x1, command);
453 
454 	return ret;
455 }
456 
ld9040_panel_send_sequence(struct ld9040 * lcd,const unsigned short * wbuf)457 static int ld9040_panel_send_sequence(struct ld9040 *lcd,
458 	const unsigned short *wbuf)
459 {
460 	int ret = 0, i = 0;
461 
462 	while ((wbuf[i] & DEFMASK) != ENDDEF) {
463 		if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
464 			ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]);
465 			if (ret)
466 				break;
467 		} else {
468 			msleep(wbuf[i+1]);
469 		}
470 		i += 2;
471 	}
472 
473 	return ret;
474 }
475 
_ld9040_gamma_ctl(struct ld9040 * lcd,const unsigned int * gamma)476 static int _ld9040_gamma_ctl(struct ld9040 *lcd, const unsigned int *gamma)
477 {
478 	unsigned int i = 0;
479 	int ret = 0;
480 
481 	/* start gamma table updating. */
482 	ret = ld9040_panel_send_sequence(lcd, seq_gamma_start);
483 	if (ret) {
484 		dev_err(lcd->dev, "failed to disable gamma table updating.\n");
485 		goto gamma_err;
486 	}
487 
488 	for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
489 		ret = ld9040_spi_write(lcd, DATA_ONLY, gamma[i]);
490 		if (ret) {
491 			dev_err(lcd->dev, "failed to set gamma table.\n");
492 			goto gamma_err;
493 		}
494 	}
495 
496 	/* update gamma table. */
497 	ret = ld9040_panel_send_sequence(lcd, seq_gamma_ctrl);
498 	if (ret)
499 		dev_err(lcd->dev, "failed to update gamma table.\n");
500 
501 gamma_err:
502 	return ret;
503 }
504 
ld9040_gamma_ctl(struct ld9040 * lcd,int gamma)505 static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma)
506 {
507 	return _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
508 }
509 
ld9040_ldi_init(struct ld9040 * lcd)510 static int ld9040_ldi_init(struct ld9040 *lcd)
511 {
512 	int ret, i;
513 	static const unsigned short *init_seq[] = {
514 		seq_user_setting,
515 		seq_panel_condition,
516 		seq_display_ctrl,
517 		seq_manual_pwr,
518 		seq_elvss_on,
519 		seq_gtcon,
520 		seq_gamma_set1,
521 		seq_gamma_ctrl,
522 		seq_sleep_out,
523 	};
524 
525 	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
526 		ret = ld9040_panel_send_sequence(lcd, init_seq[i]);
527 		/* workaround: minimum delay time for transferring CMD */
528 		usleep_range(300, 310);
529 		if (ret)
530 			break;
531 	}
532 
533 	return ret;
534 }
535 
ld9040_ldi_enable(struct ld9040 * lcd)536 static int ld9040_ldi_enable(struct ld9040 *lcd)
537 {
538 	return ld9040_panel_send_sequence(lcd, seq_display_on);
539 }
540 
ld9040_ldi_disable(struct ld9040 * lcd)541 static int ld9040_ldi_disable(struct ld9040 *lcd)
542 {
543 	int ret;
544 
545 	ret = ld9040_panel_send_sequence(lcd, seq_display_off);
546 	ret = ld9040_panel_send_sequence(lcd, seq_sleep_in);
547 
548 	return ret;
549 }
550 
ld9040_power_is_on(int power)551 static int ld9040_power_is_on(int power)
552 {
553 	return power <= FB_BLANK_NORMAL;
554 }
555 
ld9040_power_on(struct ld9040 * lcd)556 static int ld9040_power_on(struct ld9040 *lcd)
557 {
558 	int ret = 0;
559 	struct lcd_platform_data *pd;
560 
561 	pd = lcd->lcd_pd;
562 
563 	/* lcd power on */
564 	ld9040_regulator_enable(lcd);
565 
566 	if (!pd->reset) {
567 		dev_err(lcd->dev, "reset is NULL.\n");
568 		return -EINVAL;
569 	} else {
570 		pd->reset(lcd->ld);
571 		msleep(pd->reset_delay);
572 	}
573 
574 	ret = ld9040_ldi_init(lcd);
575 	if (ret) {
576 		dev_err(lcd->dev, "failed to initialize ldi.\n");
577 		return ret;
578 	}
579 
580 	ret = ld9040_ldi_enable(lcd);
581 	if (ret) {
582 		dev_err(lcd->dev, "failed to enable ldi.\n");
583 		return ret;
584 	}
585 
586 	return 0;
587 }
588 
ld9040_power_off(struct ld9040 * lcd)589 static int ld9040_power_off(struct ld9040 *lcd)
590 {
591 	int ret;
592 	struct lcd_platform_data *pd;
593 
594 	pd = lcd->lcd_pd;
595 
596 	ret = ld9040_ldi_disable(lcd);
597 	if (ret) {
598 		dev_err(lcd->dev, "lcd setting failed.\n");
599 		return -EIO;
600 	}
601 
602 	msleep(pd->power_off_delay);
603 
604 	/* lcd power off */
605 	ld9040_regulator_disable(lcd);
606 
607 	return 0;
608 }
609 
ld9040_power(struct ld9040 * lcd,int power)610 static int ld9040_power(struct ld9040 *lcd, int power)
611 {
612 	int ret = 0;
613 
614 	if (ld9040_power_is_on(power) && !ld9040_power_is_on(lcd->power))
615 		ret = ld9040_power_on(lcd);
616 	else if (!ld9040_power_is_on(power) && ld9040_power_is_on(lcd->power))
617 		ret = ld9040_power_off(lcd);
618 
619 	if (!ret)
620 		lcd->power = power;
621 
622 	return ret;
623 }
624 
ld9040_set_power(struct lcd_device * ld,int power)625 static int ld9040_set_power(struct lcd_device *ld, int power)
626 {
627 	struct ld9040 *lcd = lcd_get_data(ld);
628 
629 	if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
630 		power != FB_BLANK_NORMAL) {
631 		dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
632 		return -EINVAL;
633 	}
634 
635 	return ld9040_power(lcd, power);
636 }
637 
ld9040_get_power(struct lcd_device * ld)638 static int ld9040_get_power(struct lcd_device *ld)
639 {
640 	struct ld9040 *lcd = lcd_get_data(ld);
641 
642 	return lcd->power;
643 }
644 
ld9040_get_brightness(struct backlight_device * bd)645 static int ld9040_get_brightness(struct backlight_device *bd)
646 {
647 	return bd->props.brightness;
648 }
649 
ld9040_set_brightness(struct backlight_device * bd)650 static int ld9040_set_brightness(struct backlight_device *bd)
651 {
652 	int ret = 0, brightness = bd->props.brightness;
653 	struct ld9040 *lcd = bl_get_data(bd);
654 
655 	if (brightness < MIN_BRIGHTNESS ||
656 		brightness > bd->props.max_brightness) {
657 		dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
658 			MIN_BRIGHTNESS, MAX_BRIGHTNESS);
659 		return -EINVAL;
660 	}
661 
662 	ret = ld9040_gamma_ctl(lcd, bd->props.brightness);
663 	if (ret) {
664 		dev_err(&bd->dev, "lcd brightness setting failed.\n");
665 		return -EIO;
666 	}
667 
668 	return ret;
669 }
670 
671 static struct lcd_ops ld9040_lcd_ops = {
672 	.set_power = ld9040_set_power,
673 	.get_power = ld9040_get_power,
674 };
675 
676 static const struct backlight_ops ld9040_backlight_ops  = {
677 	.get_brightness = ld9040_get_brightness,
678 	.update_status = ld9040_set_brightness,
679 };
680 
ld9040_probe(struct spi_device * spi)681 static int ld9040_probe(struct spi_device *spi)
682 {
683 	int ret = 0;
684 	struct ld9040 *lcd = NULL;
685 	struct lcd_device *ld = NULL;
686 	struct backlight_device *bd = NULL;
687 	struct backlight_properties props;
688 
689 	lcd = devm_kzalloc(&spi->dev, sizeof(struct ld9040), GFP_KERNEL);
690 	if (!lcd)
691 		return -ENOMEM;
692 
693 	/* ld9040 lcd panel uses 3-wire 9bits SPI Mode. */
694 	spi->bits_per_word = 9;
695 
696 	ret = spi_setup(spi);
697 	if (ret < 0) {
698 		dev_err(&spi->dev, "spi setup failed.\n");
699 		return ret;
700 	}
701 
702 	lcd->spi = spi;
703 	lcd->dev = &spi->dev;
704 
705 	lcd->lcd_pd = spi->dev.platform_data;
706 	if (!lcd->lcd_pd) {
707 		dev_err(&spi->dev, "platform data is NULL.\n");
708 		return -EINVAL;
709 	}
710 
711 	mutex_init(&lcd->lock);
712 
713 	ret = devm_regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
714 	if (ret) {
715 		dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
716 		return ret;
717 	}
718 
719 	ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
720 	if (IS_ERR(ld))
721 		return PTR_ERR(ld);
722 
723 	lcd->ld = ld;
724 
725 	memset(&props, 0, sizeof(struct backlight_properties));
726 	props.type = BACKLIGHT_RAW;
727 	props.max_brightness = MAX_BRIGHTNESS;
728 
729 	bd = backlight_device_register("ld9040-bl", &spi->dev,
730 		lcd, &ld9040_backlight_ops, &props);
731 	if (IS_ERR(bd)) {
732 		ret = PTR_ERR(bd);
733 		goto out_unregister_lcd;
734 	}
735 
736 	bd->props.brightness = MAX_BRIGHTNESS;
737 	lcd->bd = bd;
738 
739 	/*
740 	 * if lcd panel was on from bootloader like u-boot then
741 	 * do not lcd on.
742 	 */
743 	if (!lcd->lcd_pd->lcd_enabled) {
744 		/*
745 		 * if lcd panel was off from bootloader then
746 		 * current lcd status is powerdown and then
747 		 * it enables lcd panel.
748 		 */
749 		lcd->power = FB_BLANK_POWERDOWN;
750 
751 		ld9040_power(lcd, FB_BLANK_UNBLANK);
752 	} else {
753 		lcd->power = FB_BLANK_UNBLANK;
754 	}
755 
756 	spi_set_drvdata(spi, lcd);
757 
758 	dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
759 	return 0;
760 
761 out_unregister_lcd:
762 	lcd_device_unregister(lcd->ld);
763 
764 	return ret;
765 }
766 
ld9040_remove(struct spi_device * spi)767 static int ld9040_remove(struct spi_device *spi)
768 {
769 	struct ld9040 *lcd = spi_get_drvdata(spi);
770 
771 	ld9040_power(lcd, FB_BLANK_POWERDOWN);
772 	backlight_device_unregister(lcd->bd);
773 	lcd_device_unregister(lcd->ld);
774 
775 	return 0;
776 }
777 
778 #ifdef CONFIG_PM_SLEEP
ld9040_suspend(struct device * dev)779 static int ld9040_suspend(struct device *dev)
780 {
781 	struct ld9040 *lcd = dev_get_drvdata(dev);
782 
783 	dev_dbg(dev, "lcd->power = %d\n", lcd->power);
784 
785 	/*
786 	 * when lcd panel is suspend, lcd panel becomes off
787 	 * regardless of status.
788 	 */
789 	return ld9040_power(lcd, FB_BLANK_POWERDOWN);
790 }
791 
ld9040_resume(struct device * dev)792 static int ld9040_resume(struct device *dev)
793 {
794 	struct ld9040 *lcd = dev_get_drvdata(dev);
795 
796 	lcd->power = FB_BLANK_POWERDOWN;
797 
798 	return ld9040_power(lcd, FB_BLANK_UNBLANK);
799 }
800 #endif
801 
802 static SIMPLE_DEV_PM_OPS(ld9040_pm_ops, ld9040_suspend, ld9040_resume);
803 
804 /* Power down all displays on reboot, poweroff or halt. */
ld9040_shutdown(struct spi_device * spi)805 static void ld9040_shutdown(struct spi_device *spi)
806 {
807 	struct ld9040 *lcd = spi_get_drvdata(spi);
808 
809 	ld9040_power(lcd, FB_BLANK_POWERDOWN);
810 }
811 
812 static struct spi_driver ld9040_driver = {
813 	.driver = {
814 		.name	= "ld9040",
815 		.owner	= THIS_MODULE,
816 		.pm	= &ld9040_pm_ops,
817 	},
818 	.probe		= ld9040_probe,
819 	.remove		= ld9040_remove,
820 	.shutdown	= ld9040_shutdown,
821 };
822 
823 module_spi_driver(ld9040_driver);
824 
825 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
826 MODULE_DESCRIPTION("ld9040 LCD Driver");
827 MODULE_LICENSE("GPL");
828