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 nt35510_read_id(nt);
710
711
712 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
713 ARRAY_SIZE(nt35510_mauc_select_page_1),
714 nt35510_mauc_select_page_1);
715 if (ret)
716 return ret;
717
718 ret = nt35510_setup_power(nt);
719 if (ret)
720 return ret;
721
722 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_POS,
723 NT35510_P1_GAMMA_LEN,
724 nt->conf->gamma_corr_pos_r);
725 if (ret)
726 return ret;
727 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_POS,
728 NT35510_P1_GAMMA_LEN,
729 nt->conf->gamma_corr_pos_g);
730 if (ret)
731 return ret;
732 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_POS,
733 NT35510_P1_GAMMA_LEN,
734 nt->conf->gamma_corr_pos_b);
735 if (ret)
736 return ret;
737 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_RED_NEG,
738 NT35510_P1_GAMMA_LEN,
739 nt->conf->gamma_corr_neg_r);
740 if (ret)
741 return ret;
742 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_GREEN_NEG,
743 NT35510_P1_GAMMA_LEN,
744 nt->conf->gamma_corr_neg_g);
745 if (ret)
746 return ret;
747 ret = nt35510_send_long(nt, dsi, NT35510_P1_SET_GAMMA_BLUE_NEG,
748 NT35510_P1_GAMMA_LEN,
749 nt->conf->gamma_corr_neg_b);
750 if (ret)
751 return ret;
752
753
754 ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR,
755 ARRAY_SIZE(nt35510_mauc_select_page_0),
756 nt35510_mauc_select_page_0);
757 if (ret)
758 return ret;
759
760 ret = nt35510_setup_display(nt);
761 if (ret)
762 return ret;
763
764 return 0;
765}
766
767static int nt35510_power_off(struct nt35510 *nt)
768{
769 int ret;
770
771 ret = regulator_bulk_disable(ARRAY_SIZE(nt->supplies), nt->supplies);
772 if (ret)
773 return ret;
774
775 if (nt->reset_gpio)
776 gpiod_set_value(nt->reset_gpio, 1);
777
778 return 0;
779}
780
781static int nt35510_unprepare(struct drm_panel *panel)
782{
783 struct nt35510 *nt = panel_to_nt35510(panel);
784 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
785 int ret;
786
787 ret = mipi_dsi_dcs_set_display_off(dsi);
788 if (ret) {
789 dev_err(nt->dev, "failed to turn display off (%d)\n", ret);
790 return ret;
791 }
792 usleep_range(10000, 20000);
793
794
795 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
796 if (ret) {
797 dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret);
798 return ret;
799 }
800
801
802 usleep_range(5000, 10000);
803
804 ret = nt35510_power_off(nt);
805 if (ret)
806 return ret;
807
808 return 0;
809}
810
811static int nt35510_prepare(struct drm_panel *panel)
812{
813 struct nt35510 *nt = panel_to_nt35510(panel);
814 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
815 int ret;
816
817 ret = nt35510_power_on(nt);
818 if (ret)
819 return ret;
820
821
822 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
823 if (ret) {
824 dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret);
825 return ret;
826 }
827
828 usleep_range(120000, 150000);
829
830 ret = mipi_dsi_dcs_set_display_on(dsi);
831 if (ret) {
832 dev_err(nt->dev, "failed to turn display on (%d)\n", ret);
833 return ret;
834 }
835
836 usleep_range(10000, 20000);
837
838 return 0;
839}
840
841static int nt35510_get_modes(struct drm_panel *panel,
842 struct drm_connector *connector)
843{
844 struct nt35510 *nt = panel_to_nt35510(panel);
845 struct drm_display_mode *mode;
846 struct drm_display_info *info;
847
848 info = &connector->display_info;
849 info->width_mm = nt->conf->width_mm;
850 info->height_mm = nt->conf->height_mm;
851 mode = drm_mode_duplicate(connector->dev, &nt->conf->mode);
852 if (!mode) {
853 dev_err(panel->dev, "bad mode or failed to add mode\n");
854 return -EINVAL;
855 }
856 drm_mode_set_name(mode);
857 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
858
859 mode->width_mm = nt->conf->width_mm;
860 mode->height_mm = nt->conf->height_mm;
861 drm_mode_probed_add(connector, mode);
862
863 return 1;
864}
865
866static const struct drm_panel_funcs nt35510_drm_funcs = {
867 .unprepare = nt35510_unprepare,
868 .prepare = nt35510_prepare,
869 .get_modes = nt35510_get_modes,
870};
871
872static int nt35510_probe(struct mipi_dsi_device *dsi)
873{
874 struct device *dev = &dsi->dev;
875 struct nt35510 *nt;
876 int ret;
877
878 nt = devm_kzalloc(dev, sizeof(struct nt35510), GFP_KERNEL);
879 if (!nt)
880 return -ENOMEM;
881 mipi_dsi_set_drvdata(dsi, nt);
882 nt->dev = dev;
883
884 dsi->lanes = 2;
885 dsi->format = MIPI_DSI_FMT_RGB888;
886
887
888
889
890
891
892
893
894
895
896
897 dsi->hs_rate = 349440000;
898 dsi->lp_rate = 9600000;
899 dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
900
901
902
903
904
905 nt->conf = of_device_get_match_data(dev);
906 if (!nt->conf) {
907 dev_err(dev, "missing device configuration\n");
908 return -ENODEV;
909 }
910
911 nt->supplies[0].supply = "vdd";
912 nt->supplies[1].supply = "vddi";
913 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(nt->supplies),
914 nt->supplies);
915 if (ret < 0)
916 return ret;
917 ret = regulator_set_voltage(nt->supplies[0].consumer,
918 2300000, 4800000);
919 if (ret)
920 return ret;
921 ret = regulator_set_voltage(nt->supplies[1].consumer,
922 1650000, 3300000);
923 if (ret)
924 return ret;
925
926 nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
927 if (IS_ERR(nt->reset_gpio)) {
928 dev_err(dev, "error getting RESET GPIO\n");
929 return PTR_ERR(nt->reset_gpio);
930 }
931
932 drm_panel_init(&nt->panel, dev, &nt35510_drm_funcs,
933 DRM_MODE_CONNECTOR_DSI);
934
935
936
937
938
939
940 ret = drm_panel_of_backlight(&nt->panel);
941 if (ret) {
942 dev_err(dev, "error getting external backlight %d\n", ret);
943 return ret;
944 }
945 if (!nt->panel.backlight) {
946 struct backlight_device *bl;
947
948 bl = devm_backlight_device_register(dev, "nt35510", dev, nt,
949 &nt35510_bl_ops, NULL);
950 if (IS_ERR(bl)) {
951 dev_err(dev, "failed to register backlight device\n");
952 return PTR_ERR(bl);
953 }
954 bl->props.max_brightness = 255;
955 bl->props.brightness = 255;
956 bl->props.power = FB_BLANK_POWERDOWN;
957 nt->panel.backlight = bl;
958 }
959
960 drm_panel_add(&nt->panel);
961
962 ret = mipi_dsi_attach(dsi);
963 if (ret < 0)
964 drm_panel_remove(&nt->panel);
965
966 return 0;
967}
968
969static int nt35510_remove(struct mipi_dsi_device *dsi)
970{
971 struct nt35510 *nt = mipi_dsi_get_drvdata(dsi);
972 int ret;
973
974 mipi_dsi_detach(dsi);
975
976 ret = nt35510_power_off(nt);
977 drm_panel_remove(&nt->panel);
978
979 return ret;
980}
981
982
983
984
985
986
987
988
989#define NT35510_GAMMA_POS_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \
990 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \
991 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \
992 0x83, 0x02, 0x78, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \
993 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \
994 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE
995
996#define NT35510_GAMMA_NEG_DEFAULT 0x00, 0x01, 0x00, 0x43, 0x00, \
997 0x6B, 0x00, 0x87, 0x00, 0xA3, 0x00, 0xCE, 0x00, 0xF1, 0x01, \
998 0x27, 0x01, 0x53, 0x01, 0x98, 0x01, 0xCE, 0x02, 0x22, 0x02, \
999 0x43, 0x02, 0x50, 0x02, 0x9E, 0x02, 0xDD, 0x03, 0x00, 0x03, \
1000 0x2E, 0x03, 0x54, 0x03, 0x7F, 0x03, 0x95, 0x03, 0xB3, 0x03, \
1001 0xC2, 0x03, 0xE1, 0x03, 0xF1, 0x03, 0xFE
1002
1003
1004
1005
1006static const struct nt35510_config nt35510_hydis_hva40wv1 = {
1007 .width_mm = 52,
1008 .height_mm = 86,
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 .mode = {
1020
1021 .clock = 20000,
1022 .hdisplay = 480,
1023 .hsync_start = 480 + 2,
1024 .hsync_end = 480 + 2 + 0,
1025 .htotal = 480 + 2 + 0 + 5,
1026 .vdisplay = 800,
1027 .vsync_start = 800 + 2,
1028 .vsync_end = 800 + 2 + 0,
1029 .vtotal = 800 + 2 + 0 + 5,
1030 .flags = 0,
1031 },
1032
1033 .avdd = { 0x09, 0x09, 0x09 },
1034
1035 .bt1ctr = { 0x34, 0x34, 0x34 },
1036
1037 .avee = { 0x09, 0x09, 0x09 },
1038
1039 .bt2ctr = { 0x24, 0x24, 0x24 },
1040
1041 .vgh = { 0x05, 0x05, 0x05 },
1042
1043 .bt4ctr = { 0x24, 0x24, 0x24 },
1044
1045 .vgl = { 0x0B, 0x0B, 0x0B },
1046
1047 .bt5ctr = { 0x24, 0x24, 0x24 },
1048
1049 .vgp = { 0x00, 0xA3, 0x00 },
1050
1051 .vgn = { 0x00, 0xA3, 0x00 },
1052
1053 .sdeqctr = { 0x01, 0x05, 0x05, 0x05 },
1054
1055 .sdvpctr = 0x01,
1056
1057 .t1 = 0x0184,
1058
1059 .vbp = 7,
1060
1061 .vfp = 50,
1062
1063 .psel = 0,
1064
1065 .dpmctr12 = { 0x03, 0x00, 0x00, },
1066
1067 .gamma_corr_pos_r = { NT35510_GAMMA_POS_DEFAULT },
1068 .gamma_corr_pos_g = { NT35510_GAMMA_POS_DEFAULT },
1069 .gamma_corr_pos_b = { NT35510_GAMMA_POS_DEFAULT },
1070 .gamma_corr_neg_r = { NT35510_GAMMA_NEG_DEFAULT },
1071 .gamma_corr_neg_g = { NT35510_GAMMA_NEG_DEFAULT },
1072 .gamma_corr_neg_b = { NT35510_GAMMA_NEG_DEFAULT },
1073};
1074
1075static const struct of_device_id nt35510_of_match[] = {
1076 {
1077 .compatible = "hydis,hva40wv1",
1078 .data = &nt35510_hydis_hva40wv1,
1079 },
1080 { }
1081};
1082MODULE_DEVICE_TABLE(of, nt35510_of_match);
1083
1084static struct mipi_dsi_driver nt35510_driver = {
1085 .probe = nt35510_probe,
1086 .remove = nt35510_remove,
1087 .driver = {
1088 .name = "panel-novatek-nt35510",
1089 .of_match_table = nt35510_of_match,
1090 },
1091};
1092module_mipi_dsi_driver(nt35510_driver);
1093
1094MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
1095MODULE_DESCRIPTION("NT35510-based panel driver");
1096MODULE_LICENSE("GPL v2");
1097