uboot/drivers/video/pxa_lcd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * PXA LCD Controller
   4 *
   5 * (C) Copyright 2001-2002
   6 * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
   7 */
   8
   9/************************************************************************/
  10/* ** HEADER FILES                                                      */
  11/************************************************************************/
  12
  13#include <common.h>
  14#include <log.h>
  15#include <asm/arch/pxa-regs.h>
  16#include <asm/io.h>
  17#include <lcd.h>
  18#include <linux/types.h>
  19#include <stdarg.h>
  20#include <stdio_dev.h>
  21
  22/* #define DEBUG */
  23
  24#ifdef CONFIG_LCD
  25
  26/*----------------------------------------------------------------------*/
  27/*
  28 * Define panel bpp, LCCR0, LCCR3 and panel_info video struct for
  29 * your display.
  30 */
  31
  32#ifdef CONFIG_PXA_VGA
  33/* LCD outputs connected to a video DAC  */
  34# define LCD_BPP        LCD_COLOR8
  35
  36/* you have to set lccr0 and lccr3 (including pcd) */
  37# define REG_LCCR0      0x003008f8
  38# define REG_LCCR3      0x0300FF01
  39
  40/* 640x480x16 @ 61 Hz */
  41vidinfo_t panel_info = {
  42        .vl_col         = 640,
  43        .vl_row         = 480,
  44        .vl_width       = 640,
  45        .vl_height      = 480,
  46        .vl_clkp        = CONFIG_SYS_HIGH,
  47        .vl_oep         = CONFIG_SYS_HIGH,
  48        .vl_hsp         = CONFIG_SYS_HIGH,
  49        .vl_vsp         = CONFIG_SYS_HIGH,
  50        .vl_dp          = CONFIG_SYS_HIGH,
  51        .vl_bpix        = LCD_BPP,
  52        .vl_lbw         = 0,
  53        .vl_splt        = 0,
  54        .vl_clor        = 0,
  55        .vl_tft         = 1,
  56        .vl_hpw         = 40,
  57        .vl_blw         = 56,
  58        .vl_elw         = 56,
  59        .vl_vpw         = 20,
  60        .vl_bfw         = 8,
  61        .vl_efw         = 8,
  62};
  63#endif /* CONFIG_PXA_VIDEO */
  64
  65/*----------------------------------------------------------------------*/
  66#ifdef CONFIG_SHARP_LM8V31
  67
  68# define LCD_BPP        LCD_COLOR8
  69# define LCD_INVERT_COLORS      /* Needed for colors to be correct, but why?    */
  70
  71/* you have to set lccr0 and lccr3 (including pcd) */
  72# define REG_LCCR0      0x0030087C
  73# define REG_LCCR3      0x0340FF08
  74
  75vidinfo_t panel_info = {
  76        .vl_col         = 640,
  77        .vl_row         = 480,
  78        .vl_width       = 157,
  79        .vl_height      = 118,
  80        .vl_clkp        = CONFIG_SYS_HIGH,
  81        .vl_oep         = CONFIG_SYS_HIGH,
  82        .vl_hsp         = CONFIG_SYS_HIGH,
  83        .vl_vsp         = CONFIG_SYS_HIGH,
  84        .vl_dp          = CONFIG_SYS_HIGH,
  85        .vl_bpix        = LCD_BPP,
  86        .vl_lbw         = 0,
  87        .vl_splt        = 1,
  88        .vl_clor        = 1,
  89        .vl_tft         = 0,
  90        .vl_hpw         = 1,
  91        .vl_blw         = 3,
  92        .vl_elw         = 3,
  93        .vl_vpw         = 1,
  94        .vl_bfw         = 0,
  95        .vl_efw         = 0,
  96};
  97#endif /* CONFIG_SHARP_LM8V31 */
  98/*----------------------------------------------------------------------*/
  99#ifdef CONFIG_VOIPAC_LCD
 100
 101# define LCD_BPP        LCD_COLOR8
 102# define LCD_INVERT_COLORS
 103
 104/* you have to set lccr0 and lccr3 (including pcd) */
 105# define REG_LCCR0      0x043008f8
 106# define REG_LCCR3      0x0340FF08
 107
 108vidinfo_t panel_info = {
 109        .vl_col         = 640,
 110        .vl_row         = 480,
 111        .vl_width       = 157,
 112        .vl_height      = 118,
 113        .vl_clkp        = CONFIG_SYS_HIGH,
 114        .vl_oep         = CONFIG_SYS_HIGH,
 115        .vl_hsp         = CONFIG_SYS_HIGH,
 116        .vl_vsp         = CONFIG_SYS_HIGH,
 117        .vl_dp          = CONFIG_SYS_HIGH,
 118        .vl_bpix        = LCD_BPP,
 119        .vl_lbw         = 0,
 120        .vl_splt        = 1,
 121        .vl_clor        = 1,
 122        .vl_tft         = 1,
 123        .vl_hpw         = 32,
 124        .vl_blw         = 144,
 125        .vl_elw         = 32,
 126        .vl_vpw         = 2,
 127        .vl_bfw         = 13,
 128        .vl_efw         = 30,
 129};
 130#endif /* CONFIG_VOIPAC_LCD */
 131
 132/*----------------------------------------------------------------------*/
 133#ifdef CONFIG_HITACHI_SX14
 134/* Hitachi SX14Q004-ZZA color STN LCD */
 135#define LCD_BPP         LCD_COLOR8
 136
 137/* you have to set lccr0 and lccr3 (including pcd) */
 138#define REG_LCCR0       0x00301079
 139#define REG_LCCR3       0x0340FF20
 140
 141vidinfo_t panel_info = {
 142        .vl_col         = 320,
 143        .vl_row         = 240,
 144        .vl_width       = 167,
 145        .vl_height      = 109,
 146        .vl_clkp        = CONFIG_SYS_HIGH,
 147        .vl_oep         = CONFIG_SYS_HIGH,
 148        .vl_hsp         = CONFIG_SYS_HIGH,
 149        .vl_vsp         = CONFIG_SYS_HIGH,
 150        .vl_dp          = CONFIG_SYS_HIGH,
 151        .vl_bpix        = LCD_BPP,
 152        .vl_lbw         = 1,
 153        .vl_splt        = 0,
 154        .vl_clor        = 1,
 155        .vl_tft         = 0,
 156        .vl_hpw         = 1,
 157        .vl_blw         = 1,
 158        .vl_elw         = 1,
 159        .vl_vpw         = 7,
 160        .vl_bfw         = 0,
 161        .vl_efw         = 0,
 162};
 163#endif /* CONFIG_HITACHI_SX14 */
 164
 165/*----------------------------------------------------------------------*/
 166#ifdef CONFIG_LMS283GF05
 167
 168# define LCD_BPP        LCD_COLOR8
 169/*# define LCD_INVERT_COLORS*/
 170
 171/* you have to set lccr0 and lccr3 (including pcd) */
 172# define REG_LCCR0      0x043008f8
 173# define REG_LCCR3      0x03b00009
 174
 175vidinfo_t panel_info = {
 176        .vl_col         = 240,
 177        .vl_row         = 320,
 178        .vl_rot         = 3,
 179        .vl_width       = 240,
 180        .vl_height      = 320,
 181        .vl_clkp        = CONFIG_SYS_HIGH,
 182        .vl_oep         = CONFIG_SYS_LOW,
 183        .vl_hsp         = CONFIG_SYS_LOW,
 184        .vl_vsp         = CONFIG_SYS_LOW,
 185        .vl_dp          = CONFIG_SYS_HIGH,
 186        .vl_bpix        = LCD_BPP,
 187        .vl_lbw         = 0,
 188        .vl_splt        = 1,
 189        .vl_clor        = 1,
 190        .vl_tft         = 1,
 191        .vl_hpw         = 4,
 192        .vl_blw         = 4,
 193        .vl_elw         = 8,
 194        .vl_vpw         = 4,
 195        .vl_bfw         = 4,
 196        .vl_efw         = 8,
 197};
 198#endif /* CONFIG_LMS283GF05 */
 199
 200/*----------------------------------------------------------------------*/
 201
 202#ifdef CONFIG_LQ038J7DH53
 203
 204# define LCD_BPP        LCD_COLOR8
 205
 206/* you have to set lccr0 and lccr3 (including pcd) */
 207# define REG_LCCR0      0x003008f9
 208# define REG_LCCR3      0x03700004
 209
 210vidinfo_t panel_info = {
 211        .vl_col         = 320,
 212        .vl_row         = 480,
 213        .vl_width       = 320,
 214        .vl_height      = 480,
 215        .vl_clkp        = CONFIG_SYS_HIGH,
 216        .vl_oep         = CONFIG_SYS_LOW,
 217        .vl_hsp         = CONFIG_SYS_LOW,
 218        .vl_vsp         = CONFIG_SYS_LOW,
 219        .vl_dp          = CONFIG_SYS_HIGH,
 220        .vl_bpix        = LCD_BPP,
 221        .vl_lbw         = 0,
 222        .vl_splt        = 1,
 223        .vl_clor        = 1,
 224        .vl_tft         = 1,
 225        .vl_hpw         = 0x04,
 226        .vl_blw         = 0x20,
 227        .vl_elw         = 0x01,
 228        .vl_vpw         = 0x01,
 229        .vl_bfw         = 0x04,
 230        .vl_efw         = 0x01,
 231};
 232#endif /* CONFIG_LQ038J7DH53 */
 233
 234/*----------------------------------------------------------------------*/
 235
 236#ifdef CONFIG_LITTLETON_LCD
 237# define LCD_BPP        LCD_COLOR8
 238
 239/* you have to set lccr0 and lccr3 (including pcd) */
 240# define REG_LCCR0      0x003008f8
 241# define REG_LCCR3      0x0300FF04
 242
 243vidinfo_t panel_info = {
 244        .vl_col         = 480,
 245        .vl_row         = 640,
 246        .vl_width       = 480,
 247        .vl_height      = 640,
 248        .vl_clkp        = CONFIG_SYS_HIGH,
 249        .vl_oep         = CONFIG_SYS_HIGH,
 250        .vl_hsp         = CONFIG_SYS_HIGH,
 251        .vl_vsp         = CONFIG_SYS_HIGH,
 252        .vl_dp          = CONFIG_SYS_HIGH,
 253        .vl_bpix        = LCD_BPP,
 254        .vl_lbw         = 0,
 255        .vl_splt        = 0,
 256        .vl_clor        = 0,
 257        .vl_tft         = 1,
 258        .vl_hpw         = 9,
 259        .vl_blw         = 8,
 260        .vl_elw         = 24,
 261        .vl_vpw         = 2,
 262        .vl_bfw         = 2,
 263        .vl_efw         = 4,
 264};
 265#endif /* CONFIG_LITTLETON_LCD */
 266
 267/*----------------------------------------------------------------------*/
 268
 269static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid);
 270static void pxafb_setup_gpio (vidinfo_t *vid);
 271static void pxafb_enable_controller (vidinfo_t *vid);
 272static int pxafb_init (vidinfo_t *vid);
 273
 274/************************************************************************/
 275/* ---------------  PXA chipset specific functions  ------------------- */
 276/************************************************************************/
 277
 278ushort *configuration_get_cmap(void)
 279{
 280        struct pxafb_info *fbi = &panel_info.pxa;
 281        return (ushort *)fbi->palette;
 282}
 283
 284void lcd_ctrl_init (void *lcdbase)
 285{
 286        pxafb_init_mem(lcdbase, &panel_info);
 287        pxafb_init(&panel_info);
 288        pxafb_setup_gpio(&panel_info);
 289        pxafb_enable_controller(&panel_info);
 290}
 291
 292/*----------------------------------------------------------------------*/
 293#if LCD_BPP == LCD_COLOR8
 294void
 295lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
 296{
 297        struct pxafb_info *fbi = &panel_info.pxa;
 298        unsigned short *palette = (unsigned short *)fbi->palette;
 299        u_int val;
 300
 301        if (regno < fbi->palette_size) {
 302                val = ((red << 8) & 0xf800);
 303                val |= ((green << 4) & 0x07e0);
 304                val |= (blue & 0x001f);
 305
 306#ifdef LCD_INVERT_COLORS
 307                palette[regno] = ~val;
 308#else
 309                palette[regno] = val;
 310#endif
 311        }
 312
 313        debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %04X\n",
 314                regno, &palette[regno],
 315                red, green, blue,
 316                palette[regno]);
 317}
 318#endif /* LCD_COLOR8 */
 319
 320/*----------------------------------------------------------------------*/
 321__weak void lcd_enable(void)
 322{
 323}
 324
 325/************************************************************************/
 326/* ** PXA255 specific routines                                          */
 327/************************************************************************/
 328
 329/*
 330 * Calculate fb size for VIDEOLFB_ATAG. Size returned contains fb,
 331 * descriptors and palette areas.
 332 */
 333ulong calc_fbsize (void)
 334{
 335        ulong size;
 336        int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
 337
 338        size = line_length * panel_info.vl_row;
 339        size += PAGE_SIZE;
 340
 341        return size;
 342}
 343
 344static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid)
 345{
 346        u_long palette_mem_size;
 347        struct pxafb_info *fbi = &vid->pxa;
 348        int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;
 349
 350        fbi->screen = (u_long)lcdbase;
 351
 352        fbi->palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16;
 353        palette_mem_size = fbi->palette_size * sizeof(u16);
 354
 355        debug("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
 356        /* locate palette and descs at end of page following fb */
 357        fbi->palette = (u_long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;
 358
 359        return 0;
 360}
 361#ifdef  CONFIG_CPU_MONAHANS
 362static inline void pxafb_setup_gpio (vidinfo_t *vid) {}
 363#else
 364static void pxafb_setup_gpio (vidinfo_t *vid)
 365{
 366        u_long lccr0;
 367
 368        /*
 369         * setup is based on type of panel supported
 370         */
 371
 372        lccr0 = vid->pxa.reg_lccr0;
 373
 374        /* 4 bit interface */
 375        if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD))
 376        {
 377                debug("Setting GPIO for 4 bit data\n");
 378                /* bits 58-61 */
 379                writel(readl(GPDR1) | (0xf << 26), GPDR1);
 380                writel((readl(GAFR1_U) & ~(0xff << 20)) | (0xaa << 20),
 381                        GAFR1_U);
 382
 383                /* bits 74-77 */
 384                writel(readl(GPDR2) | (0xf << 10), GPDR2);
 385                writel((readl(GAFR2_L) & ~(0xff << 20)) | (0xaa << 20),
 386                        GAFR2_L);
 387        }
 388
 389        /* 8 bit interface */
 390        else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) ||
 391                (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS)))
 392        {
 393                debug("Setting GPIO for 8 bit data\n");
 394                /* bits 58-65 */
 395                writel(readl(GPDR1) | (0x3f << 26), GPDR1);
 396                writel(readl(GPDR2) | (0x3), GPDR2);
 397
 398                writel((readl(GAFR1_U) & ~(0xfff << 20)) | (0xaaa << 20),
 399                        GAFR1_U);
 400                writel((readl(GAFR2_L) & ~0xf) | (0xa), GAFR2_L);
 401
 402                /* bits 74-77 */
 403                writel(readl(GPDR2) | (0xf << 10), GPDR2);
 404                writel((readl(GAFR2_L) & ~(0xff << 20)) | (0xaa << 20),
 405                        GAFR2_L);
 406        }
 407
 408        /* 16 bit interface */
 409        else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS)))
 410        {
 411                debug("Setting GPIO for 16 bit data\n");
 412                /* bits 58-77 */
 413                writel(readl(GPDR1) | (0x3f << 26), GPDR1);
 414                writel(readl(GPDR2) | 0x00003fff, GPDR2);
 415
 416                writel((readl(GAFR1_U) & ~(0xfff << 20)) | (0xaaa << 20),
 417                        GAFR1_U);
 418                writel((readl(GAFR2_L) & 0xf0000000) | 0x0aaaaaaa, GAFR2_L);
 419        }
 420        else
 421        {
 422                printf("pxafb_setup_gpio: unable to determine bits per pixel\n");
 423        }
 424}
 425#endif
 426
 427static void pxafb_enable_controller (vidinfo_t *vid)
 428{
 429        debug("Enabling LCD controller\n");
 430
 431        /* Sequence from 11.7.10 */
 432        writel(vid->pxa.reg_lccr3, LCCR3);
 433        writel(vid->pxa.reg_lccr2, LCCR2);
 434        writel(vid->pxa.reg_lccr1, LCCR1);
 435        writel(vid->pxa.reg_lccr0 & ~LCCR0_ENB, LCCR0);
 436        writel(vid->pxa.fdadr0, FDADR0);
 437        writel(vid->pxa.fdadr1, FDADR1);
 438        writel(readl(LCCR0) | LCCR0_ENB, LCCR0);
 439
 440#ifdef  CONFIG_CPU_MONAHANS
 441        writel(readl(CKENA) | CKENA_1_LCD, CKENA);
 442#else
 443        writel(readl(CKEN) | CKEN16_LCD, CKEN);
 444#endif
 445
 446        debug("FDADR0 = 0x%08x\n", readl(FDADR0));
 447        debug("FDADR1 = 0x%08x\n", readl(FDADR1));
 448        debug("LCCR0 = 0x%08x\n", readl(LCCR0));
 449        debug("LCCR1 = 0x%08x\n", readl(LCCR1));
 450        debug("LCCR2 = 0x%08x\n", readl(LCCR2));
 451        debug("LCCR3 = 0x%08x\n", readl(LCCR3));
 452}
 453
 454static int pxafb_init (vidinfo_t *vid)
 455{
 456        struct pxafb_info *fbi = &vid->pxa;
 457
 458        debug("Configuring PXA LCD\n");
 459
 460        fbi->reg_lccr0 = REG_LCCR0;
 461        fbi->reg_lccr3 = REG_LCCR3;
 462
 463        debug("vid: vl_col=%d hslen=%d lm=%d rm=%d\n",
 464                vid->vl_col, vid->vl_hpw,
 465                vid->vl_blw, vid->vl_elw);
 466        debug("vid: vl_row=%d vslen=%d um=%d bm=%d\n",
 467                vid->vl_row, vid->vl_vpw,
 468                vid->vl_bfw, vid->vl_efw);
 469
 470        fbi->reg_lccr1 =
 471                LCCR1_DisWdth(vid->vl_col) +
 472                LCCR1_HorSnchWdth(vid->vl_hpw) +
 473                LCCR1_BegLnDel(vid->vl_blw) +
 474                LCCR1_EndLnDel(vid->vl_elw);
 475
 476        fbi->reg_lccr2 =
 477                LCCR2_DisHght(vid->vl_row) +
 478                LCCR2_VrtSnchWdth(vid->vl_vpw) +
 479                LCCR2_BegFrmDel(vid->vl_bfw) +
 480                LCCR2_EndFrmDel(vid->vl_efw);
 481
 482        fbi->reg_lccr3 = REG_LCCR3 & ~(LCCR3_HSP | LCCR3_VSP);
 483        fbi->reg_lccr3 |= (vid->vl_hsp ? LCCR3_HorSnchL : LCCR3_HorSnchH)
 484                        | (vid->vl_vsp ? LCCR3_VrtSnchL : LCCR3_VrtSnchH);
 485
 486
 487        /* setup dma descriptors */
 488        fbi->dmadesc_fblow = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);
 489        fbi->dmadesc_fbhigh = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);
 490        fbi->dmadesc_palette = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);
 491
 492        #define BYTES_PER_PANEL ((fbi->reg_lccr0 & LCCR0_SDS) ? \
 493                (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8 / 2) : \
 494                (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8))
 495
 496        /* populate descriptors */
 497        fbi->dmadesc_fblow->fdadr = (u_long)fbi->dmadesc_fblow;
 498        fbi->dmadesc_fblow->fsadr = fbi->screen + BYTES_PER_PANEL;
 499        fbi->dmadesc_fblow->fidr  = 0;
 500        fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL;
 501
 502        fbi->fdadr1 = (u_long)fbi->dmadesc_fblow; /* only used in dual-panel mode */
 503
 504        fbi->dmadesc_fbhigh->fsadr = fbi->screen;
 505        fbi->dmadesc_fbhigh->fidr = 0;
 506        fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL;
 507
 508        fbi->dmadesc_palette->fsadr = fbi->palette;
 509        fbi->dmadesc_palette->fidr  = 0;
 510        fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL;
 511
 512        if( NBITS(vid->vl_bpix) < 12)
 513        {
 514                /* assume any mode with <12 bpp is palette driven */
 515                fbi->dmadesc_palette->fdadr = (u_long)fbi->dmadesc_fbhigh;
 516                fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_palette;
 517                /* flips back and forth between pal and fbhigh */
 518                fbi->fdadr0 = (u_long)fbi->dmadesc_palette;
 519        }
 520        else
 521        {
 522                /* palette shouldn't be loaded in true-color mode */
 523                fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_fbhigh;
 524                fbi->fdadr0 = (u_long)fbi->dmadesc_fbhigh; /* no pal just fbhigh */
 525        }
 526
 527        debug("fbi->dmadesc_fblow = 0x%lx\n", (u_long)fbi->dmadesc_fblow);
 528        debug("fbi->dmadesc_fbhigh = 0x%lx\n", (u_long)fbi->dmadesc_fbhigh);
 529        debug("fbi->dmadesc_palette = 0x%lx\n", (u_long)fbi->dmadesc_palette);
 530
 531        debug("fbi->dmadesc_fblow->fdadr = 0x%lx\n", fbi->dmadesc_fblow->fdadr);
 532        debug("fbi->dmadesc_fbhigh->fdadr = 0x%lx\n", fbi->dmadesc_fbhigh->fdadr);
 533        debug("fbi->dmadesc_palette->fdadr = 0x%lx\n", fbi->dmadesc_palette->fdadr);
 534
 535        debug("fbi->dmadesc_fblow->fsadr = 0x%lx\n", fbi->dmadesc_fblow->fsadr);
 536        debug("fbi->dmadesc_fbhigh->fsadr = 0x%lx\n", fbi->dmadesc_fbhigh->fsadr);
 537        debug("fbi->dmadesc_palette->fsadr = 0x%lx\n", fbi->dmadesc_palette->fsadr);
 538
 539        debug("fbi->dmadesc_fblow->ldcmd = 0x%lx\n", fbi->dmadesc_fblow->ldcmd);
 540        debug("fbi->dmadesc_fbhigh->ldcmd = 0x%lx\n", fbi->dmadesc_fbhigh->ldcmd);
 541        debug("fbi->dmadesc_palette->ldcmd = 0x%lx\n", fbi->dmadesc_palette->ldcmd);
 542
 543        return 0;
 544}
 545
 546/************************************************************************/
 547/************************************************************************/
 548
 549#endif /* CONFIG_LCD */
 550