uboot/board/friendlyarm/nanopi2/lcds.c
<<
>>
Prefs
   1// 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
 698