]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx25/karo/v1_0/src/tx25_splash.c
TX53 Release 2011-12-20
[karo-tx-redboot.git] / packages / hal / arm / mx25 / karo / v1_0 / src / tx25_splash.c
1 //==========================================================================
2 //
3 //      tx25_bootsplash.c
4 //
5 //      TX25 Bootsplash Implementation
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41
42 #include <pkgconf/hal.h>
43 #include <pkgconf/system.h>
44 #ifdef CYGPKG_REDBOOT
45 #include <redboot.h>
46 #endif
47 #include <cyg/infra/cyg_type.h>
48 #include <cyg/io/flash.h>
49 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
50 #include <flash_config.h>
51 #endif
52 #ifdef CYGOPT_REDBOOT_FIS
53 #include <fis.h>
54 #endif
55 #include CYGBLD_HAL_PLATFORM_H
56 #include <cyg/hal/plf_mmap.h>
57 #include <cyg/hal/karo_tx25.h>          // Platform specific hardware definitions
58
59 #define LCDC_BASE                       0x53fbc000
60
61 #define LCDC_SSA                        0x00
62
63 #define LCDC_SIZE                       0x04
64 #define SIZE_XMAX(x)            ((((x) >> 4) & 0x3f) << 20)
65
66 #define SIZE_YMAX(y)            ((y) & 0x3ff)
67
68 #define LCDC_VPW                        0x08
69 #define VPW_VPW(x)                      ((x) & 0x3ff)
70
71 #define LCDC_CPOS                       0x0C
72 #define CPOS_CC1                        (1 << 31)
73 #define CPOS_CC0                        (1 << 30)
74 #define CPOS_OP                         (1 << 28)
75 #define CPOS_CXP(x)                     (((x) & 3ff) << 16)
76
77 #define CPOS_CYP(y)                     ((y) & 0x3ff)
78
79 #define LCDC_LCWHB                      0x10
80 #define LCWHB_BK_EN                     (1 << 31)
81 #define LCWHB_CW(w)                     (((w) & 0x1f) << 24)
82 #define LCWHB_CH(h)                     (((h) & 0x1f) << 16)
83 #define LCWHB_BD(x)                     ((x) & 0xff)
84
85 #define LCDC_LCHCC                      0x14
86
87 #define LCHCC_CUR_COL_R(r)      (((r) & 0x3f) << 12)
88 #define LCHCC_CUR_COL_G(g)      (((g) & 0x3f) << 6)
89 #define LCHCC_CUR_COL_B(b)      ((b) & 0x3f)
90
91 #define LCDC_PCR                        0x18
92
93 #define PCR_TFT         (1 << 31)
94 #define PCR_COLOR       (1 << 30)
95 #define PCR_PBSIZ_1     (0 << 28)
96 #define PCR_PBSIZ_2     (1 << 28)
97 #define PCR_PBSIZ_4     (2 << 28)
98 #define PCR_PBSIZ_8     (3 << 28)
99 #define PCR_BPIX_1      (0 << 25)
100 #define PCR_BPIX_2      (1 << 25)
101 #define PCR_BPIX_4      (2 << 25)
102 #define PCR_BPIX_8      (3 << 25)
103 #define PCR_BPIX_12     (4 << 25)
104 #define PCR_BPIX_16     (5 << 25)
105 #define PCR_BPIX_18     (6 << 25)
106 #define PCR_PIXPOL      (1 << 24)
107 #define PCR_FLMPOL      (1 << 23)
108 #define PCR_LPPOL       (1 << 22)
109 #define PCR_CLKPOL      (1 << 21)
110 #define PCR_OEPOL       (1 << 20)
111 #define PCR_SCLKIDLE    (1 << 19)
112 #define PCR_END_SEL     (1 << 18)
113 #define PCR_END_BYTE_SWAP (1 << 17)
114 #define PCR_REV_VS      (1 << 16)
115 #define PCR_ACD_SEL     (1 << 15)
116 #define PCR_ACD(x)      (((x) & 0x7f) << 8)
117 #define PCR_SCLK_SEL    (1 << 7)
118 #define PCR_SHARP       (1 << 6)
119 #define PCR_PCD(x)      ((x) & 0x3f)
120
121 #define LCDC_HCR                        0x1C
122 #define HCR_H_WIDTH(x)          (((x) & 0x3f) << 26)
123 #define HCR_H_WAIT_1(x)         (((x) & 0xff) << 8)
124 #define HCR_H_WAIT_2(x)         ((x) & 0xff)
125
126 #define LCDC_VCR                        0x20
127 #define VCR_V_WIDTH(x)          (((x) & 0x3f) << 26)
128 #define VCR_V_WAIT_1(x)         (((x) & 0xff) << 8)
129 #define VCR_V_WAIT_2(x)         ((x) & 0xff)
130
131 #define LCDC_POS                        0x24
132 #define POS_POS(x)                      ((x) & 1f)
133
134 #define LCDC_LSCR1                      0x28
135
136 #define LCDC_PWMR                       0x2C
137
138 #define LCDC_DMACR                      0x30
139
140 #define LCDC_RMCR                       0x34
141
142 #define RMCR_SELF_REF           (1 << 0)
143
144 #define LCDC_LCDICR                     0x38
145 #define LCDICR_INT_SYN          (1 << 2)
146 #define LCDICR_INT_CON          (1)
147
148 #define LCDC_LCDISR                     0x40
149 #define LCDISR_UDR_ERR          (1 << 3)
150 #define LCDISR_ERR_RES          (1 << 2)
151 #define LCDISR_EOF                      (1 << 1)
152 #define LCDISR_BOF                      (1 << 0)
153
154 #define BMP_MAGIC                       0x4D42
155 #define BMP_HEADER_V3_SIZE      sizeof(V3BITMAPINFOHEADER)
156
157 typedef struct lcd_display_metrics {
158         cyg_uint16 *frame_buffer;
159         unsigned long pixclk;
160         unsigned long width;
161         unsigned long height;
162         unsigned long hsync;
163         unsigned long vsync;
164         unsigned long bpp;
165         /* margin settings */
166         unsigned long top;
167         unsigned long bottom;
168         unsigned long left;
169         unsigned long right;
170         /* control signal polarities */
171         bool pixclk_pol;
172         bool hsync_pol;
173         bool vsync_pol;
174 } LCDDIM;
175
176 typedef struct {
177         cyg_uint32              size;
178         cyg_int32               width;
179         cyg_int32               height;
180         cyg_uint16              planes;
181         cyg_uint16              bit_count;
182         cyg_uint32              compression;
183         cyg_uint32              size_image;
184         cyg_int32               x_pels_per_meter;
185         cyg_int32               y_pels_per_meter;
186         cyg_uint32              clr_used;
187         cyg_uint32              clr_important;
188 } V3BITMAPINFOHEADER;
189
190 typedef struct {
191         cyg_uint16      type;                   // Signatur
192         cyg_uint32      size;                   // Groesse der datei
193         cyg_uint16      reserved[2];
194         cyg_uint32      offset;                 // Offset der Pixeldaten
195 } __attribute__((packed)) BITMAPFILEHEADER;
196
197 #define lcd_reg_write(val, reg) __lcd_reg_write(val, reg, #reg)
198 static inline void __lcd_reg_write(cyg_uint32 val, unsigned short reg,
199                                                                 const char *name)
200 {
201         writel(val, LCDC_BASE + reg);
202 }
203
204 static inline cyg_uint32 lcd_reg_read(unsigned short reg)
205 {
206         cyg_uint32 val;
207
208         val = readl(LCDC_BASE + reg);
209         return val;
210 }
211
212
213 static bool get_var(const char *name, void *val, int type)
214 {
215         bool ok;
216
217         ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
218                                                                         (char *)name, val, type);
219         if (!ok) {
220                 diag_printf("fconfig variable %s not set; fconfig -i is needed!\n",
221                                         name);
222         }
223         return ok;
224 }
225
226 static inline void lcdc_enable(int on)
227 {
228         cyg_uint32 cgcr1 = readl(CCM_BASE_ADDR + CLKCTL_CGR1);
229
230         if (on) {
231                 cgcr1 |= 1 << 29;
232         } else {
233                 cgcr1 &= ~(1 << 29);
234         }
235         writel(cgcr1, CCM_BASE_ADDR + CLKCTL_CGR1);
236 }
237
238 static inline int bytes_per_pixel(unsigned long bpp)
239 {
240         switch (bpp) {
241         case 8:
242                 return 1;
243
244         case 16:
245                 return 2;
246
247         default:
248                 return 4;
249         }
250 }
251
252 static void lcd_pin_cfg(void)
253 {
254 #if 0
255         writel(1, IOMUXC_BASE_ADDR + 0x088);
256         writel(1, IOMUXC_BASE_ADDR + 0x08c);
257         writel(0, IOMUXC_BASE_ADDR + 0x0c8);
258         writel(0, IOMUXC_BASE_ADDR + 0x0cc);
259         writel(0, IOMUXC_BASE_ADDR + 0x0d0);
260         writel(0, IOMUXC_BASE_ADDR + 0x0d4);
261         writel(0, IOMUXC_BASE_ADDR + 0x0d8);
262         writel(0, IOMUXC_BASE_ADDR + 0x0dc);
263         writel(0, IOMUXC_BASE_ADDR + 0x0e0);
264         writel(0, IOMUXC_BASE_ADDR + 0x0e4);
265         writel(0, IOMUXC_BASE_ADDR + 0x0e8);
266         writel(0, IOMUXC_BASE_ADDR + 0x0ec);
267         writel(0, IOMUXC_BASE_ADDR + 0x0f0);
268         writel(0, IOMUXC_BASE_ADDR + 0x0f4);
269         writel(0, IOMUXC_BASE_ADDR + 0x0f8);
270         writel(0, IOMUXC_BASE_ADDR + 0x0fc);
271         writel(0, IOMUXC_BASE_ADDR + 0x100);
272         writel(0, IOMUXC_BASE_ADDR + 0x104);
273         writel(0, IOMUXC_BASE_ADDR + 0x108);
274         writel(0, IOMUXC_BASE_ADDR + 0x10c);
275         writel(0, IOMUXC_BASE_ADDR + 0x110);
276         writel(0, IOMUXC_BASE_ADDR + 0x114);
277 #endif
278 }
279
280 /* evaluate the config parameters */
281 static bool bootsplash_setup(LCDDIM *ldim, unsigned long img_len)
282 {
283         bool ok;
284
285         ok = get_var("lcd_buffer_addr", &ldim->frame_buffer, CONFIG_INT);
286         ok &= get_var("lcd_clk_period", &ldim->pixclk, CONFIG_INT);
287         ok &= get_var("lcd_clk_polarity", &ldim->pixclk_pol, CONFIG_BOOL);
288
289         ok &= get_var("lcd_panel_width", &ldim->width, CONFIG_INT);
290         ok &= get_var("lcd_panel_height", &ldim->height, CONFIG_INT);
291         ok &= get_var("lcd_bpp", &ldim->bpp, CONFIG_INT);
292
293         ok &= get_var("lcd_hsync_width", &ldim->hsync, CONFIG_INT);
294         ok &= get_var("lcd_hsync_polarity", &ldim->hsync_pol, CONFIG_BOOL);
295         ok &= get_var("lcd_margin_left", &ldim->left, CONFIG_INT);
296         ok &= get_var("lcd_margin_right", &ldim->right, CONFIG_INT);
297
298         ok &= get_var("lcd_vsync_width", &ldim->vsync, CONFIG_INT);
299         ok &= get_var("lcd_vsync_polarity", &ldim->vsync_pol, CONFIG_BOOL);
300         ok &= get_var("lcd_margin_top", &ldim->top, CONFIG_INT);
301         ok &= get_var("lcd_margin_bottom", &ldim->bottom, CONFIG_INT);
302
303         if (!ok)
304                 return false;
305
306         if (ldim->width < 16 || ldim->width > 1024) {
307                 diag_printf("Invalid LCD panel width: %lu\n", ldim->width);
308                 ok = false;
309         }
310
311         if (ldim->height < 1 || ldim->height > 511) {
312                 diag_printf("Invalid LCD panel height: %lu\n", ldim->height);
313                 ok = false;
314         }
315
316         if (ldim->hsync < 1 || ldim->hsync > 64) {
317                 diag_printf("Invalid HSYNC width: %lu\n", ldim->hsync);
318                 ok = false;
319         }
320
321         if (ldim->vsync > 63) {
322                 diag_printf("Invalid VSYNC width: %lu\n", ldim->vsync);
323                 ok = false;
324         }
325
326         if (ldim->left < 3 || ldim->left > 258) {
327                 diag_printf("Invalid left margin: %lu\n", ldim->left);
328                 ok = false;
329         }
330
331         if (ldim->right < 1 || ldim->right > 256) {
332                 diag_printf("Invalid right margin: %lu\n", ldim->right);
333                 ok = false;
334         }
335
336         if (ldim->top > 255) {
337                 diag_printf("Invalid top margin: %lu\n", ldim->top);
338                 ok = false;
339         }
340
341         if (ldim->bottom > 255) {
342                 diag_printf("Invalid bottom margin: %lu\n", ldim->bottom);
343                 ok = false;
344         }
345
346         switch (ldim->bpp) {
347         default:
348                 diag_printf("Invalid color depth: %lu\n", ldim->bpp);
349                 return false;
350
351         case 16:
352         case 8:
353                 break;
354         }
355
356         if (ldim->width * ldim->height * bytes_per_pixel(ldim->bpp) > img_len) {
357                 diag_printf("LCD panel size %lux%lux%u = %lu does not match image size %lu\n",
358                                         ldim->width, ldim->height, bytes_per_pixel(ldim->bpp),
359                                         ldim->width * ldim->height * bytes_per_pixel(ldim->bpp),
360                                         img_len);
361                 ok = false;
362         }
363
364         return ok;
365 }
366
367 /* initialize the LCD controller */
368 static bool bootsplash_display(LCDDIM *ldim)
369 {
370         unsigned long lcdc_clk = get_peri_clock(LCDC_CLK);
371         unsigned long pcr;
372         CYG_ADDRESS disp_addr_phys;
373
374         HAL_VIRT_TO_PHYS_ADDRESS(ldim->frame_buffer, disp_addr_phys);
375
376         diag_printf("LCD %lux%lu-%lu %lu.%03luMHz\n",
377                                 ldim->width, ldim->height, ldim->bpp,
378                                 1000000 / ldim->pixclk,
379                                 1000000000 / ldim->pixclk % 1000);
380
381         ldim->pixclk = 1000000000 / ldim->pixclk * 1000;
382         if (ldim->pixclk > lcdc_clk / 2) {
383                 diag_printf("LCD pixel clock %lu too high; max.: %lu\n",
384                                         ldim->pixclk, lcdc_clk / 2);
385                 return false;
386         }
387
388         pcr = lcdc_clk / ldim->pixclk;
389         if (pcr-- > 63) {
390                 diag_printf("LCD pixel clock %lu too low; min.: %lu\n",
391                                         ldim->pixclk, lcdc_clk / 128);
392                 return false;
393         }
394
395         pcr |= PCR_TFT | PCR_COLOR | PCR_SCLK_SEL |
396                 (ldim->vsync_pol * PCR_FLMPOL) |
397                 (ldim->hsync_pol * PCR_LPPOL) |
398                 (ldim->pixclk_pol * PCR_PIXPOL);
399
400         switch (ldim->bpp) {
401         case 18:
402                 pcr |= PCR_PBSIZ_8 | PCR_BPIX_18;
403                 break;
404
405         case 16:
406                 pcr |= PCR_PBSIZ_8 | PCR_BPIX_16;
407                 break;
408
409         case 8:
410                 pcr |= PCR_BPIX_8 | PCR_END_BYTE_SWAP;
411                 break;
412         }
413
414         lcdc_enable(0);
415         lcd_pin_cfg();
416
417         lcd_reg_write(VPW_VPW(ldim->width * ldim->bpp / 8 / 4), LCDC_VPW);
418         lcd_reg_write(HCR_H_WIDTH(ldim->hsync - 1) | HCR_H_WAIT_2(ldim->left - 3) |
419                                 HCR_H_WAIT_1(ldim->right - 1), LCDC_HCR);
420         lcd_reg_write(VCR_V_WIDTH(ldim->vsync) | VCR_V_WAIT_2(ldim->top) |
421                                 VCR_V_WAIT_1(ldim->bottom), LCDC_VCR);
422         lcd_reg_write(SIZE_XMAX(ldim->width) | SIZE_YMAX(ldim->height), LCDC_SIZE);
423         lcd_reg_write(pcr, LCDC_PCR);
424         lcd_reg_write(0, LCDC_PWMR);
425         lcd_reg_write(0, LCDC_LSCR1);
426         lcd_reg_write(0x80040060, LCDC_DMACR);
427
428         lcd_reg_write(disp_addr_phys, LCDC_SSA);
429         lcd_reg_write(0, LCDC_POS);
430         lcd_reg_write(0, LCDC_CPOS);
431         lcd_reg_write(0, LCDC_RMCR);
432
433         lcdc_enable(1);
434
435         while (!(lcd_reg_read(LCDC_LCDISR) & LCDISR_EOF));
436
437         gpio_set_bit(LCD_POWER_GPIO / 32 + 1, LCD_POWER_GPIO % 32);
438         gpio_set_bit(LCD_RESET_GPIO / 32 + 1, LCD_RESET_GPIO % 32);
439
440         HAL_DELAY_US(300000);
441         gpio_clr_bit(LCD_BACKLIGHT_GPIO / 32 + 1, LCD_BACKLIGHT_GPIO % 32);
442
443         return true;
444 }
445
446 static void set_pixel(LCDDIM *ldim, unsigned short x, unsigned short y,
447                         unsigned char red, unsigned char green, unsigned char blue)
448 {
449         unsigned int offset = y * ldim->width + x;
450         unsigned short *fb = (unsigned short *)(ldim->frame_buffer + offset);
451
452         *fb = ((red & 0x1f) << 11) |
453                 ((green & 0x3f) << 5) |
454                 ((blue & 0x1f) << 0);
455 }
456
457 static unsigned long paint_test_picture(LCDDIM *ldim)
458 {
459         const int stripes = 8;
460         const unsigned int fill_size = ldim->width * ldim->height / stripes;
461         cyg_uint16 *frame_pointer = ldim->frame_buffer;
462         int x;
463
464         memset(frame_pointer, 0, fill_size * bytes_per_pixel(ldim->bpp));
465         frame_pointer += fill_size;
466
467         for (x = 0; x < fill_size; x++) {
468                 *frame_pointer++ = 0xf800;                      // red screen
469         }
470
471         for (x = 0; x < fill_size; x++) {
472                 *frame_pointer++ = 0x07e0;                      // green screen
473         }
474
475         for (x = 0; x < fill_size; x++) {
476                 *frame_pointer++ = 0x001f;                      // blue screen
477         }
478
479         for (x = 0; x < fill_size; x++) {
480                 *frame_pointer++ = 0x07ff;                      // yellow screen
481         }
482
483         for (x = 0; x < fill_size; x++) {
484                 *frame_pointer++ = 0xf81f;                      // magenta screen
485         }
486
487         for (x = 0; x < fill_size; x++) {
488                 *frame_pointer++ = 0xffe0;                      // cyan screen
489         }
490
491         memset(frame_pointer, 0xff, fill_size * bytes_per_pixel(ldim->bpp));
492         frame_pointer += fill_size;
493
494         // draw a white frame
495         for (x = 0; x < ldim->width; x++)
496                 set_pixel(ldim, x, 0,
497                                 0xff, 0xff, 0xff);
498
499         for (x = 0; x < ldim->height; x++)
500                 set_pixel(ldim, ldim->width - 1, x,
501                                 0xff, 0xff, 0xff);
502
503         for (x = 0; x < ldim->width; x++)
504                 set_pixel(ldim, x, ldim->height - 1,
505                                 0xff, 0xff, 0xff);
506
507         for (x = 0; x < ldim->height; x++)
508                 set_pixel(ldim, 0, x,
509                                 0xff, 0xff, 0xff);
510
511         // diagonal lines
512         for (x = 0; x < ldim->width; x++)
513                 set_pixel(ldim, x, x * ldim->height / ldim->width,
514                                 (x & 1) * 0xff, (x & 1) * 0xff, (x & 1) * 0xff);
515
516         for (x = 0; x < ldim->width; x++)
517                 set_pixel(ldim, ldim->width - x - 1, x * ldim->height / ldim->width,
518                                 (x & 1) * 0xff, (x & 1) * 0xff, (x & 1) * 0xff);
519         return (frame_pointer - ldim->frame_buffer) * bytes_per_pixel(ldim->bpp);
520 }
521
522 static void load_bitmap(LCDDIM *ldim, void *ram_addr,
523                                                 unsigned long img_len)
524 {
525         cyg_uint8               *sp;
526         cyg_uint8               red, green, blue;
527         cyg_uint16              *ppixel;
528
529         BITMAPFILEHEADER        bmfh;
530         V3BITMAPINFOHEADER      bmih;
531         int line, col;
532
533         /* copy bitmap file header */
534         memcpy(&bmfh, ram_addr, sizeof(bmfh));
535
536         /* copy bitmap info header */
537         memcpy(&bmih, (cyg_uint8 *)ram_addr + sizeof(bmfh), sizeof(bmih));
538
539         if (bmfh.type != 0x4d42) {
540                 if (ldim->width * ldim->height * bytes_per_pixel(ldim->bpp) > img_len) {
541                         diag_printf("LCD panel size %lux%lux%u = %lu does not match image size %lu\n",
542                                                 ldim->width, ldim->height, bytes_per_pixel(ldim->bpp),
543                                                 ldim->width * ldim->height * bytes_per_pixel(ldim->bpp),
544                                                 img_len);
545                         goto end_failure;
546                 }
547                 memcpy(ldim->frame_buffer, ram_addr, img_len);
548                 return;
549         }
550
551         if (bmfh.offset >= bmfh.size) {
552                 diag_printf("Corrupted BMP header\n");
553                 goto end_failure;
554         }
555
556         if (bmih.size != BMP_HEADER_V3_SIZE ) {
557                 diag_printf("** ERROR: unsupported bitmap header version, structure size must be %u\n",
558                                         BMP_HEADER_V3_SIZE);
559                 goto end_failure;
560         }
561
562         if (bmih.bit_count != 24) {
563                 diag_printf("** ERROR: only 24 bit BMP files are supported\n");
564                 goto end_failure;
565         }
566
567         if ((bmih.width != ldim->width) || (bmih.height != ldim->height)) {
568                 diag_printf("** ERROR: BMP image size %ux%u does not match configured size: %lux%lu\n",
569                                         bmih.width, bmih.height, ldim->width, ldim->height);
570                 goto end_failure;
571         }
572
573         /* pointer to picture data */
574         sp = (cyg_uint8 *)ram_addr + bmfh.offset;
575
576         if (bmih.bit_count == 16) {
577                 for (line = ldim->height; line > 0; line--) {
578                         memcpy(ldim->frame_buffer + (line - 1) * ldim->width,
579                                 sp, ldim->width * 2);
580                         sp += ldim->width * 2;
581                 }
582                 return;
583         }
584
585         for (line = ldim->height; line > 0; line--) {
586                 ppixel = ldim->frame_buffer + (line - 1) * ldim->width;
587                 for (col = 0; col < ldim->width; col ++) {
588                         blue    = *sp++ >> 3;   // 5 bits
589                         green   = *sp++ >> 2;   // 6 bits
590                         red             = *sp++ >> 3;   // 5 bits
591                         *ppixel++       = ((red << 11) | (green << 5) | (blue << 0));
592                 }
593         }
594         return;
595
596 end_failure:
597         paint_test_picture(ldim);
598 }
599
600 /*
601  * load the logo from nand flash to memory.
602  */
603 static bool do_logo_load(LCDDIM *ldim)
604 {
605         void *fis_addr;
606         int ret = 0xFF;
607         void *err_addr;
608         unsigned int logo_size;
609         struct fis_image_desc *img;
610         void *ram_addr;
611
612         /* Read the logo from storage media */
613         if ((img = fis_lookup("logo", NULL)) == NULL) {
614                 diag_printf("No logo partition found in the fis table, logo not loaded\n");
615                 return false;
616         }
617
618         fis_addr = (void *)img->flash_base;
619         ram_addr = (void *)img->mem_base;
620
621         logo_size = img->data_length;
622         ret = FLASH_READ(fis_addr, ram_addr, logo_size, &err_addr);
623         if (ret != 0) {
624                 diag_printf("Loading logo from FLASH to MEMORY failed. error code: %d", ret);
625                 return false;
626         }
627         if (!bootsplash_setup(ldim, logo_size)) {
628                 diag_printf("Cannot init splash screen; Invalid display parameters\n");
629                 return false;
630         }
631         load_bitmap(ldim, ram_addr, logo_size);
632         bootsplash_display(ldim);
633         return true;
634 }
635
636 static void redboot_bootsplash_display(void)
637 {
638         bool bootsplash_feature_enable;
639         int ok;
640         LCDDIM ldim;
641
642         gpio_set_bit(LCD_RESET_GPIO / 32, LCD_RESET_GPIO % 32);
643         gpio_set_bit(LCD_POWER_GPIO / 32, LCD_POWER_GPIO % 32);
644         gpio_set_bit(LCD_BACKLIGHT_GPIO / 32, LCD_BACKLIGHT_GPIO % 32);
645
646         ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
647                                                                         "bootsplash_enable",
648                                                                         &bootsplash_feature_enable, CONFIG_BOOL);
649         if (!ok) {
650                 diag_printf("fconfig variable bootsplash_enable not found\n");
651         }
652         if (ok && bootsplash_feature_enable) {
653                 do_logo_load(&ldim);
654         }
655 }
656
657 #ifdef CYGPKG_REDBOOT
658 RedBoot_init(redboot_bootsplash_display, RedBoot_INIT_SECOND);
659
660 RedBoot_config_option("Enable splash display at boot",
661                                         bootsplash_enable,
662                                         ALWAYS_ENABLED, true,
663                                         CONFIG_BOOL,
664                                         false
665         );
666
667 RedBoot_config_option("LCD frame buffer address",
668                                         lcd_buffer_addr,
669                                         "bootsplash_enable", true,
670                                         CONFIG_INT,
671                                         RAM_BANK0_BASE + RAM_BANK0_SIZE
672         );
673
674 RedBoot_config_option("Pixel clock period (in ps)",
675                                         lcd_clk_period,
676                                         "bootsplash_enable", true,
677                                         CONFIG_INT,
678                                         33333
679         );
680
681 RedBoot_config_option("Pixel clock polarity active low",
682                                         lcd_clk_polarity,
683                                         "bootsplash_enable", true,
684                                         CONFIG_BOOL,
685                                         false
686         );
687
688 RedBoot_config_option("LCD panel width (in pixels)",
689                                         lcd_panel_width,
690                                         "bootsplash_enable", true,
691                                         CONFIG_INT,
692                                         640
693         );
694
695 RedBoot_config_option("LCD panel height (in pixels)",
696                                         lcd_panel_height,
697                                         "bootsplash_enable", true,
698                                         CONFIG_INT,
699                                         480
700         );
701
702 RedBoot_config_option("LCD color depth (BPP)",
703                                         lcd_bpp,
704                                         "bootsplash_enable", true,
705                                         CONFIG_INT,
706                                         16
707         );
708
709 RedBoot_config_option("HSYNC pulse width (in pixels)",
710                                         lcd_hsync_width,
711                                         "bootsplash_enable", true,
712                                         CONFIG_INT,
713                                         64
714         );
715
716 RedBoot_config_option("HSYNC polarity active low",
717                                         lcd_hsync_polarity,
718                                         "bootsplash_enable", true,
719                                         CONFIG_BOOL,
720                                         true
721         );
722
723 RedBoot_config_option("Left margin (in pixels)",
724                                         lcd_margin_left,
725                                         "bootsplash_enable", true,
726                                         CONFIG_INT,
727                                         96
728         );
729
730 RedBoot_config_option("Right margin (in pixels)",
731                                         lcd_margin_right,
732                                         "bootsplash_enable", true,
733                                         CONFIG_INT,
734                                         80
735         );
736
737 RedBoot_config_option("VSYNC pulse width (in scan lines)",
738                                         lcd_vsync_width,
739                                         "bootsplash_enable", true,
740                                         CONFIG_INT,
741                                         3
742         );
743
744 RedBoot_config_option("VSYNC polarity active low",
745                                         lcd_vsync_polarity,
746                                         "bootsplash_enable", true,
747                                         CONFIG_BOOL,
748                                         true
749         );
750
751 RedBoot_config_option("Top margin (in scan lines)",
752                                         lcd_margin_top,
753                                         "bootsplash_enable", true,
754                                         CONFIG_INT,
755                                         46
756         );
757
758 RedBoot_config_option("Bottom margin (in scan lines)",
759                                         lcd_margin_bottom,
760                                         "bootsplash_enable", true,
761                                         CONFIG_INT,
762                                         39
763         );
764 #endif