uboot/drivers/video/fsl_dcu_fb.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Freescale Semiconductor, Inc.
   3 *
   4 * FSL DCU Framebuffer driver
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <asm/io.h>
  10#include <common.h>
  11#include <fsl_dcu_fb.h>
  12#include <linux/fb.h>
  13#include <malloc.h>
  14#include <video_fb.h>
  15#include "videomodes.h"
  16
  17/* Convert the X,Y resolution pair into a single number */
  18#define RESOLUTION(x, y) (((u32)(x) << 16) | (y))
  19
  20#ifdef CONFIG_SYS_FSL_DCU_LE
  21#define dcu_read32      in_le32
  22#define dcu_write32     out_le32
  23#elif defined(CONFIG_SYS_FSL_DCU_BE)
  24#define dcu_read32      in_be32
  25#define dcu_write32     out_be32
  26#endif
  27
  28#define DCU_MODE_BLEND_ITER(x)          ((x) << 20)
  29#define DCU_MODE_RASTER_EN              (1 << 14)
  30#define DCU_MODE_NORMAL                 1
  31#define DCU_MODE_COLORBAR               3
  32#define DCU_BGND_R(x)                   ((x) << 16)
  33#define DCU_BGND_G(x)                   ((x) << 8)
  34#define DCU_BGND_B(x)                   (x)
  35#define DCU_DISP_SIZE_DELTA_Y(x)        ((x) << 16)
  36#define DCU_DISP_SIZE_DELTA_X(x)        (x)
  37#define DCU_HSYN_PARA_BP(x)             ((x) << 22)
  38#define DCU_HSYN_PARA_PW(x)             ((x) << 11)
  39#define DCU_HSYN_PARA_FP(x)             (x)
  40#define DCU_VSYN_PARA_BP(x)             ((x) << 22)
  41#define DCU_VSYN_PARA_PW(x)             ((x) << 11)
  42#define DCU_VSYN_PARA_FP(x)             (x)
  43#define DCU_SYN_POL_INV_PXCK_FALL       (0 << 6)
  44#define DCU_SYN_POL_NEG_REMAIN          (0 << 5)
  45#define DCU_SYN_POL_INV_VS_LOW          (1 << 1)
  46#define DCU_SYN_POL_INV_HS_LOW          (1)
  47#define DCU_THRESHOLD_LS_BF_VS(x)       ((x) << 16)
  48#define DCU_THRESHOLD_OUT_BUF_HIGH(x)   ((x) << 8)
  49#define DCU_THRESHOLD_OUT_BUF_LOW(x)    (x)
  50#define DCU_UPDATE_MODE_MODE            (1 << 31)
  51#define DCU_UPDATE_MODE_READREG         (1 << 30)
  52
  53#define DCU_CTRLDESCLN_1_HEIGHT(x)      ((x) << 16)
  54#define DCU_CTRLDESCLN_1_WIDTH(x)       (x)
  55#define DCU_CTRLDESCLN_2_POSY(x)        ((x) << 16)
  56#define DCU_CTRLDESCLN_2_POSX(x)        (x)
  57#define DCU_CTRLDESCLN_4_EN             (1 << 31)
  58#define DCU_CTRLDESCLN_4_TILE_EN        (1 << 30)
  59#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT  (1 << 29)
  60#define DCU_CTRLDESCLN_4_SAFETY_EN      (1 << 28)
  61#define DCU_CTRLDESCLN_4_TRANS(x)       ((x) << 20)
  62#define DCU_CTRLDESCLN_4_BPP(x)         ((x) << 16)
  63#define DCU_CTRLDESCLN_4_RLE_EN         (1 << 15)
  64#define DCU_CTRLDESCLN_4_LUOFFS(x)      ((x) << 4)
  65#define DCU_CTRLDESCLN_4_BB_ON          (1 << 2)
  66#define DCU_CTRLDESCLN_4_AB(x)          (x)
  67#define DCU_CTRLDESCLN_5_CKMAX_R(x)     ((x) << 16)
  68#define DCU_CTRLDESCLN_5_CKMAX_G(x)     ((x) << 8)
  69#define DCU_CTRLDESCLN_5_CKMAX_B(x)     (x)
  70#define DCU_CTRLDESCLN_6_CKMIN_R(x)     ((x) << 16)
  71#define DCU_CTRLDESCLN_6_CKMIN_G(x)     ((x) << 8)
  72#define DCU_CTRLDESCLN_6_CKMIN_B(x)     (x)
  73#define DCU_CTRLDESCLN_7_TILE_VER(x)    ((x) << 16)
  74#define DCU_CTRLDESCLN_7_TILE_HOR(x)    (x)
  75#define DCU_CTRLDESCLN_8_FG_FCOLOR(x)   (x)
  76#define DCU_CTRLDESCLN_9_BG_BCOLOR(x)   (x)
  77
  78#define BPP_16_RGB565                   4
  79#define BPP_24_RGB888                   5
  80#define BPP_32_ARGB8888                 6
  81
  82/*
  83 * This setting is used for the TWR_LCD_RGB card
  84 */
  85static struct fb_videomode fsl_dcu_mode_480_272 = {
  86        .name           = "480x272-60",
  87        .refresh        = 60,
  88        .xres           = 480,
  89        .yres           = 272,
  90        .pixclock       = 91996,
  91        .left_margin    = 2,
  92        .right_margin   = 2,
  93        .upper_margin   = 1,
  94        .lower_margin   = 1,
  95        .hsync_len      = 41,
  96        .vsync_len      = 2,
  97        .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  98        .vmode          = FB_VMODE_NONINTERLACED
  99};
 100
 101/*
 102 * This setting is used for Siliconimage SiI9022A HDMI
 103 */
 104static struct fb_videomode fsl_dcu_mode_640_480 = {
 105        .name           = "640x480-60",
 106        .refresh        = 60,
 107        .xres           = 640,
 108        .yres           = 480,
 109        .pixclock       = 39722,
 110        .left_margin    = 48,
 111        .right_margin   = 16,
 112        .upper_margin   = 33,
 113        .lower_margin   = 10,
 114        .hsync_len      = 96,
 115        .vsync_len      = 2,
 116        .sync           = 0,
 117        .vmode          = FB_VMODE_NONINTERLACED,
 118};
 119
 120/*
 121 * DCU register map
 122 */
 123struct dcu_reg {
 124        u32 desc_cursor[4];
 125        u32 mode;
 126        u32 bgnd;
 127        u32 disp_size;
 128        u32 hsyn_para;
 129        u32 vsyn_para;
 130        u32 synpol;
 131        u32 threshold;
 132        u32 int_status;
 133        u32 int_mask;
 134        u32 colbar[8];
 135        u32 div_ratio;
 136        u32 sign_calc[2];
 137        u32 crc_val;
 138        u8 res_064[0x6c-0x64];
 139        u32 parr_err_status1;
 140        u8 res_070[0x7c-0x70];
 141        u32 parr_err_status3;
 142        u32 mparr_err_status1;
 143        u8 res_084[0x90-0x84];
 144        u32 mparr_err_status3;
 145        u32 threshold_inp_buf[2];
 146        u8 res_09c[0xa0-0x9c];
 147        u32 luma_comp;
 148        u32 chroma_red;
 149        u32 chroma_green;
 150        u32 chroma_blue;
 151        u32 crc_pos;
 152        u32 lyr_intpol_en;
 153        u32 lyr_luma_comp;
 154        u32 lyr_chrm_red;
 155        u32 lyr_chrm_grn;
 156        u32 lyr_chrm_blue;
 157        u8 res_0c4[0xcc-0xc8];
 158        u32 update_mode;
 159        u32 underrun;
 160        u8 res_0d4[0x100-0xd4];
 161        u32 gpr;
 162        u32 slr_l[2];
 163        u32 slr_disp_size;
 164        u32 slr_hvsync_para;
 165        u32 slr_pol;
 166        u32 slr_l_transp[2];
 167        u8 res_120[0x200-0x120];
 168        u32 ctrldescl[DCU_LAYER_MAX_NUM][16];
 169};
 170
 171static struct fb_info info;
 172
 173static void reset_total_layers(void)
 174{
 175        struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
 176        int i;
 177
 178        for (i = 0; i < DCU_LAYER_MAX_NUM; i++) {
 179                dcu_write32(&regs->ctrldescl[i][0], 0);
 180                dcu_write32(&regs->ctrldescl[i][1], 0);
 181                dcu_write32(&regs->ctrldescl[i][2], 0);
 182                dcu_write32(&regs->ctrldescl[i][3], 0);
 183                dcu_write32(&regs->ctrldescl[i][4], 0);
 184                dcu_write32(&regs->ctrldescl[i][5], 0);
 185                dcu_write32(&regs->ctrldescl[i][6], 0);
 186                dcu_write32(&regs->ctrldescl[i][7], 0);
 187                dcu_write32(&regs->ctrldescl[i][8], 0);
 188                dcu_write32(&regs->ctrldescl[i][9], 0);
 189                dcu_write32(&regs->ctrldescl[i][10], 0);
 190        }
 191
 192        dcu_write32(&regs->update_mode, DCU_UPDATE_MODE_READREG);
 193}
 194
 195static int layer_ctrldesc_init(int index, u32 pixel_format)
 196{
 197        struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
 198        unsigned int bpp = BPP_24_RGB888;
 199
 200        dcu_write32(&regs->ctrldescl[index][0],
 201                    DCU_CTRLDESCLN_1_HEIGHT(info.var.yres) |
 202                    DCU_CTRLDESCLN_1_WIDTH(info.var.xres));
 203
 204        dcu_write32(&regs->ctrldescl[index][1],
 205                    DCU_CTRLDESCLN_2_POSY(0) |
 206                    DCU_CTRLDESCLN_2_POSX(0));
 207
 208        dcu_write32(&regs->ctrldescl[index][2], (unsigned int)info.screen_base);
 209
 210        switch (pixel_format) {
 211        case 16:
 212                bpp = BPP_16_RGB565;
 213                break;
 214        case 24:
 215                bpp = BPP_24_RGB888;
 216                break;
 217        case 32:
 218                bpp = BPP_32_ARGB8888;
 219                break;
 220        default:
 221                printf("unsupported color depth: %u\n", pixel_format);
 222        }
 223
 224        dcu_write32(&regs->ctrldescl[index][3],
 225                    DCU_CTRLDESCLN_4_EN |
 226                    DCU_CTRLDESCLN_4_TRANS(0xff) |
 227                    DCU_CTRLDESCLN_4_BPP(bpp) |
 228                    DCU_CTRLDESCLN_4_AB(0));
 229
 230        dcu_write32(&regs->ctrldescl[index][4],
 231                    DCU_CTRLDESCLN_5_CKMAX_R(0xff) |
 232                    DCU_CTRLDESCLN_5_CKMAX_G(0xff) |
 233                    DCU_CTRLDESCLN_5_CKMAX_B(0xff));
 234        dcu_write32(&regs->ctrldescl[index][5],
 235                    DCU_CTRLDESCLN_6_CKMIN_R(0) |
 236                    DCU_CTRLDESCLN_6_CKMIN_G(0) |
 237                    DCU_CTRLDESCLN_6_CKMIN_B(0));
 238
 239        dcu_write32(&regs->ctrldescl[index][6],
 240                    DCU_CTRLDESCLN_7_TILE_VER(0) |
 241                    DCU_CTRLDESCLN_7_TILE_HOR(0));
 242
 243        dcu_write32(&regs->ctrldescl[index][7], DCU_CTRLDESCLN_8_FG_FCOLOR(0));
 244        dcu_write32(&regs->ctrldescl[index][8], DCU_CTRLDESCLN_9_BG_BCOLOR(0));
 245
 246        dcu_write32(&regs->update_mode, DCU_UPDATE_MODE_READREG);
 247
 248        return 0;
 249}
 250
 251int fsl_dcu_init(unsigned int xres, unsigned int yres,
 252                 unsigned int pixel_format)
 253{
 254        struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR;
 255        unsigned int div, mode;
 256
 257        /* Memory allocation for framebuffer */
 258        info.screen_size =
 259                info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8);
 260        info.screen_base = (char *)memalign(ARCH_DMA_MINALIGN,
 261                        roundup(info.screen_size, ARCH_DMA_MINALIGN));
 262        memset(info.screen_base, 0, info.screen_size);
 263
 264        reset_total_layers();
 265        div = dcu_set_pixel_clock(info.var.pixclock);
 266        dcu_write32(&regs->div_ratio, (div - 1));
 267
 268        dcu_write32(&regs->disp_size,
 269                    DCU_DISP_SIZE_DELTA_Y(info.var.yres) |
 270                    DCU_DISP_SIZE_DELTA_X(info.var.xres / 16));
 271
 272        dcu_write32(&regs->hsyn_para,
 273                    DCU_HSYN_PARA_BP(info.var.left_margin) |
 274                    DCU_HSYN_PARA_PW(info.var.hsync_len) |
 275                    DCU_HSYN_PARA_FP(info.var.right_margin));
 276
 277        dcu_write32(&regs->vsyn_para,
 278                    DCU_VSYN_PARA_BP(info.var.upper_margin) |
 279                    DCU_VSYN_PARA_PW(info.var.vsync_len) |
 280                    DCU_VSYN_PARA_FP(info.var.lower_margin));
 281
 282        dcu_write32(&regs->synpol,
 283                    DCU_SYN_POL_INV_PXCK_FALL |
 284                    DCU_SYN_POL_NEG_REMAIN |
 285                    DCU_SYN_POL_INV_VS_LOW |
 286                    DCU_SYN_POL_INV_HS_LOW);
 287
 288        dcu_write32(&regs->bgnd,
 289                    DCU_BGND_R(0) | DCU_BGND_G(0) | DCU_BGND_B(0));
 290
 291        dcu_write32(&regs->mode,
 292                    DCU_MODE_BLEND_ITER(DCU_LAYER_MAX_NUM) |
 293                    DCU_MODE_RASTER_EN);
 294
 295        dcu_write32(&regs->threshold,
 296                    DCU_THRESHOLD_LS_BF_VS(0x3) |
 297                    DCU_THRESHOLD_OUT_BUF_HIGH(0x78) |
 298                    DCU_THRESHOLD_OUT_BUF_LOW(0));
 299
 300        mode = dcu_read32(&regs->mode);
 301        dcu_write32(&regs->mode, mode | DCU_MODE_NORMAL);
 302
 303        layer_ctrldesc_init(0, pixel_format);
 304
 305        return 0;
 306}
 307
 308void *video_hw_init(void)
 309{
 310        static GraphicDevice ctfb;
 311        const char *options;
 312        unsigned int depth = 0, freq = 0;
 313        struct fb_videomode *fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
 314
 315        if (!video_get_video_mode(&ctfb.winSizeX, &ctfb.winSizeY, &depth, &freq,
 316                                  &options))
 317                return NULL;
 318
 319        /* Find the monitor port, which is a required option */
 320        if (!options)
 321                return NULL;
 322        if (strncmp(options, "monitor=", 8) != 0)
 323                return NULL;
 324
 325        switch (RESOLUTION(ctfb.winSizeX, ctfb.winSizeY)) {
 326        case RESOLUTION(480, 272):
 327                fsl_dcu_mode_db = &fsl_dcu_mode_480_272;
 328                break;
 329        case RESOLUTION(640, 480):
 330                fsl_dcu_mode_db = &fsl_dcu_mode_640_480;
 331                break;
 332        default:
 333                printf("unsupported resolution %ux%u\n",
 334                       ctfb.winSizeX, ctfb.winSizeY);
 335        }
 336
 337        info.var.xres = fsl_dcu_mode_db->xres;
 338        info.var.yres = fsl_dcu_mode_db->yres;
 339        info.var.bits_per_pixel = 32;
 340        info.var.pixclock = fsl_dcu_mode_db->pixclock;
 341        info.var.left_margin = fsl_dcu_mode_db->left_margin;
 342        info.var.right_margin = fsl_dcu_mode_db->right_margin;
 343        info.var.upper_margin = fsl_dcu_mode_db->upper_margin;
 344        info.var.lower_margin = fsl_dcu_mode_db->lower_margin;
 345        info.var.hsync_len = fsl_dcu_mode_db->hsync_len;
 346        info.var.vsync_len = fsl_dcu_mode_db->vsync_len;
 347        info.var.sync = fsl_dcu_mode_db->sync;
 348        info.var.vmode = fsl_dcu_mode_db->vmode;
 349        info.fix.line_length = info.var.xres * info.var.bits_per_pixel / 8;
 350
 351        if (platform_dcu_init(ctfb.winSizeX, ctfb.winSizeY,
 352                              options + 8, fsl_dcu_mode_db) < 0)
 353                return NULL;
 354
 355        ctfb.frameAdrs = (unsigned int)info.screen_base;
 356        ctfb.plnSizeX = ctfb.winSizeX;
 357        ctfb.plnSizeY = ctfb.winSizeY;
 358
 359        ctfb.gdfBytesPP = 4;
 360        ctfb.gdfIndex = GDF_32BIT_X888RGB;
 361
 362        ctfb.memSize = info.screen_size;
 363
 364        return &ctfb;
 365}
 366