uboot/board/bf527-ezkit/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/mach-common/bits/dma.h>
  15#include <i2c.h>
  16#include <linux/types.h>
  17#include <stdio_dev.h>
  18
  19int gunzip(void *, int, unsigned char *, unsigned long *);
  20
  21#define DMA_SIZE16      2
  22
  23#include <asm/mach-common/bits/ppi.h>
  24#include <asm/mach-common/bits/timer.h>
  25
  26#include <asm/bfin_logo_230x230.h>
  27
  28#define LCD_X_RES               320     /* Horizontal Resolution */
  29#define LCD_Y_RES               240     /* Vertical Resolution */
  30#define LCD_BPP                 24      /* Bit Per Pixel */
  31#define LCD_PIXEL_SIZE          (LCD_BPP / 8)
  32
  33#define DMA_BUS_SIZE            16
  34#define LCD_CLK                 (12*1000*1000)  /* 12MHz */
  35
  36#define CLOCKS_PER_PIX          3
  37
  38/* HS and VS timing parameters (all in number of PPI clk ticks) */
  39#define H_ACTPIX        (LCD_X_RES * CLOCKS_PER_PIX)    /* active horizontal pixel */
  40#define H_PERIOD        (408 * CLOCKS_PER_PIX)          /* HS period */
  41#define H_PULSE         90                              /* HS pulse width */
  42#define H_START         204                             /* first valid pixel */
  43
  44#define U_LINE          1                               /* Blanking Lines */
  45
  46#define V_LINES         (LCD_Y_RES + U_LINE)            /* total vertical lines */
  47#define V_PULSE         (3 * H_PERIOD)                  /* VS pulse width (1-5 H_PERIODs) */
  48#define V_PERIOD        (H_PERIOD * V_LINES)            /* VS period */
  49
  50#define ACTIVE_VIDEO_MEM_OFFSET (U_LINE * H_ACTPIX)
  51
  52#define PPI_TX_MODE             0x2
  53#define PPI_XFER_TYPE_11        0xC
  54#define PPI_PORT_CFG_01         0x10
  55#define PPI_PACK_EN             0x80
  56#define PPI_POLS_1              0x8000
  57
  58/* enable and disable PPI functions */
  59void EnablePPI(void)
  60{
  61        *pPPI_CONTROL |= PORT_EN;
  62}
  63
  64void DisablePPI(void)
  65{
  66        *pPPI_CONTROL &= ~PORT_EN;
  67}
  68
  69void Init_Ports(void)
  70{
  71        *pPORTF_MUX &= ~PORT_x_MUX_0_MASK;
  72        *pPORTF_MUX |= PORT_x_MUX_0_FUNC_1;
  73        *pPORTF_FER |= PF0 | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF7;
  74
  75        *pPORTG_MUX &= ~PORT_x_MUX_1_MASK;
  76        *pPORTG_MUX |= PORT_x_MUX_1_FUNC_1;
  77        *pPORTG_FER |= PG5;
  78}
  79
  80void Init_PPI(void)
  81{
  82
  83        *pPPI_DELAY = H_START;
  84        *pPPI_COUNT = (H_ACTPIX-1);
  85        *pPPI_FRAME = 0;
  86
  87        /* PPI control, to be replaced with definitions */
  88        *pPPI_CONTROL = PPI_TX_MODE             |       /* output mode , PORT_DIR */
  89                        PPI_XFER_TYPE_11        |       /* sync mode XFR_TYPE */
  90                        PPI_PORT_CFG_01         |       /* two frame sync PORT_CFG */
  91                        PPI_PACK_EN             |       /* packing enabled PACK_EN */
  92                        PPI_POLS_1;                     /* faling edge syncs POLS */
  93}
  94
  95void Init_DMA(void *dst)
  96{
  97        *pDMA0_START_ADDR = dst;
  98
  99        /* X count */
 100        *pDMA0_X_COUNT = H_ACTPIX / 2;
 101        *pDMA0_X_MODIFY = DMA_BUS_SIZE / 8;
 102
 103        /* Y count */
 104        *pDMA0_Y_COUNT = V_LINES;
 105        *pDMA0_Y_MODIFY = DMA_BUS_SIZE / 8;
 106
 107        /* DMA Config */
 108        *pDMA0_CONFIG =
 109                WDSIZE_16       |       /* 16 bit DMA */
 110                DMA2D           |       /* 2D DMA */
 111                FLOW_AUTO;              /* autobuffer mode */
 112}
 113
 114
 115void EnableDMA(void)
 116{
 117        *pDMA0_CONFIG |= DMAEN;
 118}
 119
 120void DisableDMA(void)
 121{
 122        *pDMA0_CONFIG &= ~DMAEN;
 123}
 124
 125
 126/* Init TIMER0 as Frame Sync 1 generator */
 127void InitTIMER0(void)
 128{
 129        *pTIMER_DISABLE |= TIMDIS0;                     /* disable Timer */
 130        SSYNC();
 131        *pTIMER_STATUS  |= TIMIL0 | TOVF_ERR0 | TRUN0;  /* clear status */
 132        SSYNC();
 133
 134        *pTIMER0_PERIOD  = H_PERIOD;
 135        SSYNC();
 136        *pTIMER0_WIDTH   = H_PULSE;
 137        SSYNC();
 138
 139        *pTIMER0_CONFIG  = PWM_OUT |
 140                                PERIOD_CNT   |
 141                                TIN_SEL      |
 142                                CLK_SEL      |
 143                                EMU_RUN;
 144        SSYNC();
 145}
 146
 147void EnableTIMER0(void)
 148{
 149        *pTIMER_ENABLE  |= TIMEN0;
 150        SSYNC();
 151}
 152
 153void DisableTIMER0(void)
 154{
 155        *pTIMER_DISABLE  |= TIMDIS0;
 156        SSYNC();
 157}
 158
 159
 160void InitTIMER1(void)
 161{
 162        *pTIMER_DISABLE |= TIMDIS1;                     /* disable Timer */
 163        SSYNC();
 164        *pTIMER_STATUS  |= TIMIL1 | TOVF_ERR1 | TRUN1;  /* clear status */
 165        SSYNC();
 166
 167
 168        *pTIMER1_PERIOD  = V_PERIOD;
 169        SSYNC();
 170        *pTIMER1_WIDTH   = V_PULSE;
 171        SSYNC();
 172
 173        *pTIMER1_CONFIG  = PWM_OUT |
 174                                PERIOD_CNT   |
 175                                TIN_SEL      |
 176                                CLK_SEL      |
 177                                EMU_RUN;
 178        SSYNC();
 179}
 180
 181void EnableTIMER1(void)
 182{
 183        *pTIMER_ENABLE  |= TIMEN1;
 184        SSYNC();
 185}
 186
 187void DisableTIMER1(void)
 188{
 189        *pTIMER_DISABLE  |= TIMDIS1;
 190        SSYNC();
 191}
 192
 193int video_init(void *dst)
 194{
 195
 196        Init_Ports();
 197        Init_DMA(dst);
 198        EnableDMA();
 199        InitTIMER0();
 200        InitTIMER1();
 201        Init_PPI();
 202        EnablePPI();
 203
 204        /* Frame sync 2 (VS) needs to start at least one PPI clk earlier */
 205        EnableTIMER1();
 206        /* Add Some Delay ... */
 207        SSYNC();
 208        SSYNC();
 209        SSYNC();
 210        SSYNC();
 211
 212        /* now start frame sync 1 */
 213        EnableTIMER0();
 214
 215        return 0;
 216}
 217
 218static void dma_bitblit(void *dst, fastimage_t *logo, int x, int y)
 219{
 220        if (dcache_status())
 221                blackfin_dcache_flush_range(logo->data, logo->data + logo->size);
 222
 223        bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
 224
 225        /* Setup destination start address */
 226        bfin_write_MDMA_D0_START_ADDR(dst + ((x & -2) * LCD_PIXEL_SIZE)
 227                                        + (y * LCD_X_RES * LCD_PIXEL_SIZE));
 228        /* Setup destination xcount */
 229        bfin_write_MDMA_D0_X_COUNT(logo->width * LCD_PIXEL_SIZE / DMA_SIZE16);
 230        /* Setup destination xmodify */
 231        bfin_write_MDMA_D0_X_MODIFY(DMA_SIZE16);
 232
 233        /* Setup destination ycount */
 234        bfin_write_MDMA_D0_Y_COUNT(logo->height);
 235        /* Setup destination ymodify */
 236        bfin_write_MDMA_D0_Y_MODIFY((LCD_X_RES - logo->width) * LCD_PIXEL_SIZE + DMA_SIZE16);
 237
 238
 239        /* Setup Source start address */
 240        bfin_write_MDMA_S0_START_ADDR(logo->data);
 241        /* Setup Source xcount */
 242        bfin_write_MDMA_S0_X_COUNT(logo->width * LCD_PIXEL_SIZE / DMA_SIZE16);
 243        /* Setup Source xmodify */
 244        bfin_write_MDMA_S0_X_MODIFY(DMA_SIZE16);
 245
 246        /* Setup Source ycount */
 247        bfin_write_MDMA_S0_Y_COUNT(logo->height);
 248        /* Setup Source ymodify */
 249        bfin_write_MDMA_S0_Y_MODIFY(DMA_SIZE16);
 250
 251
 252        /* Enable source DMA */
 253        bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16 | DMA2D);
 254        SSYNC();
 255        bfin_write_MDMA_D0_CONFIG(WNR | DMAEN  | WDSIZE_16 | DMA2D);
 256
 257        while (bfin_read_MDMA_D0_IRQ_STATUS() & DMA_RUN);
 258
 259        bfin_write_MDMA_S0_IRQ_STATUS(bfin_read_MDMA_S0_IRQ_STATUS() | DMA_DONE | DMA_ERR);
 260        bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() | DMA_DONE | DMA_ERR);
 261
 262}
 263
 264void video_putc(const char c)
 265{
 266}
 267
 268void video_puts(const char *s)
 269{
 270}
 271
 272int drv_video_init(void)
 273{
 274        int error, devices = 1;
 275        struct stdio_dev videodev;
 276
 277        u8 *dst;
 278        u32 fbmem_size = LCD_X_RES * LCD_Y_RES * LCD_PIXEL_SIZE + ACTIVE_VIDEO_MEM_OFFSET;
 279
 280        dst = malloc(fbmem_size);
 281
 282        if (dst == NULL) {
 283                printf("Failed to alloc FB memory\n");
 284                return -1;
 285        }
 286
 287#ifdef EASYLOGO_ENABLE_GZIP
 288        unsigned char *data = EASYLOGO_DECOMP_BUFFER;
 289        unsigned long src_len = EASYLOGO_ENABLE_GZIP;
 290        if (gunzip(data, bfin_logo.size, bfin_logo.data, &src_len)) {
 291                puts("Failed to decompress logo\n");
 292                free(dst);
 293                return -1;
 294        }
 295        bfin_logo.data = data;
 296#endif
 297
 298        memset(dst + ACTIVE_VIDEO_MEM_OFFSET, bfin_logo.data[0], fbmem_size - ACTIVE_VIDEO_MEM_OFFSET);
 299
 300        dma_bitblit(dst + ACTIVE_VIDEO_MEM_OFFSET, &bfin_logo,
 301                        (LCD_X_RES - bfin_logo.width) / 2,
 302                        (LCD_Y_RES - bfin_logo.height) / 2);
 303
 304        video_init(dst);                /* Video initialization */
 305
 306        memset(&videodev, 0, sizeof(videodev));
 307
 308        strcpy(videodev.name, "video");
 309        videodev.ext = DEV_EXT_VIDEO;   /* Video extensions */
 310        videodev.flags = DEV_FLAGS_SYSTEM;      /* No Output */
 311        videodev.putc = video_putc;     /* 'putc' function */
 312        videodev.puts = video_puts;     /* 'puts' function */
 313
 314        error = stdio_register(&videodev);
 315
 316        return (error == 0) ? devices : error;
 317}
 318