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