blob: b37367300cf0c92e7c56840f7fdbdd947086737f [file] [log] [blame]
Stefan Boschb4bb31d2020-07-10 19:07:37 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2017 FriendlyARM (www.arm9.net)
4 */
5
6#include <config.h>
Stefan Boschb4bb31d2020-07-10 19:07:37 +02007#include <errno.h>
8#include <fdtdec.h>
9#include <fdt_support.h>
10#include <asm/io.h>
11
12#include <asm/arch/nexell.h>
13#include <asm/arch/display.h>
14#include <asm/arch/nx_gpio.h>
15
16#include "nxp-fb.h"
17
18/*
19 * param @module_index for nx_gpio APIs and will be removed
20 * after support pinctrl
21 */
22#ifndef PAD_GPIO_A
23#define PAD_GPIO_A 0
24#endif
25
26static inline void common_gpio_init(void)
27{
28 /* PVCLK */
29 nx_gpio_set_fast_slew(PAD_GPIO_A, 0, 1);
30}
31
32static void s70_gpio_init(void)
33{
34 int i;
35
36 /* PVCLK */
37 nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 1);
38
39 /* RGB24 */
40 for (i = 1; i < 25; i++)
41 nx_gpio_set_drive_strength(PAD_GPIO_A, i, 2);
42
43 /* HS/VS/DE */
44 for (; i < 28; i++)
45 nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
46}
47
48static void s702_gpio_init(void)
49{
50 int i;
51
52 common_gpio_init();
53
54 nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 2);
55
56 for (i = 1; i < 25; i++)
57 nx_gpio_set_drive_strength(PAD_GPIO_A, i, 0);
58
59 for (; i < 28; i++)
60 nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
61}
62
63static void s430_gpio_init(void)
64{
65 int i;
66
67 for (i = 0; i < 28; i++)
68 nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
69}
70
71static void hd101_gpio_init(void)
72{
73 int i;
74
75 common_gpio_init();
76
77 nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 2);
78
79 for (i = 1; i < 25; i++)
80 nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
81
82 nx_gpio_set_drive_strength(PAD_GPIO_A, 27, 1);
83}
84
85static void hd700_gpio_init(void)
86{
87 hd101_gpio_init();
88}
89
90/* NXP display configs for supported LCD */
91
92static struct nxp_lcd wxga_hd700 = {
93 .width = 800,
94 .height = 1280,
95 .p_width = 94,
96 .p_height = 151,
97 .bpp = 24,
98 .freq = 60,
99
100 .timing = {
101 .h_fp = 20,
102 .h_bp = 20,
103 .h_sw = 24,
104 .v_fp = 4,
105 .v_fpe = 1,
106 .v_bp = 4,
107 .v_bpe = 1,
108 .v_sw = 8,
109 },
110 .polarity = {
111 .rise_vclk = 0,
112 .inv_hsync = 0,
113 .inv_vsync = 0,
114 .inv_vden = 0,
115 },
116 .gpio_init = hd700_gpio_init,
117};
118
119static struct nxp_lcd wvga_s70 = {
120 .width = 800,
121 .height = 480,
122 .p_width = 155,
123 .p_height = 93,
124 .bpp = 24,
125 .freq = 61,
126
127 .timing = {
128 .h_fp = 48,
129 .h_bp = 36,
130 .h_sw = 10,
131 .v_fp = 22,
132 .v_fpe = 1,
133 .v_bp = 15,
134 .v_bpe = 1,
135 .v_sw = 8,
136 },
137 .polarity = {
138 .rise_vclk = 0,
139 .inv_hsync = 1,
140 .inv_vsync = 1,
141 .inv_vden = 0,
142 },
143 .gpio_init = s70_gpio_init,
144};
145
146static struct nxp_lcd wvga_s702 = {
147 .width = 800,
148 .height = 480,
149 .p_width = 155,
150 .p_height = 93,
151 .bpp = 24,
152 .freq = 61,
153
154 .timing = {
155 .h_fp = 44,
156 .h_bp = 26,
157 .h_sw = 20,
158 .v_fp = 22,
159 .v_fpe = 1,
160 .v_bp = 15,
161 .v_bpe = 1,
162 .v_sw = 8,
163 },
164 .polarity = {
165 .rise_vclk = 1,
166 .inv_hsync = 1,
167 .inv_vsync = 1,
168 .inv_vden = 0,
169 },
170 .gpio_init = s702_gpio_init,
171};
172
173static struct nxp_lcd wvga_s70d = {
174 .width = 800,
175 .height = 480,
176 .p_width = 155,
177 .p_height = 93,
178 .bpp = 24,
179 .freq = 61,
180
181 .timing = {
182 .h_fp = 80,
183 .h_bp = 78,
184 .h_sw = 10,
185 .v_fp = 22,
186 .v_fpe = 1,
187 .v_bp = 24,
188 .v_bpe = 1,
189 .v_sw = 8,
190 },
191 .polarity = {
192 .rise_vclk = 0,
193 .inv_hsync = 1,
194 .inv_vsync = 1,
195 .inv_vden = 0,
196 },
197 .gpio_init = s702_gpio_init,
198};
199
200static struct nxp_lcd wvga_w50 = {
201 .width = 800,
202 .height = 480,
203 .p_width = 108,
204 .p_height = 64,
205 .bpp = 24,
206 .freq = 61,
207
208 .timing = {
209 .h_fp = 40,
210 .h_bp = 40,
211 .h_sw = 48,
212 .v_fp = 20,
213 .v_fpe = 1,
214 .v_bp = 20,
215 .v_bpe = 1,
216 .v_sw = 12,
217 },
218 .polarity = {
219 .rise_vclk = 0,
220 .inv_hsync = 1,
221 .inv_vsync = 1,
222 .inv_vden = 0,
223 },
224 .gpio_init = s70_gpio_init,
225};
226
227static struct nxp_lcd wvga_s430 = {
228 .width = 480,
229 .height = 800,
230 .p_width = 108,
231 .p_height = 64,
232 .bpp = 24,
233 .freq = 60,
234
235 .timing = {
236 .h_fp = 64,
237 .h_bp = 0,
238 .h_sw = 16,
239 .v_fp = 32,
240 .v_fpe = 1,
241 .v_bp = 0,
242 .v_bpe = 1,
243 .v_sw = 16,
244 },
245 .polarity = {
246 .rise_vclk = 1,
247 .inv_hsync = 1,
248 .inv_vsync = 1,
249 .inv_vden = 0,
250 },
251 .gpio_init = s430_gpio_init,
252};
253
254static struct nxp_lcd wsvga_w101 = {
255 .width = 1024,
256 .height = 600,
257 .p_width = 204,
258 .p_height = 120,
259 .bpp = 24,
260 .freq = 60,
261
262 .timing = {
263 .h_fp = 40,
264 .h_bp = 40,
265 .h_sw = 200,
266 .v_fp = 8,
267 .v_fpe = 1,
268 .v_bp = 8,
269 .v_bpe = 1,
270 .v_sw = 16,
271 },
272 .polarity = {
273 .rise_vclk = 1,
274 .inv_hsync = 1,
275 .inv_vsync = 1,
276 .inv_vden = 0,
277 },
278};
279
280static struct nxp_lcd wsvga_x710 = {
281 .width = 1024,
282 .height = 600,
283 .p_width = 154,
284 .p_height = 90,
285 .bpp = 24,
286 .freq = 61,
287
288 .timing = {
289 .h_fp = 84,
290 .h_bp = 84,
291 .h_sw = 88,
292 .v_fp = 10,
293 .v_fpe = 1,
294 .v_bp = 10,
295 .v_bpe = 1,
296 .v_sw = 20,
297 },
298 .polarity = {
299 .rise_vclk = 0,
300 .inv_hsync = 1,
301 .inv_vsync = 1,
302 .inv_vden = 0,
303 },
304 .gpio_init = hd101_gpio_init,
305};
306
307static struct nxp_lcd xga_a97 = {
308 .width = 1024,
309 .height = 768,
310 .p_width = 200,
311 .p_height = 150,
312 .bpp = 24,
313 .freq = 61,
314
315 .timing = {
316 .h_fp = 12,
317 .h_bp = 12,
318 .h_sw = 4,
319 .v_fp = 8,
320 .v_fpe = 1,
321 .v_bp = 8,
322 .v_bpe = 1,
323 .v_sw = 4,
324 },
325 .polarity = {
326 .rise_vclk = 0,
327 .inv_hsync = 1,
328 .inv_vsync = 1,
329 .inv_vden = 0,
330 },
331};
332
333static struct nxp_lcd xga_lq150 = {
334 .width = 1024,
335 .height = 768,
336 .p_width = 304,
337 .p_height = 228,
338 .bpp = 24,
339 .freq = 60,
340
341 .timing = {
342 .h_fp = 12,
343 .h_bp = 12,
344 .h_sw = 40,
345 .v_fp = 8,
346 .v_fpe = 1,
347 .v_bp = 8,
348 .v_bpe = 1,
349 .v_sw = 40,
350 },
351 .polarity = {
352 .rise_vclk = 0,
353 .inv_hsync = 1,
354 .inv_vsync = 1,
355 .inv_vden = 0,
356 },
357};
358
359static struct nxp_lcd vga_l80 = {
360 .width = 640,
361 .height = 480,
362 .p_width = 160,
363 .p_height = 120,
364 .bpp = 32,
365 .freq = 60,
366
367 .timing = {
368 .h_fp = 35,
369 .h_bp = 53,
370 .h_sw = 73,
371 .v_fp = 3,
372 .v_fpe = 1,
373 .v_bp = 29,
374 .v_bpe = 1,
375 .v_sw = 6,
376 },
377 .polarity = {
378 .rise_vclk = 0,
379 .inv_hsync = 1,
380 .inv_vsync = 1,
381 .inv_vden = 0,
382 },
383};
384
385static struct nxp_lcd wxga_bp101 = {
386 .width = 1280,
387 .height = 800,
388 .p_width = 218,
389 .p_height = 136,
390 .bpp = 24,
391 .freq = 60,
392
393 .timing = {
394 .h_fp = 20,
395 .h_bp = 20,
396 .h_sw = 24,
397 .v_fp = 4,
398 .v_fpe = 1,
399 .v_bp = 4,
400 .v_bpe = 1,
401 .v_sw = 8,
402 },
403 .polarity = {
404 .rise_vclk = 1,
405 .inv_hsync = 1,
406 .inv_vsync = 1,
407 .inv_vden = 0,
408 },
409};
410
411static struct nxp_lcd wxga_hd101 = {
412 .width = 1280,
413 .height = 800,
414 .p_width = 218,
415 .p_height = 136,
416 .bpp = 24,
417 .freq = 60,
418
419 .timing = {
420 .h_fp = 16,
421 .h_bp = 16,
422 .h_sw = 30,
423 .v_fp = 8,
424 .v_fpe = 1,
425 .v_bp = 8,
426 .v_bpe = 1,
427 .v_sw = 12,
428 },
429 .polarity = {
430 .rise_vclk = 1,
431 .inv_hsync = 0,
432 .inv_vsync = 0,
433 .inv_vden = 0,
434 },
435 .gpio_init = hd101_gpio_init,
436};
437
438static struct nxp_lcd hvga_h43 = {
439 .width = 480,
440 .height = 272,
441 .p_width = 96,
442 .p_height = 54,
443 .bpp = 32,
444 .freq = 65,
445
446 .timing = {
447 .h_fp = 5,
448 .h_bp = 40,
449 .h_sw = 2,
450 .v_fp = 8,
451 .v_fpe = 1,
452 .v_bp = 8,
453 .v_bpe = 1,
454 .v_sw = 2,
455 },
456 .polarity = {
457 .rise_vclk = 0,
458 .inv_hsync = 1,
459 .inv_vsync = 1,
460 .inv_vden = 0,
461 },
462};
463
464static struct nxp_lcd hvga_p43 = {
465 .width = 480,
466 .height = 272,
467 .p_width = 96,
468 .p_height = 54,
469 .bpp = 32,
470 .freq = 65,
471
472 .timing = {
473 .h_fp = 5,
474 .h_bp = 40,
475 .h_sw = 2,
476 .v_fp = 8,
477 .v_fpe = 1,
478 .v_bp = 9,
479 .v_bpe = 1,
480 .v_sw = 2,
481 },
482 .polarity = {
483 .rise_vclk = 1,
484 .inv_hsync = 1,
485 .inv_vsync = 1,
486 .inv_vden = 0,
487 },
488};
489
490static struct nxp_lcd qvga_w35 = {
491 .width = 320,
492 .height = 240,
493 .p_width = 70,
494 .p_height = 52,
495 .bpp = 16,
496 .freq = 65,
497
498 .timing = {
499 .h_fp = 4,
500 .h_bp = 70,
501 .h_sw = 4,
502 .v_fp = 4,
503 .v_fpe = 1,
504 .v_bp = 12,
505 .v_bpe = 1,
506 .v_sw = 4,
507 },
508 .polarity = {
509 .rise_vclk = 1,
510 .inv_hsync = 0,
511 .inv_vsync = 0,
512 .inv_vden = 0,
513 },
514};
515
516/* HDMI */
517static struct nxp_lcd hdmi_def = {
518 .width = 1920,
519 .height = 1080,
520 .p_width = 480,
521 .p_height = 320,
522 .bpp = 24,
523 .freq = 60,
524
525 .timing = {
526 .h_fp = 12,
527 .h_bp = 12,
528 .h_sw = 4,
529 .v_fp = 8,
530 .v_fpe = 1,
531 .v_bp = 8,
532 .v_bpe = 1,
533 .v_sw = 4,
534 },
535 .polarity = {
536 .rise_vclk = 0,
537 .inv_hsync = 1,
538 .inv_vsync = 1,
539 .inv_vden = 0,
540 },
541};
542
543static struct hdmi_config {
544 char *name;
545 int width;
546 int height;
547} bd_hdmi_config[] = {
548 { "HDMI1080P60", 1920, 1080 },
549 { "HDMI1080I60", 1920, 1080 },
550 { "HDMI1080P30", 1920, 1080 },
551 { "HDMI1080P50", 1920, 1080 },
552 { "HDMI1080I50", 1920, 1080 },
553
554 { "HDMI1080P60D", 960, 536 },
555 { "HDMI1080I60D", 960, 536 },
556 { "HDMI1080P30D", 960, 536 },
557 { "HDMI1080P50D", 960, 536 },
558 { "HDMI1080I50D", 960, 536 },
559
560 { "HDMI720P60", 1280, 720 },
561 { "HDMI720P60D", 640, 360 },
562 { "HDMI720P50", 1280, 720 },
563 { "HDMI720P50D", 640, 360 },
564
565 { "HDMI576P16X9", 720, 576 },
566 { "HDMI576P16X9D", 720, 576 },
567 { "HDMI576P4X3", 720, 576 },
568 { "HDMI576P4X3D", 720, 576 },
569
570 { "HDMI480P16X9", 720, 480 },
571 { "HDMI480P16X9D", 720, 480 },
572 { "HDMI480P4X3", 720, 480 },
573 { "HDMI480P4X3D", 720, 480 },
574};
575
576/* Try to guess LCD panel by kernel command line, or
577 * using *HD101* as default
578 */
579static struct {
580 int id;
581 char *name;
582 struct nxp_lcd *lcd;
583 int dpi;
584 int ctp;
585 enum lcd_format fmt;
586} bd_lcd_config[] = {
587 { 25, "HD101", &wxga_hd101, 0, 1, LCD_RGB },
588 { 32, "HD101B", &wxga_hd101, 0, 1, LCD_RGB },
589 { 18, "HD700", &wxga_hd700, 213, 1, LCD_RGB },
590 { 30, "HD702", &wxga_hd700, 213, 1, LCD_RGB },
591 { 33, "H70", &wxga_hd700, 213, 0, LCD_VESA },
592 { 3, "S70", &wvga_s70, 128, 1, LCD_RGB },
593 { 36, "S701", &wvga_s70, 128, 1, LCD_RGB },
594 { 24, "S702", &wvga_s702, 128, 3, LCD_RGB },
595 { 26, "S70D", &wvga_s70d, 128, 0, LCD_RGB },
596 { 14, "H43", &hvga_h43, 0, 0, LCD_RGB },
597 { 19, "P43", &hvga_p43, 0, 0, LCD_RGB },
598 { 8, "W35", &qvga_w35, 0, 0, LCD_RGB },
599 { 28, "X710", &wsvga_x710, 0, 1, LCD_RGB },
600 { 31, "S430", &wvga_s430, 180, 1, LCD_RGB },
601 { 4, "W50", &wvga_w50, 0, 0, LCD_RGB },
602
603 /* TODO: Testing */
604 { 15, "W101", &wsvga_w101, 0, 1, LCD_RGB },
605 { 5, "L80", &vga_l80, 0, 1, LCD_RGB },
606 { -1, "A97", &xga_a97, 0, 0, LCD_RGB },
607 { -1, "LQ150", &xga_lq150, 0, 1, LCD_RGB },
608 { -1, "BP101", &wxga_bp101, 0, 1, LCD_RGB },
609 /* Pls keep it at last */
610 { 128, "HDMI", &hdmi_def, 0, 0, LCD_HDMI },
611};
612
613static int lcd_idx;
614
615int bd_setup_lcd_by_id(int id)
616{
617 int i;
618
619 for (i = 0; i < ARRAY_SIZE(bd_lcd_config); i++) {
620 if (bd_lcd_config[i].id == id) {
621 lcd_idx = i;
622 break;
623 }
624 }
625
626 if (i >= ARRAY_SIZE(bd_lcd_config)) {
627 /* NOT found */
628 return -19;
629 }
630
631 return bd_lcd_config[i].id;
632}
633
634int bd_setup_lcd_by_name(char *str)
635{
636 char *delim;
637 int i;
638
639 delim = strchr(str, ',');
640 if (delim)
641 *delim++ = '\0';
642
643 if (!strncasecmp("HDMI", str, 4)) {
644 struct hdmi_config *cfg = &bd_hdmi_config[0];
645 struct nxp_lcd *lcd;
646
647 lcd_idx = ARRAY_SIZE(bd_lcd_config) - 1;
648 lcd = bd_lcd_config[lcd_idx].lcd;
649
650 for (i = 0; i < ARRAY_SIZE(bd_hdmi_config); i++, cfg++) {
651 if (!strcasecmp(cfg->name, str)) {
652 lcd->width = cfg->width;
653 lcd->height = cfg->height;
654 bd_lcd_config[lcd_idx].name = cfg->name;
655 goto __ret;
656 }
657 }
658 }
659
660 for (i = 0; i < ARRAY_SIZE(bd_lcd_config); i++) {
661 if (!strcasecmp(bd_lcd_config[i].name, str)) {
662 lcd_idx = i;
663 break;
664 }
665 }
666
667__ret:
668 return 0;
669}
670
671struct nxp_lcd *bd_get_lcd(void)
672{
673 return bd_lcd_config[lcd_idx].lcd;
674}
675
676const char *bd_get_lcd_name(void)
677{
678 return bd_lcd_config[lcd_idx].name;
679}
680
681enum lcd_format bd_get_lcd_format(void)
682{
683 return bd_lcd_config[lcd_idx].fmt;
684}
685
686int bd_get_lcd_density(void)
687{
688 return bd_lcd_config[lcd_idx].dpi;
689}
690
691#if CONFIG_IS_ENABLED(OF_CONTROL)
692int bd_fixup_lcd_fdt(void *blob, struct nxp_lcd *lcd)
693{
694 return 0;
695}
696#endif