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