uboot/drivers/video/ssd2828.c
<<
>>
Prefs
   1/*
   2 * (C) 2015 Siarhei Siamashka <siarhei.siamashka@gmail.com>
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7/*
   8 * Support for the SSD2828 bridge chip, which can take pixel data coming
   9 * from a parallel LCD interface and translate it on the flight into MIPI DSI
  10 * interface for driving a MIPI compatible TFT display.
  11 */
  12
  13#include <common.h>
  14#include <mipi_display.h>
  15#include <asm/arch/gpio.h>
  16#include <asm/gpio.h>
  17
  18#include "videomodes.h"
  19#include "ssd2828.h"
  20
  21#define         SSD2828_DIR     0xB0
  22#define         SSD2828_VICR1   0xB1
  23#define         SSD2828_VICR2   0xB2
  24#define         SSD2828_VICR3   0xB3
  25#define         SSD2828_VICR4   0xB4
  26#define         SSD2828_VICR5   0xB5
  27#define         SSD2828_VICR6   0xB6
  28#define         SSD2828_CFGR    0xB7
  29#define         SSD2828_VCR     0xB8
  30#define         SSD2828_PCR     0xB9
  31#define         SSD2828_PLCR    0xBA
  32#define         SSD2828_CCR     0xBB
  33#define         SSD2828_PSCR1   0xBC
  34#define         SSD2828_PSCR2   0xBD
  35#define         SSD2828_PSCR3   0xBE
  36#define         SSD2828_PDR     0xBF
  37#define         SSD2828_OCR     0xC0
  38#define         SSD2828_MRSR    0xC1
  39#define         SSD2828_RDCR    0xC2
  40#define         SSD2828_ARSR    0xC3
  41#define         SSD2828_LCR     0xC4
  42#define         SSD2828_ICR     0xC5
  43#define         SSD2828_ISR     0xC6
  44#define         SSD2828_ESR     0xC7
  45#define         SSD2828_DAR1    0xC9
  46#define         SSD2828_DAR2    0xCA
  47#define         SSD2828_DAR3    0xCB
  48#define         SSD2828_DAR4    0xCC
  49#define         SSD2828_DAR5    0xCD
  50#define         SSD2828_DAR6    0xCE
  51#define         SSD2828_HTTR1   0xCF
  52#define         SSD2828_HTTR2   0xD0
  53#define         SSD2828_LRTR1   0xD1
  54#define         SSD2828_LRTR2   0xD2
  55#define         SSD2828_TSR     0xD3
  56#define         SSD2828_LRR     0xD4
  57#define         SSD2828_PLLR    0xD5
  58#define         SSD2828_TR      0xD6
  59#define         SSD2828_TECR    0xD7
  60#define         SSD2828_ACR1    0xD8
  61#define         SSD2828_ACR2    0xD9
  62#define         SSD2828_ACR3    0xDA
  63#define         SSD2828_ACR4    0xDB
  64#define         SSD2828_IOCR    0xDC
  65#define         SSD2828_VICR7   0xDD
  66#define         SSD2828_LCFR    0xDE
  67#define         SSD2828_DAR7    0xDF
  68#define         SSD2828_PUCR1   0xE0
  69#define         SSD2828_PUCR2   0xE1
  70#define         SSD2828_PUCR3   0xE2
  71#define         SSD2828_CBCR1   0xE9
  72#define         SSD2828_CBCR2   0xEA
  73#define         SSD2828_CBSR    0xEB
  74#define         SSD2828_ECR     0xEC
  75#define         SSD2828_VSDR    0xED
  76#define         SSD2828_TMR     0xEE
  77#define         SSD2828_GPIO1   0xEF
  78#define         SSD2828_GPIO2   0xF0
  79#define         SSD2828_DLYA01  0xF1
  80#define         SSD2828_DLYA23  0xF2
  81#define         SSD2828_DLYB01  0xF3
  82#define         SSD2828_DLYB23  0xF4
  83#define         SSD2828_DLYC01  0xF5
  84#define         SSD2828_DLYC23  0xF6
  85#define         SSD2828_ACR5    0xF7
  86#define         SSD2828_RR      0xFF
  87
  88#define SSD2828_CFGR_HS                                 (1 << 0)
  89#define SSD2828_CFGR_CKE                                (1 << 1)
  90#define SSD2828_CFGR_SLP                                (1 << 2)
  91#define SSD2828_CFGR_VEN                                (1 << 3)
  92#define SSD2828_CFGR_HCLK                               (1 << 4)
  93#define SSD2828_CFGR_CSS                                (1 << 5)
  94#define SSD2828_CFGR_DCS                                (1 << 6)
  95#define SSD2828_CFGR_REN                                (1 << 7)
  96#define SSD2828_CFGR_ECD                                (1 << 8)
  97#define SSD2828_CFGR_EOT                                (1 << 9)
  98#define SSD2828_CFGR_LPE                                (1 << 10)
  99#define SSD2828_CFGR_TXD                                (1 << 11)
 100
 101#define SSD2828_VIDEO_MODE_NON_BURST_WITH_SYNC_PULSES   (0 << 2)
 102#define SSD2828_VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS   (1 << 2)
 103#define SSD2828_VIDEO_MODE_BURST                        (2 << 2)
 104
 105#define SSD2828_VIDEO_PIXEL_FORMAT_16BPP                0
 106#define SSD2828_VIDEO_PIXEL_FORMAT_18BPP_PACKED         1
 107#define SSD2828_VIDEO_PIXEL_FORMAT_18BPP_LOOSELY_PACKED 2
 108#define SSD2828_VIDEO_PIXEL_FORMAT_24BPP                3
 109
 110#define SSD2828_LP_CLOCK_DIVIDER(n)                     (((n) - 1) & 0x3F)
 111
 112/*
 113 * SPI transfer, using the "24-bit 3 wire" mode (that's how it is called in
 114 * the SSD2828 documentation). The 'dout' input parameter specifies 24-bits
 115 * of data to be written to SSD2828. Returns the lowest 16-bits of data,
 116 * that is received back.
 117 */
 118static u32 soft_spi_xfer_24bit_3wire(const struct ssd2828_config *drv, u32 dout)
 119{
 120        int j, bitlen = 24;
 121        u32 tmpdin = 0;
 122        /*
 123         * According to the "24 Bit 3 Wire SPI Interface Timing Characteristics"
 124         * and "TX_CLK Timing Characteristics" tables in the SSD2828 datasheet,
 125         * the lowest possible 'tx_clk' clock frequency is 8MHz, and SPI runs
 126         * at 1/8 of that after reset. So using 1 microsecond delays is safe in
 127         * the main loop. But the delays around chip select pin manipulations
 128         * need to be longer (up to 16 'tx_clk' cycles, or 2 microseconds in
 129         * the worst case).
 130         */
 131        const int spi_delay_us = 1;
 132        const int spi_cs_delay_us = 2;
 133
 134        gpio_set_value(drv->csx_pin, 0);
 135        udelay(spi_cs_delay_us);
 136        for (j = bitlen - 1; j >= 0; j--) {
 137                gpio_set_value(drv->sck_pin, 0);
 138                gpio_set_value(drv->sdi_pin, (dout & (1 << j)) != 0);
 139                udelay(spi_delay_us);
 140                if (drv->sdo_pin != -1)
 141                        tmpdin = (tmpdin << 1) | gpio_get_value(drv->sdo_pin);
 142                gpio_set_value(drv->sck_pin, 1);
 143                udelay(spi_delay_us);
 144        }
 145        udelay(spi_cs_delay_us);
 146        gpio_set_value(drv->csx_pin, 1);
 147        udelay(spi_cs_delay_us);
 148        return tmpdin & 0xFFFF;
 149}
 150
 151/*
 152 * Read from a SSD2828 hardware register (regnum >= 0xB0)
 153 */
 154static u32 read_hw_register(const struct ssd2828_config *cfg, u8 regnum)
 155{
 156        soft_spi_xfer_24bit_3wire(cfg, 0x700000 | regnum);
 157        return soft_spi_xfer_24bit_3wire(cfg, 0x730000);
 158}
 159
 160/*
 161 * Write to a SSD2828 hardware register (regnum >= 0xB0)
 162 */
 163static void write_hw_register(const struct ssd2828_config *cfg, u8 regnum,
 164                              u16 val)
 165{
 166        soft_spi_xfer_24bit_3wire(cfg, 0x700000 | regnum);
 167        soft_spi_xfer_24bit_3wire(cfg, 0x720000 | val);
 168}
 169
 170/*
 171 * Send MIPI command to the LCD panel (cmdnum < 0xB0)
 172 */
 173static void send_mipi_dcs_command(const struct ssd2828_config *cfg, u8 cmdnum)
 174{
 175        /* Set packet size to 1 (a single command with no parameters) */
 176        write_hw_register(cfg, SSD2828_PSCR1, 1);
 177        /* Send the command */
 178        write_hw_register(cfg, SSD2828_PDR, cmdnum);
 179}
 180
 181/*
 182 * Reset SSD2828
 183 */
 184static void ssd2828_reset(const struct ssd2828_config *cfg)
 185{
 186        /* RESET needs 10 milliseconds according to the datasheet */
 187        gpio_set_value(cfg->reset_pin, 0);
 188        mdelay(10);
 189        gpio_set_value(cfg->reset_pin, 1);
 190        mdelay(10);
 191}
 192
 193static int ssd2828_enable_gpio(const struct ssd2828_config *cfg)
 194{
 195        if (gpio_request(cfg->csx_pin, "ssd2828_csx")) {
 196                printf("SSD2828: request for 'ssd2828_csx' pin failed\n");
 197                return 1;
 198        }
 199        if (gpio_request(cfg->sck_pin, "ssd2828_sck")) {
 200                gpio_free(cfg->csx_pin);
 201                printf("SSD2828: request for 'ssd2828_sck' pin failed\n");
 202                return 1;
 203        }
 204        if (gpio_request(cfg->sdi_pin, "ssd2828_sdi")) {
 205                gpio_free(cfg->csx_pin);
 206                gpio_free(cfg->sck_pin);
 207                printf("SSD2828: request for 'ssd2828_sdi' pin failed\n");
 208                return 1;
 209        }
 210        if (gpio_request(cfg->reset_pin, "ssd2828_reset")) {
 211                gpio_free(cfg->csx_pin);
 212                gpio_free(cfg->sck_pin);
 213                gpio_free(cfg->sdi_pin);
 214                printf("SSD2828: request for 'ssd2828_reset' pin failed\n");
 215                return 1;
 216        }
 217        if (cfg->sdo_pin != -1 && gpio_request(cfg->sdo_pin, "ssd2828_sdo")) {
 218                gpio_free(cfg->csx_pin);
 219                gpio_free(cfg->sck_pin);
 220                gpio_free(cfg->sdi_pin);
 221                gpio_free(cfg->reset_pin);
 222                printf("SSD2828: request for 'ssd2828_sdo' pin failed\n");
 223                return 1;
 224        }
 225        gpio_direction_output(cfg->reset_pin, 0);
 226        gpio_direction_output(cfg->csx_pin, 1);
 227        gpio_direction_output(cfg->sck_pin, 1);
 228        gpio_direction_output(cfg->sdi_pin, 1);
 229        if (cfg->sdo_pin != -1)
 230                gpio_direction_input(cfg->sdo_pin);
 231
 232        return 0;
 233}
 234
 235static int ssd2828_free_gpio(const struct ssd2828_config *cfg)
 236{
 237        gpio_free(cfg->csx_pin);
 238        gpio_free(cfg->sck_pin);
 239        gpio_free(cfg->sdi_pin);
 240        gpio_free(cfg->reset_pin);
 241        if (cfg->sdo_pin != -1)
 242                gpio_free(cfg->sdo_pin);
 243        return 1;
 244}
 245
 246/*
 247 * PLL configuration register settings.
 248 *
 249 * See the "PLL Configuration Register Description" in the SSD2828 datasheet.
 250 */
 251static u32 construct_pll_config(u32 desired_pll_freq_kbps,
 252                                u32 reference_freq_khz)
 253{
 254        u32 div_factor = 1, mul_factor, fr = 0;
 255        u32 output_freq_kbps;
 256
 257        /* The intermediate clock after division can't be less than 5MHz */
 258        while (reference_freq_khz / (div_factor + 1) >= 5000)
 259                div_factor++;
 260        if (div_factor > 31)
 261                div_factor = 31;
 262
 263        mul_factor = DIV_ROUND_UP(desired_pll_freq_kbps * div_factor,
 264                                  reference_freq_khz);
 265
 266        output_freq_kbps = reference_freq_khz * mul_factor / div_factor;
 267
 268        if (output_freq_kbps >= 501000)
 269                fr = 3;
 270        else if (output_freq_kbps >= 251000)
 271                fr = 2;
 272        else if (output_freq_kbps >= 126000)
 273                fr = 1;
 274
 275        return (fr << 14) | (div_factor << 8) | mul_factor;
 276}
 277
 278static u32 decode_pll_config(u32 pll_config, u32 reference_freq_khz)
 279{
 280        u32 mul_factor = pll_config & 0xFF;
 281        u32 div_factor = (pll_config >> 8) & 0x1F;
 282        if (mul_factor == 0)
 283                mul_factor = 1;
 284        if (div_factor == 0)
 285                div_factor = 1;
 286        return reference_freq_khz * mul_factor / div_factor;
 287}
 288
 289static int ssd2828_configure_video_interface(const struct ssd2828_config *cfg,
 290                                             const struct ctfb_res_modes *mode)
 291{
 292        u32 val;
 293
 294        /* RGB Interface Control Register 1 */
 295        write_hw_register(cfg, SSD2828_VICR1, (mode->vsync_len << 8) |
 296                                              (mode->hsync_len));
 297
 298        /* RGB Interface Control Register 2 */
 299        u32 vbp = mode->vsync_len + mode->upper_margin;
 300        u32 hbp = mode->hsync_len + mode->left_margin;
 301        write_hw_register(cfg, SSD2828_VICR2, (vbp << 8) | hbp);
 302
 303        /* RGB Interface Control Register 3 */
 304        write_hw_register(cfg, SSD2828_VICR3, (mode->lower_margin << 8) |
 305                                              (mode->right_margin));
 306
 307        /* RGB Interface Control Register 4 */
 308        write_hw_register(cfg, SSD2828_VICR4, mode->xres);
 309
 310        /* RGB Interface Control Register 5 */
 311        write_hw_register(cfg, SSD2828_VICR5, mode->yres);
 312
 313        /* RGB Interface Control Register 6 */
 314        val = SSD2828_VIDEO_MODE_BURST;
 315        switch (cfg->ssd2828_color_depth) {
 316        case 16:
 317                val |= SSD2828_VIDEO_PIXEL_FORMAT_16BPP;
 318                break;
 319        case 18:
 320                val |= cfg->mipi_dsi_loosely_packed_pixel_format ?
 321                        SSD2828_VIDEO_PIXEL_FORMAT_18BPP_LOOSELY_PACKED :
 322                        SSD2828_VIDEO_PIXEL_FORMAT_18BPP_PACKED;
 323                break;
 324        case 24:
 325                val |= SSD2828_VIDEO_PIXEL_FORMAT_24BPP;
 326                break;
 327        default:
 328                printf("SSD2828: unsupported color depth\n");
 329                return 1;
 330        }
 331        write_hw_register(cfg, SSD2828_VICR6, val);
 332
 333        /* Lane Configuration Register */
 334        write_hw_register(cfg, SSD2828_LCFR,
 335                          cfg->mipi_dsi_number_of_data_lanes - 1);
 336
 337        return 0;
 338}
 339
 340int ssd2828_init(const struct ssd2828_config *cfg,
 341                 const struct ctfb_res_modes *mode)
 342{
 343        u32 lp_div, pll_freq_kbps, reference_freq_khz, pll_config;
 344        /* The LP clock speed is limited by 10MHz */
 345        const u32 mipi_dsi_low_power_clk_khz = 10000;
 346        /*
 347         * This is just the reset default value of CFGR register (0x301).
 348         * Because we are not always able to read back from SPI, have
 349         * it initialized here.
 350         */
 351        u32 cfgr_reg = SSD2828_CFGR_EOT | /* EOT Packet Enable */
 352                       SSD2828_CFGR_ECD | /* Disable ECC and CRC */
 353                       SSD2828_CFGR_HS;   /* Data lanes are in HS mode */
 354
 355        /* Initialize the pins */
 356        if (ssd2828_enable_gpio(cfg) != 0)
 357                return 1;
 358
 359        /* Reset the chip */
 360        ssd2828_reset(cfg);
 361
 362        /*
 363         * If there is a pin to read data back from SPI, then we are lucky. Try
 364         * to check if SPI is configured correctly and SSD2828 is actually able
 365         * to talk back.
 366         */
 367        if (cfg->sdo_pin != -1) {
 368                if (read_hw_register(cfg, SSD2828_DIR) != 0x2828 ||
 369                    read_hw_register(cfg, SSD2828_CFGR) != cfgr_reg) {
 370                        printf("SSD2828: SPI communication failed.\n");
 371                        ssd2828_free_gpio(cfg);
 372                        return 1;
 373                }
 374        }
 375
 376        /*
 377         * Pick the reference clock for PLL. If we know the exact 'tx_clk'
 378         * clock speed, then everything is good. If not, then we can fallback
 379         * to 'pclk' (pixel clock from the parallel LCD interface). In the
 380         * case of using this fallback, it is necessary to have parallel LCD
 381         * already initialized and running at this point.
 382         */
 383        reference_freq_khz = cfg->ssd2828_tx_clk_khz;
 384        if (reference_freq_khz  == 0) {
 385                reference_freq_khz = mode->pixclock_khz;
 386                /* Use 'pclk' as the reference clock for PLL */
 387                cfgr_reg |= SSD2828_CFGR_CSS;
 388        }
 389
 390        /*
 391         * Setup the parallel LCD timings in the appropriate registers.
 392         */
 393        if (ssd2828_configure_video_interface(cfg, mode) != 0) {
 394                ssd2828_free_gpio(cfg);
 395                return 1;
 396        }
 397
 398        /* Configuration Register */
 399        cfgr_reg &= ~SSD2828_CFGR_HS;  /* Data lanes are in LP mode */
 400        cfgr_reg |= SSD2828_CFGR_CKE;  /* Clock lane is in HS mode */
 401        cfgr_reg |= SSD2828_CFGR_DCS;  /* Only use DCS packets */
 402        write_hw_register(cfg, SSD2828_CFGR, cfgr_reg);
 403
 404        /* PLL Configuration Register */
 405        pll_config = construct_pll_config(
 406                                cfg->mipi_dsi_bitrate_per_data_lane_mbps * 1000,
 407                                reference_freq_khz);
 408        write_hw_register(cfg, SSD2828_PLCR, pll_config);
 409
 410        pll_freq_kbps = decode_pll_config(pll_config, reference_freq_khz);
 411        lp_div = DIV_ROUND_UP(pll_freq_kbps, mipi_dsi_low_power_clk_khz * 8);
 412
 413        /* VC Control Register */
 414        write_hw_register(cfg, SSD2828_VCR, 0);
 415
 416        /* Clock Control Register */
 417        write_hw_register(cfg, SSD2828_CCR, SSD2828_LP_CLOCK_DIVIDER(lp_div));
 418
 419        /* PLL Control Register */
 420        write_hw_register(cfg, SSD2828_PCR, 1); /* Enable PLL */
 421
 422        /* Wait for PLL lock */
 423        udelay(500);
 424
 425        send_mipi_dcs_command(cfg, MIPI_DCS_EXIT_SLEEP_MODE);
 426        mdelay(cfg->mipi_dsi_delay_after_exit_sleep_mode_ms);
 427
 428        send_mipi_dcs_command(cfg, MIPI_DCS_SET_DISPLAY_ON);
 429        mdelay(cfg->mipi_dsi_delay_after_set_display_on_ms);
 430
 431        cfgr_reg |= SSD2828_CFGR_HS;    /* Enable HS mode for data lanes */
 432        cfgr_reg |= SSD2828_CFGR_VEN;   /* Enable video pipeline */
 433        write_hw_register(cfg, SSD2828_CFGR, cfgr_reg);
 434
 435        return 0;
 436}
 437