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