~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/board/cm-bf548/video.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
112
static 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
 
 
121
void 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
 
 
157
void 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
 
 
181
void 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
 
 
200
void EnableDMA(void)
 
201
{
 
202
        bfin_write_DMA12_CONFIG(bfin_read_DMA12_CONFIG() | DMAEN);
 
203
}
 
204
 
 
205
void DisableDMA(void)
 
206
{
 
207
        bfin_write_DMA12_CONFIG(bfin_read_DMA12_CONFIG() & ~DMAEN);
 
208
}
 
209
 
 
210
/* enable and disable PPI functions */
 
211
void EnablePPI(void)
 
212
{
 
213
        bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
 
214
}
 
215
 
 
216
void DisablePPI(void)
 
217
{
 
218
        bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
 
219
}
 
220
 
 
221
int 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
 
 
232
void video_stop(void)
 
233
{
 
234
        DisablePPI();
 
235
        DisableDMA();
 
236
}
 
237
 
 
238
static 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
 
 
286
void video_putc(const char c)
 
287
{
 
288
}
 
289
 
 
290
void video_puts(const char *s)
 
291
{
 
292
}
 
293
 
 
294
int drv_video_init(void)
 
295
{
 
296
        int error, devices = 1;
 
297
        struct stdio_dev videodev;
 
298
 
 
299
        u8 *dst;
 
300
        u32 fbmem_size =
 
301
            LCD_X_RES * LCD_Y_RES * LCD_PIXEL_SIZE + ACTIVE_VIDEO_MEM_OFFSET;
 
302
 
 
303
        dst = malloc(fbmem_size);
 
304
 
 
305
        if (dst == NULL) {
 
306
                printf("Failed to alloc FB memory\n");
 
307
                return -1;
 
308
        }
 
309
 
 
310
#ifdef EASYLOGO_ENABLE_GZIP
 
311
        unsigned char *data = EASYLOGO_DECOMP_BUFFER;
 
312
        unsigned long src_len = EASYLOGO_ENABLE_GZIP;
 
313
        error = gunzip(data, bfin_logo.size, bfin_logo.data, &src_len);
 
314
        bfin_logo.data = data;
 
315
#elif defined(EASYLOGO_ENABLE_LZMA)
 
316
        unsigned char *data = EASYLOGO_DECOMP_BUFFER;
 
317
        SizeT lzma_len = bfin_logo.size;
 
318
        error = lzmaBuffToBuffDecompress(data, &lzma_len,
 
319
                bfin_logo.data, EASYLOGO_ENABLE_LZMA);
 
320
        bfin_logo.data = data;
 
321
#else
 
322
        error = 0;
 
323
#endif
 
324
 
 
325
        if (error) {
 
326
                puts("Failed to decompress logo\n");
 
327
                free(dst);
 
328
                return -1;
 
329
        }
 
330
 
 
331
        memset(dst + ACTIVE_VIDEO_MEM_OFFSET, bfin_logo.data[0],
 
332
               fbmem_size - ACTIVE_VIDEO_MEM_OFFSET);
 
333
 
 
334
        dma_bitblit(dst + ACTIVE_VIDEO_MEM_OFFSET, &bfin_logo,
 
335
                    (LCD_X_RES - bfin_logo.width) / 2,
 
336
                    (LCD_Y_RES - bfin_logo.height) / 2);
 
337
 
 
338
        video_init(dst);        /* Video initialization */
 
339
 
 
340
        memset(&videodev, 0, sizeof(videodev));
 
341
 
 
342
        strcpy(videodev.name, "video");
 
343
        videodev.ext = DEV_EXT_VIDEO;   /* Video extensions */
 
344
        videodev.flags = DEV_FLAGS_SYSTEM;      /* No Output */
 
345
        videodev.putc = video_putc;     /* 'putc' function */
 
346
        videodev.puts = video_puts;     /* 'puts' function */
 
347
 
 
348
        error = stdio_register(&videodev);
 
349
 
 
350
        return (error == 0) ? devices : error;
 
351
}