uboot/board/cm-bf548/video.c
<<
>>
Prefs
   1/*
   2 * video.c - run splash screen on lcd
   3 *
   4 * Copyright (c) 2007-2008 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <stdarg.h>
  10#include <common.h>
  11#include <config.h>
  12#include <malloc.h>
  13#include <asm/blackfin.h>
  14#include <asm/clock.h>
  15#include <asm/gpio.h>
  16#include <asm/portmux.h>
  17#include <asm/mach-common/bits/dma.h>
  18#include <i2c.h>
  19#include <linux/types.h>
  20#include <stdio_dev.h>
  21
  22#include <lzma/LzmaTypes.h>
  23#include <lzma/LzmaDec.h>
  24#include <lzma/LzmaTools.h>
  25
  26#define DMA_SIZE16      2
  27
  28#include <asm/mach-common/bits/eppi.h>
  29
  30#include EASYLOGO_HEADER
  31
  32#define LCD_X_RES               480     /*Horizontal Resolution */
  33#define LCD_Y_RES               272     /* Vertical Resolution */
  34
  35#define LCD_BPP                 24      /* Bit Per Pixel */
  36#define LCD_PIXEL_SIZE          (LCD_BPP / 8)
  37#define DMA_BUS_SIZE            32
  38#define ACTIVE_VIDEO_MEM_OFFSET 0
  39
  40/*      -- Horizontal synchronizing --
  41 *
  42 * Timing characteristics taken from the SHARP LQ043T1DG01 datasheet
  43 * (LCY-W-06602A Page 9 of 22)
  44 *
  45 * Clock Frequency      1/Tc Min 7.83 Typ 9.00 Max 9.26 MHz
  46 *
  47 * Period               TH - 525 - Clock
  48 * Pulse width          THp - 41 - Clock
  49 * Horizontal period    THd - 480 - Clock
  50 * Back porch           THb - 2 - Clock
  51 * Front porch          THf - 2 - Clock
  52 *
  53 * -- Vertical synchronizing --
  54 * Period               TV - 286 - Line
  55 * Pulse width          TVp - 10 - Line
  56 * Vertical period      TVd - 272 - Line
  57 * Back porch           TVb - 2 - Line
  58 * Front porch          TVf - 2 - Line
  59 */
  60
  61#define LCD_CLK                 (8*1000*1000)   /* 8MHz */
  62
  63/* # active data to transfer after Horizontal Delay clock */
  64#define EPPI_HCOUNT             LCD_X_RES
  65
  66/* # active lines to transfer after Vertical Delay clock */
  67#define EPPI_VCOUNT             LCD_Y_RES
  68
  69/* Samples per Line = 480 (active data) + 45 (padding) */
  70#define EPPI_LINE               525
  71
  72/* Lines per Frame = 272 (active data) + 14 (padding) */
  73#define EPPI_FRAME              286
  74
  75/* FS1 (Hsync) Width (Typical)*/
  76#define EPPI_FS1W_HBL           41
  77
  78/* FS1 (Hsync) Period (Typical) */
  79#define EPPI_FS1P_AVPL          EPPI_LINE
  80
  81/* Horizontal Delay clock after assertion of Hsync (Typical) */
  82#define EPPI_HDELAY             43
  83
  84/* FS2 (Vsync) Width    = FS1 (Hsync) Period * 10 */
  85#define EPPI_FS2W_LVB           (EPPI_LINE * 10)
  86
  87 /* FS2 (Vsync) Period   = FS1 (Hsync) Period * Lines per Frame */
  88#define EPPI_FS2P_LAVF          (EPPI_LINE * EPPI_FRAME)
  89
  90/* Vertical Delay after assertion of Vsync (2 Lines) */
  91#define EPPI_VDELAY             12
  92
  93#define EPPI_CLIP               0xFF00FF00
  94
  95/* EPPI Control register configuration value for RGB out
  96 * - EPPI as Output
  97 * GP 2 frame sync mode,
  98 * Internal Clock generation disabled, Internal FS generation enabled,
  99 * Receives samples on EPPI_CLK raising edge, Transmits samples on EPPI_CLK falling edge,
 100 * FS1 & FS2 are active high,
 101 * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
 102 * DMA Unpacking disabled when RGB Formating is enabled, otherwise DMA unpacking enabled
 103 * Swapping Enabled,
 104 * One (DMA) Channel Mode,
 105 * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
 106 * Regular watermark - when FIFO is 100% full,
 107 * Urgent watermark - when FIFO is 75% full
 108 */
 109
 110#define EPPI_CONTROL            (0x20136E2E)
 111
 112static inline u16 get_eppi_clkdiv(u32 target_ppi_clk)
 113{
 114        u32 sclk = get_sclk();
 115
 116        /* EPPI_CLK = (SCLK) / (2 * (EPPI_CLKDIV[15:0] + 1)) */
 117
 118        return (((sclk / target_ppi_clk) / 2) - 1);
 119}
 120
 121void Init_PPI(void)
 122{
 123        u16 eppi_clkdiv = get_eppi_clkdiv(LCD_CLK);
 124
 125        bfin_write_EPPI0_FS1W_HBL(EPPI_FS1W_HBL);
 126        bfin_write_EPPI0_FS1P_AVPL(EPPI_FS1P_AVPL);
 127        bfin_write_EPPI0_FS2W_LVB(EPPI_FS2W_LVB);
 128        bfin_write_EPPI0_FS2P_LAVF(EPPI_FS2P_LAVF);
 129        bfin_write_EPPI0_CLIP(EPPI_CLIP);
 130
 131        bfin_write_EPPI0_FRAME(EPPI_FRAME);
 132        bfin_write_EPPI0_LINE(EPPI_LINE);
 133
 134        bfin_write_EPPI0_HCOUNT(EPPI_HCOUNT);
 135        bfin_write_EPPI0_HDELAY(EPPI_HDELAY);
 136        bfin_write_EPPI0_VCOUNT(EPPI_VCOUNT);
 137        bfin_write_EPPI0_VDELAY(EPPI_VDELAY);
 138
 139        bfin_write_EPPI0_CLKDIV(eppi_clkdiv);
 140
 141/*
 142 * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
 143 * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
 144 */
 145#if defined(CONFIG_VIDEO_RGB666)
 146        bfin_write_EPPI0_CONTROL((EPPI_CONTROL & ~DLENGTH) | DLEN_18 |
 147                                 RGB_FMT_EN);
 148#else
 149        bfin_write_EPPI0_CONTROL(((EPPI_CONTROL & ~DLENGTH) | DLEN_24) &
 150                                 ~RGB_FMT_EN);
 151#endif
 152
 153}
 154
 155#define               DEB2_URGENT  0x2000       /* DEB2 Urgent */
 156
 157void Init_DMA(void *dst)
 158{
 159#if defined(CONFIG_DEB_DMA_URGENT)
 160        bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE() | DEB2_URGENT);
 161#endif
 162
 163        bfin_write_DMA12_START_ADDR(dst);
 164
 165        /* X count */
 166        bfin_write_DMA12_X_COUNT((LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
 167        bfin_write_DMA12_X_MODIFY(DMA_BUS_SIZE / 8);
 168
 169        /* Y count */
 170        bfin_write_DMA12_Y_COUNT(LCD_Y_RES);
 171        bfin_write_DMA12_Y_MODIFY(DMA_BUS_SIZE / 8);
 172
 173        /* DMA Config */
 174        bfin_write_DMA12_CONFIG(
 175            WDSIZE_32 | /* 32 bit DMA */
 176            DMA2D |             /* 2D DMA */
 177            FLOW_AUTO           /* autobuffer mode */
 178        );
 179}
 180
 181void Init_Ports(void)
 182{
 183        const unsigned short pins[] = {
 184                P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, P_PPI0_D4,
 185                P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, P_PPI0_D9,
 186                P_PPI0_D10, P_PPI0_D11, P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
 187                P_PPI0_D15, P_PPI0_D16, P_PPI0_D17,
 188#if !defined(CONFIG_VIDEO_RGB666)
 189                P_PPI0_D18, P_PPI0_D19, P_PPI0_D20, P_PPI0_D21, P_PPI0_D22,
 190                P_PPI0_D23,
 191#endif
 192                P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, 0,
 193        };
 194        peripheral_request_list(pins, "lcd");
 195
 196        gpio_request(GPIO_PE3, "lcd-disp");
 197        gpio_direction_output(GPIO_PE3, 1);
 198}
 199
 200void EnableDMA(void)
 201{
 202        bfin_write_DMA12_CONFIG(bfin_read_DMA12_CONFIG() | DMAEN);
 203}
 204
 205void DisableDMA(void)
 206{
 207        bfin_write_DMA12_CONFIG(bfin_read_DMA12_CONFIG() & ~DMAEN);
 208}
 209
 210/* enable and disable PPI functions */
 211void EnablePPI(void)
 212{
 213        bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
 214}
 215
 216void DisablePPI(void)
 217{
 218        bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
 219}
 220
 221int video_init(void *dst)
 222{
 223        Init_Ports();
 224        Init_DMA(dst);
 225        EnableDMA();
 226        Init_PPI();
 227        EnablePPI();
 228
 229        return 0;
 230}
 231
 232void video_stop(void)
 233{
 234        DisablePPI();
 235        DisableDMA();
 236}
 237
 238static void dma_bitblit(void *dst, fastimage_t *logo, int x, int y)
 239{
 240        if (dcache_status())
 241                blackfin_dcache_flush_range(logo->data,
 242                                            logo->data + logo->size);
 243
 244        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
 245
 246        /* Setup destination start address */
 247        bfin_write_MDMA_D0_START_ADDR(dst + ((x & -2) * LCD_PIXEL_SIZE)
 248                                      + (y * LCD_X_RES * LCD_PIXEL_SIZE));
 249        /* Setup destination xcount */
 250        bfin_write_MDMA_D0_X_COUNT(logo->width * LCD_PIXEL_SIZE / DMA_SIZE16);
 251        /* Setup destination xmodify */
 252        bfin_write_MDMA_D0_X_MODIFY(DMA_SIZE16);
 253
 254        /* Setup destination ycount */
 255        bfin_write_MDMA_D0_Y_COUNT(logo->height);
 256        /* Setup destination ymodify */
 257        bfin_write_MDMA_D0_Y_MODIFY((LCD_X_RES - logo->width) * LCD_PIXEL_SIZE +
 258                                    DMA_SIZE16);
 259
 260        /* Setup Source start address */
 261        bfin_write_MDMA_S0_START_ADDR(logo->data);
 262        /* Setup Source xcount */
 263        bfin_write_MDMA_S0_X_COUNT(logo->width * LCD_PIXEL_SIZE / DMA_SIZE16);
 264        /* Setup Source xmodify */
 265        bfin_write_MDMA_S0_X_MODIFY(DMA_SIZE16);
 266
 267        /* Setup Source ycount */
 268        bfin_write_MDMA_S0_Y_COUNT(logo->height);
 269        /* Setup Source ymodify */
 270        bfin_write_MDMA_S0_Y_MODIFY(DMA_SIZE16);
 271
 272        /* Enable source DMA */
 273        bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16 | DMA2D);
 274        SSYNC();
 275        bfin_write_MDMA_D0_CONFIG(WNR | DMAEN | WDSIZE_16 | DMA2D);
 276
 277        while (bfin_read_MDMA_D0_IRQ_STATUS() & DMA_RUN) ;
 278
 279        bfin_write_MDMA_S0_IRQ_STATUS(bfin_read_MDMA_S0_IRQ_STATUS() | DMA_DONE
 280                                      | DMA_ERR);
 281        bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() | DMA_DONE
 282                                      | DMA_ERR);
 283
 284}
 285
 286int drv_video_init(void)
 287{
 288        int error, devices = 1;
 289        struct stdio_dev videodev;
 290
 291        u8 *dst;
 292        u32 fbmem_size =
 293            LCD_X_RES * LCD_Y_RES * LCD_PIXEL_SIZE + ACTIVE_VIDEO_MEM_OFFSET;
 294
 295        dst = malloc(fbmem_size);
 296
 297        if (dst == NULL) {
 298                printf("Failed to alloc FB memory\n");
 299                return -1;
 300        }
 301
 302#ifdef EASYLOGO_ENABLE_GZIP
 303        unsigned char *data = EASYLOGO_DECOMP_BUFFER;
 304        unsigned long src_len = EASYLOGO_ENABLE_GZIP;
 305        error = gunzip(data, bfin_logo.size, bfin_logo.data, &src_len);
 306        bfin_logo.data = data;
 307#elif defined(EASYLOGO_ENABLE_LZMA)
 308        unsigned char *data = EASYLOGO_DECOMP_BUFFER;
 309        SizeT lzma_len = bfin_logo.size;
 310        error = lzmaBuffToBuffDecompress(data, &lzma_len,
 311                bfin_logo.data, EASYLOGO_ENABLE_LZMA);
 312        bfin_logo.data = data;
 313#else
 314        error = 0;
 315#endif
 316
 317        if (error) {
 318                puts("Failed to decompress logo\n");
 319                free(dst);
 320                return -1;
 321        }
 322
 323        memset(dst + ACTIVE_VIDEO_MEM_OFFSET, bfin_logo.data[0],
 324               fbmem_size - ACTIVE_VIDEO_MEM_OFFSET);
 325
 326        dma_bitblit(dst + ACTIVE_VIDEO_MEM_OFFSET, &bfin_logo,
 327                    (LCD_X_RES - bfin_logo.width) / 2,
 328                    (LCD_Y_RES - bfin_logo.height) / 2);
 329
 330        video_init(dst);        /* Video initialization */
 331
 332        memset(&videodev, 0, sizeof(videodev));
 333
 334        strcpy(videodev.name, "video");
 335
 336        error = stdio_register(&videodev);
 337
 338        return (error == 0) ? devices : error;
 339}
 340