1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/backlight.h>
26#include <linux/bitops.h>
27#include <linux/gpio/consumer.h>
28#include <linux/module.h>
29#include <linux/of_device.h>
30#include <linux/regmap.h>
31#include <linux/regulator/consumer.h>
32
33#include <video/mipi_display.h>
34
35#include <drm/drm_mipi_dsi.h>
36#include <drm/drm_modes.h>
37#include <drm/drm_panel.h>
38
39#define MCS_CMD_MAUCCTR 0xF0
40#define MCS_CMD_READ_ID1 0xDA
41#define MCS_CMD_READ_ID2 0xDB
42#define MCS_CMD_READ_ID3 0xDC
43#define MCS_CMD_MTP_READ_SETTING 0xF8
44#define MCS_CMD_MTP_READ_PARAM 0xFF
45
46
47
48
49
50#define NT35510_P0_DOPCTR 0xB1
51#define NT35510_P0_SDHDTCTR 0xB6
52#define NT35510_P0_GSEQCTR 0xB7
53#define NT35510_P0_SDEQCTR 0xB8
54#define NT35510_P0_SDVPCTR 0xBA
55#define NT35510_P0_DPFRCTR1 0xBD
56#define NT35510_P0_DPFRCTR2 0xBE
57#define NT35510_P0_DPFRCTR3 0xBF
58#define NT35510_P0_DPMCTR12 0xCC
59
60#define NT35510_P0_DOPCTR_LEN 2
61#define NT35510_P0_GSEQCTR_LEN 2
62#define NT35510_P0_SDEQCTR_LEN 4
63#define NT35510_P0_SDVPCTR_LEN 1
64#define NT35510_P0_DPFRCTR1_LEN 5
65#define NT35510_P0_DPFRCTR2_LEN 5
66#define NT35510_P0_DPFRCTR3_LEN 5
67#define NT35510_P0_DPMCTR12_LEN 3
68
69#define NT35510_DOPCTR_0_RAMKP BIT(7)
70#define NT35510_DOPCTR_0_DSITE BIT(6)
71#define NT35510_DOPCTR_0_DSIG BIT(5)
72#define NT35510_DOPCTR_0_DSIM BIT(4)
73#define NT35510_DOPCTR_0_EOTP BIT(3)
74#define NT35510_DOPCTR_0_N565 BIT(2)
75#define NT35510_DOPCTR_1_TW_PWR_SEL BIT(4)
76#define NT35510_DOPCTR_1_CRGB BIT(3)
77#define NT35510_DOPCTR_1_CTB BIT(2)
78#define NT35510_DOPCTR_1_CRL BIT(1)
79#define NT35510_P0_SDVPCTR_PRG BIT(2)
80#define NT35510_P0_SDVPCTR_AVDD 0
81#define NT35510_P0_SDVPCTR_OFFCOL 1
82#define NT35510_P0_SDVPCTR_AVSS 2
83#define NT35510_P0_SDVPCTR_HI_Z 3
84
85
86
87
88
89#define NT35510_P1_SETAVDD 0xB0
90#define NT35510_P1_SETAVEE 0xB1
91#define NT35510_P1_SETVCL 0xB2
92#define NT35510_P1_SETVGH 0xB3
93#define NT35510_P1_SETVRGH 0xB4
94#define NT35510_P1_SETVGL 0xB5
95#define NT35510_P1_BT1CTR 0xB6
96#define NT35510_P1_BT2CTR 0xB7
97#define NT35510_P1_BT3CTR 0xB8
98#define NT35510_P1_BT4CTR 0xB9
99#define NT35510_P1_BT5CTR 0xBA
100#define NT35510_P1_PFMCTR 0xBB
101#define NT35510_P1_SETVGP 0xBC
102#define NT35510_P1_SETVGN 0xBD
103#define NT35510_P1_SETVCMOFF 0xBE
104#define NT35510_P1_VGHCTR 0xBF
105#define NT35510_P1_SET_GAMMA_RED_POS 0xD1
106#define NT35510_P1_SET_GAMMA_GREEN_POS 0xD2
107#define NT35510_P1_SET_GAMMA_BLUE_POS 0xD3
108#define NT35510_P1_SET_GAMMA_RED_NEG 0xD4
109#define NT35510_P1_SET_GAMMA_GREEN_NEG 0xD5
110#define NT35510_P1_SET_GAMMA_BLUE_NEG 0xD6
111
112
113#define NT35510_P1_AVDD_LEN 3
114#define NT35510_P1_AVEE_LEN 3
115#define NT35510_P1_VGH_LEN 3
116#define NT35510_P1_VGL_LEN 3
117#define NT35510_P1_VGP_LEN 3
118#define NT35510_P1_VGN_LEN 3
119
120#define NT35510_P1_BT1CTR_LEN 3
121#define NT35510_P1_BT2CTR_LEN 3
122#define NT35510_P1_BT4CTR_LEN 3
123#define NT35510_P1_BT5CTR_LEN 3
124
125#define NT35510_P1_GAMMA_LEN 52
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159struct nt35510_config {
160
161
162
163 u32 width_mm;
164
165
166
167 u32 height_mm;
168
169
170
171
172
173 const struct drm_display_mode mode;
174
175
176
177
178 u8 avdd[NT35510_P1_AVDD_LEN];
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 u8 bt1ctr[NT35510_P1_BT1CTR_LEN];
203
204
205
206
207 u8 avee[NT35510_P1_AVEE_LEN];
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222 u8 bt2ctr[NT35510_P1_BT2CTR_LEN];
223
224
225
226
227 u8 vgh[NT35510_P1_VGH_LEN];
228
229
230
231
232
233
234
235
236
237
238
239
240
241 u8 bt4ctr[NT35510_P1_BT4CTR_LEN];
242
243
244
245
246 u8 vgl[NT35510_P1_VGL_LEN];
247
248
249
250
251
252
253
254
255
256
257
258
259
260 u8 bt5ctr[NT35510_P1_BT5CTR_LEN];
261
262
263
264
265
266
267
268
269
270 u8 vgp[NT35510_P1_VGP_LEN];
271
272
273
274
275 u8 vgn[NT35510_P1_VGN_LEN];
276
277
278
279
280
281
282
283
284
285 u8 sdeqctr[NT35510_P0_SDEQCTR_LEN];
286
287
288
289 u8 sdvpctr;
290
291
292
293
294
295 u16 t1;
296
297
298
299
300
301 u8 vbp;
302
303
304
305 u8 vfp;
306
307
308
309 u8 psel;
310
311
312
313
314
315
316
317
318
319
320
321 u8 dpmctr12[NT35510_P0_DPMCTR12_LEN];
322
323
324
325 u8 gamma_corr_pos_r[NT35510_P1_GAMMA_LEN];
326
327
328
329 u8 gamma_corr_pos_g[NT35510_P1_GAMMA_LEN];
330
331
332
333 u8 gamma_corr_pos_b[NT35510_P1_GAMMA_LEN];
334
335
336
337 u8 gamma_corr_neg_r[NT35510_P1_GAMMA_LEN];
338
339
340
341 u8 gamma_corr_neg_g[NT35510_P1_GAMMA_LEN];
342
343
344
345 u8 gamma_corr_neg_b[NT35510_P1_GAMMA_LEN];
346};
347
348
349
350
351struct nt35510 {
352
353
354
355 struct device *dev;
356
357
358
359
360
361
362 const struct nt35510_config *conf;
363
364
365
366 struct drm_panel panel;
367
368
369
370 struct regulator_bulk_data supplies[2];
371
372
373
374 struct gpio_desc *reset_gpio;
375};
376
377
378static const u8 nt35510_mauc_mtp_read_param[] = { 0xAA, 0x55, 0x25, 0x01 };
379static const u8 nt35510_mauc_mtp_read_setting[] = { 0x01, 0x02, 0x00, 0x20,
380 0x33, 0x13, 0x00, 0x40,
381 0x00, 0x00, 0x23, 0x02 };
382static const u8 nt35510_mauc_select_page_0[] = { 0x55, 0xAA, 0x52, 0x08, 0x00 };
383static const u8 nt35510_mauc_select_page_1[] = { 0x55, 0xAA, 0x52, 0x08, 0x01 };
384static const u8 nt35510_vgh_on[] = { 0x01 };
385
386static inline struct nt35510 *panel_to_nt35510(struct drm_panel *panel)
387{
388 return container_of(panel, struct nt35510, panel);
389}
390
391#define NT35510_ROTATE_0_SETTING 0x02
392#define NT35510_ROTATE_180_SETTING 0x00
393
394static int nt35510_send_long(struct nt35510 *nt, struct mipi_dsi_device *dsi,
395 u8 cmd, u8 cmdlen, const u8 *seq)
396{
397 const u8 *seqp = seq;
398 int cmdwritten = 0;
399 int chunk = cmdlen;
400 int ret;
401
402 if (chunk > 15)
403 chunk = 15;
404 ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk);
405 if (ret < 0) {
406 dev_err(nt->dev, "error sending DCS command seq cmd %02x\n", cmd);
407 return ret;
408 }
409 cmdwritten += chunk;
410 seqp += chunk;
411
412 while (cmdwritten < cmdlen) {
413 chunk = cmdlen - cmdwritten;
414 if (chunk > 15)
415 chunk = 15;
416 ret = mipi_dsi_generic_write(dsi, seqp, chunk);
417 if (ret < 0) {
418 dev_err(nt->dev, "error sending generic write seq %02x\n", cmd);
419 return ret;
420 }
421 cmdwritten += chunk;
422 seqp += chunk;
423 }
424 dev_dbg(nt->dev, "sent command %02x %02x bytes\n", cmd, cmdlen);
425 return 0;
426}
427
428static int nt35510_read_id(struct nt35510 *nt)
429{
430 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
431 u8 id1, id2, id3;
432 int ret;
433
434 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID1, &id1, 1);
435 if (ret < 0) {
436 dev_err(nt->dev, "could not read MTP ID1\n");
437 return ret;
438 }
439 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID2, &id2, 1);
440 if (ret < 0) {
441 dev_err(nt->dev, "could not read MTP ID2\n");
442 return ret;
443 }
444 ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID3, &id3, 1);
445 if (ret < 0) {
446 dev_err(nt->dev, "could not read MTP ID3\n");
447 return ret;
448 }
449
450
451
452
453
454
455 dev_info(nt->dev, "MTP ID manufacturer: %02x version: %02x driver: %02x\n", id1, id2, id3);
456
457 return 0;
458}
459
460
461
462
463
464static int nt35510_setup_power(struct nt35510 *nt)
465{
466 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
467 int ret;
468
469 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETAVDD,
470 NT35510_P1_AVDD_LEN,
471 nt->conf->avdd);
472 if (ret)
473 return ret;
474 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT1CTR,
475 NT35510_P1_BT1CTR_LEN,
476 nt->conf->bt1ctr);
477 if (ret)
478 return ret;
479 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETAVEE,
480 NT35510_P1_AVEE_LEN,
481 nt->conf->avee);
482 if (ret)
483 return ret;
484 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT2CTR,
485 NT35510_P1_BT2CTR_LEN,
486 nt->conf->bt2ctr);
487 if (ret)
488 return ret;
489 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGH,
490 NT35510_P1_VGH_LEN,
491 nt->conf->vgh);
492 if (ret)
493 return ret;
494 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT4CTR,
495 NT35510_P1_BT4CTR_LEN,
496 nt->conf->bt4ctr);
497 if (ret)
498 return ret;
499 ret = nt35510_send_long(nt, dsi, NT35510_P1_VGHCTR,
500 ARRAY_SIZE(nt35510_vgh_on),
501 nt35510_vgh_on);
502 if (ret)
503 return ret;
504 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGL,
505 NT35510_P1_VGL_LEN,
506 nt->conf->vgl);
507 if (ret)
508 return ret;
509 ret = nt35510_send_long(nt, dsi, NT35510_P1_BT5CTR,
510 NT35510_P1_BT5CTR_LEN,
511 nt->conf->bt5ctr);
512 if (ret)
513 return ret;
514 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGP,
515 NT35510_P1_VGP_LEN,
516 nt->conf->vgp);
517 if (ret)
518 return ret;
519 ret = nt35510_send_long(nt, dsi, NT35510_P1_SETVGN,
520 NT35510_P1_VGN_LEN,
521 nt->conf->vgn);
522 if (ret)
523 return ret;
524
525
526 usleep_range(10000, 20000);
527
528 return 0;
529}
530
531
532
533
534
535static int nt35510_setup_display(struct nt35510 *nt)
536{
537 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
538 const struct nt35510_config *conf = nt->conf;
539 u8 dopctr[NT35510_P0_DOPCTR_LEN];
540 u8 gseqctr[NT35510_P0_GSEQCTR_LEN];
541 u8 dpfrctr[NT35510_P0_DPFRCTR1_LEN];
542
543 u8 addr_mode = NT35510_ROTATE_0_SETTING;
544 u8 val;
545 int ret;
546
547
548 dopctr[0] = NT35510_DOPCTR_0_DSITE | NT35510_DOPCTR_0_EOTP |
549 NT35510_DOPCTR_0_N565;
550 dopctr[1] = NT35510_DOPCTR_1_CTB;
551 ret = nt35510_send_long(nt, dsi, NT35510_P0_DOPCTR,
552 NT35510_P0_DOPCTR_LEN,
553 dopctr);
554 if (ret)
555 return ret;
556
557 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_ADDRESS_MODE, &addr_mode,
558 sizeof(addr_mode));
559 if (ret < 0)
560 return ret;
561
562
563
564
565
566
567 val = 0x0A;
568 ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDHDTCTR, &val,
569 sizeof(val));
570 if (ret < 0)
571 return ret;
572
573
574 gseqctr[0] = 0x00;
575 gseqctr[1] = 0x00;
576 ret = nt35510_send_long(nt, dsi, NT35510_P0_GSEQCTR,
577 NT35510_P0_GSEQCTR_LEN,
578 gseqctr);
579 if (ret)
580 return ret;
581
582 ret = nt35510_send_long(nt, dsi, NT35510_P0_SDEQCTR,
583 NT35510_P0_SDEQCTR_LEN,
584 conf->sdeqctr);
585 if (ret)
586 return ret;
587
588 ret = mipi_dsi_dcs_write(dsi, NT35510_P0_SDVPCTR,
589 &conf->sdvpctr, 1);
590 if (ret < 0)
591 return ret;
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609 dpfrctr[0] = (conf->t1 >> 8) & 0xFF;
610 dpfrctr[1] = conf->t1 & 0xFF;
611
612 dpfrctr[2] = conf->vbp;
613
614 dpfrctr[3] = conf->vfp;
615 dpfrctr[4] = conf->psel;
616 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR1,
617 NT35510_P0_DPFRCTR1_LEN,
618 dpfrctr);
619 if (ret)
620 return ret;
621
622 dpfrctr[3]--;
623 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR2,
624 NT35510_P0_DPFRCTR2_LEN,
625 dpfrctr);
626 if (ret)
627 return ret;
628 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPFRCTR3,
629 NT35510_P0_DPFRCTR3_LEN,
630 dpfrctr);
631 if (ret)
632 return ret;
633
634
635 ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
636 if (ret)
637 return ret;
638
639
640 ret = nt35510_send_long(nt, dsi, NT35510_P0_DPMCTR12,
641 NT35510_P0_DPMCTR12_LEN,
642 conf->dpmctr12);
643 if (ret)
644 return ret;
645
646 return 0;
647}
648
649static int nt35510_set_brightness(struct backlight_device *bl)
650{
651 struct nt35510 *nt = bl_get_data(bl);
652 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
653 u8 brightness = bl->props.brightness;
654 int ret;
655
656 dev_dbg(nt->dev, "set brightness %d\n", brightness);
657 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
658 &brightness,
659 sizeof(brightness));
660 if (ret < 0)
661 return ret;
662
663 return 0;
664}
665
666static const struct backlight_ops nt35510_bl_ops = {
667 .update_status = nt35510_set_brightness,
668};
669
670
671
672
673static int nt35510_power_on(struct nt35510 *nt)
674{
675 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
676 int ret;
677
678 ret = regulator_bulk_enable(ARRAY_SIZE(nt->supplies), nt->supplies);
679 if (ret < 0) {
680 dev_err(nt->dev, "unable to enable regulators\n");
681 return ret;
682 }
683
684
685 if (nt->reset_gpio) {
686 gpiod_set_value(nt->reset_gpio, 1);
687
688 usleep_range(20, 1000);
689 gpiod_set_value(nt->reset_gpio, 0);
690
691
692
693
694 usleep_range(120000, 140000);
695 }
696
697 ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_PARAM,
698 ARRAY_SIZE(nt35510_mauc_mtp_read_param),
699 nt35510_mauc_mtp_read_param);
700 if (ret)
701 return ret;
702
703 ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_SETTING,
704 ARRAY_SIZE(nt35510_mauc_mtp_read_setting),
705 nt35510_mauc_mtp_read_setting);
706 if (ret)
707 return ret;
708
709 ret = nt35510_read_id(nt);
710 if (ret)
711 return ret;
712
713
714 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
715 ARRAY_SIZE(nt35510_mauc_select_page_1),
716 nt35510_mauc_select_page_1);
717 if (ret)
718 return ret;
719
720 ret = nt35510_setup_power(nt);
721 if (ret)
722 return ret;
723
724 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_POS,
725 NT35510_P1_GAMMA_LEN,
726 nt->conf->gamma_corr_pos_r);
727 if (ret)
728 return ret;
729 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_POS,
730 NT35510_P1_GAMMA_LEN,
731 nt->conf->gamma_corr_pos_g);
732 if (ret)
733 return ret;
734 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_POS,
735 NT35510_P1_GAMMA_LEN,
736 nt->conf->gamma_corr_pos_b);
737 if (ret)
738 return ret;
739 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_NEG,
740 NT35510_P1_GAMMA_LEN,
741 nt->conf->gamma_corr_neg_r);
742 if (ret)
743 return ret;
744 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_NEG,
745 NT35510_P1_GAMMA_LEN,
746 nt->conf->gamma_corr_neg_g);
747 if (ret)
748 return ret;
749 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_NEG,
750 NT35510_P1_GAMMA_LEN,
751 nt->conf->gamma_corr_neg_b);
752 if (ret)
753 return ret;
754
755
756 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
757 ARRAY_SIZE(nt35510_mauc_select_page_0),
758 nt35510_mauc_select_page_0);
759 if (ret)
760 return ret;
761
762 ret = nt35510_setup_display(nt);
763 if (ret)
764 return ret;
765
766 return 0;
767}
768
769static int nt35510_power_off(struct nt35510 *nt)
770{
771 int ret;
772
773 ret = regulator_bulk_disable(ARRAY_SIZE(nt->supplies), nt->supplies);
774 if (ret)
775 return ret;
776
777 if (nt->reset_gpio)
778 gpiod_set_value(nt->reset_gpio, 1);
779
780 return 0;
781}
782
783static int nt35510_unprepare(struct drm_panel *panel)
784{
785 struct nt35510 *nt = panel_to_nt35510(panel);
786 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
787 int ret;
788
789 ret = mipi_dsi_dcs_set_display_off(dsi);
790 if (ret) {
791 dev_err(nt->dev, "failed to turn display off (%d)\n", ret);
792 return ret;
793 }
794 usleep_range(10000, 20000);
795
796
797 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
798 if (ret) {
799 dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret);
800 return ret;
801 }
802
803
804 usleep_range(5000, 10000);
805
806 ret = nt35510_power_off(nt);
807 if (ret)
808 return ret;
809
810 return 0;
811}
812
813static int nt35510_prepare(struct drm_panel *panel)
814{
815 struct nt35510 *nt = panel_to_nt35510(panel);
816 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
817 int ret;
818
819 ret = nt35510_power_on(nt);
820 if (ret)
821 return ret;
822
823
824 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
825 if (ret) {
826 dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret);
827 return ret;
828 }
829
830 usleep_range(120000, 150000);
831
832 ret = mipi_dsi_dcs_set_display_on(dsi);
833 if (ret) {
834 dev_err(nt->dev, "failed to turn display on (%d)\n", ret);
835 return ret;
836 }
837
838 usleep_range(10000, 20000);
839
840 return 0;
841}
842
843static int nt35510_get_modes(struct drm_panel *panel,
844 struct drm_connector *connector)
845{
846 struct nt35510 *nt = panel_to_nt35510(panel);
847 struct drm_display_mode *mode;
848 struct drm_display_info *info;
849
850 info = &connector->display_info;
851 info->width_mm = nt->conf->width_mm;
852 info->height_mm = nt->conf->height_mm;
853 mode = drm_mode_duplicate(connector->dev, &nt->conf->mode);
854 if (!mode) {
855 dev_err(panel->dev, "bad mode or failed to add mode\n");
856 return -EINVAL;
857 }
858 drm_mode_set_name(mode);
859 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
860
861 mode->width_mm = nt->conf->width_mm;
862 mode->height_mm = nt->conf->height_mm;
863 drm_mode_probed_add(connector, mode);
864
865 return 1;
866}
867
868static const struct drm_panel_funcs nt35510_drm_funcs = {
869 .unprepare = nt35510_unprepare,
870 .prepare = nt35510_prepare,
871 .get_modes = nt35510_get_modes,
872};
873
874static int nt35510_probe(struct mipi_dsi_device *dsi)
875{
876 struct device *dev = &dsi->dev;
877 struct nt35510 *nt;
878 int ret;
879
880 nt = devm_kzalloc(dev, sizeof(struct nt35510), GFP_KERNEL);
881 if (!nt)
882 return -ENOMEM;
883 mipi_dsi_set_drvdata(dsi, nt);
884 nt->dev = dev;
885
886 dsi->lanes = 2;
887 dsi->format = MIPI_DSI_FMT_RGB888;
888
889
890
891
892
893
894
895
896
897
898
899 dsi->hs_rate = 349440000;
900 dsi->lp_rate = 9600000;
901 dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
902 MIPI_DSI_MODE_EOT_PACKET;
903
904
905
906
907
908 nt->conf = of_device_get_match_data(dev);
909 if (!nt->conf) {
910 dev_err(dev, "missing device configuration\n");
911 return -ENODEV;
912 }
913
914 nt->supplies[0].supply = "vdd";
915 nt->supplies[1].supply = "vddi";
916 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->supplies),
917 nt->supplies);
918 if (ret < 0)
919 return ret;
920 ret = regulator_set_voltage(nt->supplies[0].consumer,
921 2300000, 4800000);
922 if (ret)
923 return ret;
924 ret = regulator_set_voltage(nt->supplies[1].consumer,
925 1650000, 3300000);
926 if (ret)
927 return ret;
928
929 nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
930 if (IS_ERR(nt->reset_gpio)) {
931 dev_err(dev, "error getting RESET GPIO\n");
932 return PTR_ERR(nt->reset_gpio);
933 }
934
935 drm_panel_init(&nt->panel, dev, &nt35510_drm_funcs,
936 DRM_MODE_CONNECTOR_DSI);
937
938
939
940
941
942
943 ret = drm_panel_of_backlight(&nt->panel);
944 if (ret) {
945 dev_err(dev, "error getting external backlight %d\n", ret);
946 return ret;
947 }
948 if (!nt->panel.backlight) {
949 struct backlight_device *bl;
950
951 bl = devm_backlight_device_register(dev, "nt35510", dev, nt,
952 &nt35510_bl_ops, NULL);
953 if (IS_ERR(bl)) {
954 dev_err(dev, "failed to register backlight device\n");
955 return PTR_ERR(bl);
956 }
957 bl->props.max_brightness = 255;
958 bl->props.brightness = 255;
959 bl->props.power = FB_BLANK_POWERDOWN;
960 nt->panel.backlight = bl;
961 }
962
963 drm_panel_add(&nt->panel);
964
965 ret = mipi_dsi_attach(dsi);
966 if (ret < 0)
967 drm_panel_remove(&nt->panel);
968
969 return 0;
970}
971
972static int nt35510_remove(struct mipi_dsi_device *dsi)
973{
974 struct nt35510 *nt = mipi_dsi_get_drvdata(dsi);
975 int ret;
976
977 mipi_dsi_detach(dsi);
978
979 ret = nt35510_power_off(nt);
980 drm_panel_remove(&nt->panel);
981
982 return ret;
983}
984
985
986
987
988
989
990
991
992#define NT35510_GAMMA_POS_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \
993 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \
994 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \
995 0x83, 0x02, 0x78, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \
996 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \
997 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE
998
999#define NT35510_GAMMA_NEG_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \
1000 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \
1001 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \
1002 0x43, 0x02, 0x50, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \
1003 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \
1004 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE
1005
1006
1007
1008
1009static const struct nt35510_config nt35510_hydis_hva40wv1 = {
1010 .width_mm = 52,
1011 .height_mm = 86,
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 .mode = {
1023
1024 .clock = 20000,
1025 .hdisplay = 480,
1026 .hsync_start = 480 + 2,
1027 .hsync_end = 480 + 2 + 0,
1028 .htotal = 480 + 2 + 0 + 5,
1029 .vdisplay = 800,
1030 .vsync_start = 800 + 2,
1031 .vsync_end = 800 + 2 + 0,
1032 .vtotal = 800 + 2 + 0 + 5,
1033 .flags = 0,
1034 },
1035
1036 .avdd = { 0x09, 0x09, 0x09 },
1037
1038 .bt1ctr = { 0x34, 0x34, 0x34 },
1039
1040 .avee = { 0x09, 0x09, 0x09 },
1041
1042 .bt2ctr = { 0x24, 0x24, 0x24 },
1043
1044 .vgh = { 0x05, 0x05, 0x05 },
1045
1046 .bt4ctr = { 0x24, 0x24, 0x24 },
1047
1048 .vgl = { 0x0B, 0x0B, 0x0B },
1049
1050 .bt5ctr = { 0x24, 0x24, 0x24 },
1051
1052 .vgp = { 0x00, 0xA3, 0x00 },
1053
1054 .vgn = { 0x00, 0xA3, 0x00 },
1055
1056 .sdeqctr = { 0x01, 0x05, 0x05, 0x05 },
1057
1058 .sdvpctr = 0x01,
1059
1060 .t1 = 0x0184,
1061
1062 .vbp = 7,
1063
1064 .vfp = 50,
1065
1066 .psel = 0,
1067
1068 .dpmctr12 = { 0x03, 0x00, 0x00, },
1069
1070 .gamma_corr_pos_r = { NT35510_GAMMA_POS_DEFAULT },
1071 .gamma_corr_pos_g = { NT35510_GAMMA_POS_DEFAULT },
1072 .gamma_corr_pos_b = { NT35510_GAMMA_POS_DEFAULT },
1073 .gamma_corr_neg_r = { NT35510_GAMMA_NEG_DEFAULT },
1074 .gamma_corr_neg_g = { NT35510_GAMMA_NEG_DEFAULT },
1075 .gamma_corr_neg_b = { NT35510_GAMMA_NEG_DEFAULT },
1076};
1077
1078static const struct of_device_id nt35510_of_match[] = {
1079 {
1080 .compatible = "hydis,hva40wv1",
1081 .data = &nt35510_hydis_hva40wv1,
1082 },
1083 { }
1084};
1085MODULE_DEVICE_TABLE(of, nt35510_of_match);
1086
1087static struct mipi_dsi_driver nt35510_driver = {
1088 .probe = nt35510_probe,
1089 .remove = nt35510_remove,
1090 .driver = {
1091 .name = "panel-novatek-nt35510",
1092 .of_match_table = nt35510_of_match,
1093 },
1094};
1095module_mipi_dsi_driver(nt35510_driver);
1096
1097MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
1098MODULE_DESCRIPTION("NT35510-based panel driver");
1099MODULE_LICENSE("GPL v2");
1100