]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx25/karo/v1_0/src/tx25_splash.c
RedBoot Release TX53-v3 2012-02-08
[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 CYGBLD_HAL_PLF_DEFS_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 pix_pol;
172         bool clk_pol;   
173         bool hsync_pol;
174         bool vsync_pol;
175 } LCDDIM;
176
177 typedef struct {
178         cyg_uint32              size;
179         cyg_int32               width;
180         cyg_int32               height;
181         cyg_uint16              planes;
182         cyg_uint16              bit_count;
183         cyg_uint32              compression;
184         cyg_uint32              size_image;
185         cyg_int32               x_pels_per_meter;
186         cyg_int32               y_pels_per_meter;
187         cyg_uint32              clr_used;
188         cyg_uint32              clr_important;
189 } V3BITMAPINFOHEADER;
190
191 typedef struct {
192         cyg_uint16      type;                   // Signatur
193         cyg_uint32      size;                   // Groesse der datei
194         cyg_uint16      reserved[2];
195         cyg_uint32      offset;                 // Offset der Pixeldaten
196 } __attribute__((packed)) BITMAPFILEHEADER;
197
198 #define lcd_reg_write(val, reg) __lcd_reg_write(val, reg, #reg)
199 static inline void __lcd_reg_write(cyg_uint32 val, unsigned short reg,
200                                                                 const char *name)
201 {
202         writel(val, LCDC_BASE + reg);
203 }
204
205 static inline cyg_uint32 lcd_reg_read(unsigned short reg)
206 {
207         cyg_uint32 val;
208
209         val = readl(LCDC_BASE + reg);
210         return val;
211 }
212
213
214 static bool get_var(const char *name, void *val, int type)
215 {
216         bool ok;
217
218         ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
219                                                                         (char *)name, val, type);
220         if (!ok) {
221                 diag_printf("fconfig variable %s not set; fconfig -i is needed!\n",
222                                         name);
223         }
224         return ok;
225 }
226
227 static inline void lcdc_enable(int on)
228 {
229         cyg_uint32 cgcr1 = readl(CCM_BASE_ADDR + CLKCTL_CGR1);
230
231         if (on) {
232                 cgcr1 |= 1 << 29;
233         } else {
234                 cgcr1 &= ~(1 << 29);
235         }
236         writel(cgcr1, CCM_BASE_ADDR + CLKCTL_CGR1);
237 }
238
239 static inline int bytes_per_pixel(unsigned long bpp)
240 {
241         switch (bpp) {
242         case 8:
243                 return 1;
244
245         case 16:
246                 return 2;
247
248         default:
249                 return 4;
250         }
251 }
252
253 static void lcd_pin_cfg(void)
254 {
255 #if 0
256         writel(1, IOMUXC_BASE_ADDR + 0x088);
257         writel(1, IOMUXC_BASE_ADDR + 0x08c);
258         writel(0, IOMUXC_BASE_ADDR + 0x0c8);
259         writel(0, IOMUXC_BASE_ADDR + 0x0cc);
260         writel(0, IOMUXC_BASE_ADDR + 0x0d0);
261         writel(0, IOMUXC_BASE_ADDR + 0x0d4);
262         writel(0, IOMUXC_BASE_ADDR + 0x0d8);
263         writel(0, IOMUXC_BASE_ADDR + 0x0dc);
264         writel(0, IOMUXC_BASE_ADDR + 0x0e0);
265         writel(0, IOMUXC_BASE_ADDR + 0x0e4);
266         writel(0, IOMUXC_BASE_ADDR + 0x0e8);
267         writel(0, IOMUXC_BASE_ADDR + 0x0ec);
268         writel(0, IOMUXC_BASE_ADDR + 0x0f0);
269         writel(0, IOMUXC_BASE_ADDR + 0x0f4);
270         writel(0, IOMUXC_BASE_ADDR + 0x0f8);
271         writel(0, IOMUXC_BASE_ADDR + 0x0fc);
272         writel(0, IOMUXC_BASE_ADDR + 0x100);
273         writel(0, IOMUXC_BASE_ADDR + 0x104);
274         writel(0, IOMUXC_BASE_ADDR + 0x108);
275         writel(0, IOMUXC_BASE_ADDR + 0x10c);
276         writel(0, IOMUXC_BASE_ADDR + 0x110);
277         writel(0, IOMUXC_BASE_ADDR + 0x114);
278 #endif
279 }
280
281 /* evaluate the config parameters */
282 static bool bootsplash_setup(LCDDIM *ldim, unsigned long img_len)
283 {
284         bool ok;
285
286         ok = get_var("lcd_buffer_addr", &ldim->frame_buffer, CONFIG_INT);
287         ok &= get_var("lcd_clk_period", &ldim->pixclk, CONFIG_INT);
288         ok &= get_var("lcd_clk_polarity", &ldim->clk_pol, CONFIG_BOOL);
289         ok &= get_var("lcd_pix_polarity", &ldim->pix_pol, CONFIG_BOOL);
290
291         ok &= get_var("lcd_panel_width", &ldim->width, CONFIG_INT);
292         ok &= get_var("lcd_panel_height", &ldim->height, CONFIG_INT);
293         ok &= get_var("lcd_bpp", &ldim->bpp, CONFIG_INT);
294
295         ok &= get_var("lcd_hsync_width", &ldim->hsync, CONFIG_INT);
296         ok &= get_var("lcd_hsync_polarity", &ldim->hsync_pol, CONFIG_BOOL);
297         ok &= get_var("lcd_margin_left", &ldim->left, CONFIG_INT);
298         ok &= get_var("lcd_margin_right", &ldim->right, CONFIG_INT);
299
300         ok &= get_var("lcd_vsync_width", &ldim->vsync, CONFIG_INT);
301         ok &= get_var("lcd_vsync_polarity", &ldim->vsync_pol, CONFIG_BOOL);
302         ok &= get_var("lcd_margin_top", &ldim->top, CONFIG_INT);
303         ok &= get_var("lcd_margin_bottom", &ldim->bottom, CONFIG_INT);
304
305         if (!ok)
306                 return false;
307
308         if (ldim->width < 16 || ldim->width > 1024) {
309                 diag_printf("Invalid LCD panel width: %lu\n", ldim->width);
310                 ok = false;
311         }
312
313         if (ldim->height < 1 || ldim->height > 511) {
314                 diag_printf("Invalid LCD panel height: %lu\n", ldim->height);
315                 ok = false;
316         }
317
318         if (ldim->hsync < 1 || ldim->hsync > 64) {
319                 diag_printf("Invalid HSYNC width: %lu\n", ldim->hsync);
320                 ok = false;
321         }
322
323         if (ldim->vsync > 63) {
324                 diag_printf("Invalid VSYNC width: %lu\n", ldim->vsync);
325                 ok = false;
326         }
327
328         if (ldim->left < 3 || ldim->left > 258) {
329                 diag_printf("Invalid left margin: %lu\n", ldim->left);
330                 ok = false;
331         }
332
333         if (ldim->right < 1 || ldim->right > 256) {
334                 diag_printf("Invalid right margin: %lu\n", ldim->right);
335                 ok = false;
336         }
337
338         if (ldim->top > 255) {
339                 diag_printf("Invalid top margin: %lu\n", ldim->top);
340                 ok = false;
341         }
342
343         if (ldim->bottom > 255) {
344                 diag_printf("Invalid bottom margin: %lu\n", ldim->bottom);
345                 ok = false;
346         }
347
348         switch (ldim->bpp) {
349         default:
350                 diag_printf("Invalid color depth: %lu\n", ldim->bpp);
351                 return false;
352
353         case 16:
354         case 8:
355                 break;
356         }
357
358         if (ldim->width * ldim->height * bytes_per_pixel(ldim->bpp) > img_len) {
359                 diag_printf("LCD panel size %lux%lux%u = %lu does not match image size %lu\n",
360                                         ldim->width, ldim->height, bytes_per_pixel(ldim->bpp),
361                                         ldim->width * ldim->height * bytes_per_pixel(ldim->bpp),
362                                         img_len);
363                 ok = false;
364         }
365
366         return ok;
367 }
368
369 /* initialize the LCD controller */
370 static bool bootsplash_display(LCDDIM *ldim)
371 {
372         unsigned long lcdc_clk = get_peri_clock(LCDC_CLK);
373         unsigned long pcr;
374         CYG_ADDRESS disp_addr_phys;
375
376         HAL_VIRT_TO_PHYS_ADDRESS(ldim->frame_buffer, disp_addr_phys);
377
378         diag_printf("LCD %lux%lu-%lu %lu.%03luMHz\n",
379                                 ldim->width, ldim->height, ldim->bpp,
380                                 1000000 / ldim->pixclk,
381                                 1000000000 / ldim->pixclk % 1000);
382
383         ldim->pixclk = 1000000000 / ldim->pixclk * 1000;
384         if (ldim->pixclk > lcdc_clk / 2) {
385                 diag_printf("LCD pixel clock %lu too high; max.: %lu\n",
386                                         ldim->pixclk, lcdc_clk / 2);
387                 return false;
388         }
389
390         pcr = lcdc_clk / ldim->pixclk;
391         if (pcr-- > 63) {
392                 diag_printf("LCD pixel clock %lu too low; min.: %lu\n",
393                                         ldim->pixclk, lcdc_clk / 128);
394                 return false;
395         }
396
397         pcr |= PCR_TFT | PCR_COLOR | PCR_SCLK_SEL |
398                 (ldim->vsync_pol * PCR_FLMPOL) |
399                 (ldim->hsync_pol * PCR_LPPOL) |
400                 (ldim->pix_pol * PCR_PIXPOL) |
401                 (ldim->clk_pol * PCR_CLKPOL);
402
403         switch (ldim->bpp) {
404         case 18:
405                 pcr |= PCR_PBSIZ_8 | PCR_BPIX_18;
406                 break;
407
408         case 16:
409                 pcr |= PCR_PBSIZ_8 | PCR_BPIX_16;
410                 break;
411
412         case 8:
413                 pcr |= PCR_BPIX_8 | PCR_END_BYTE_SWAP;
414                 break;
415         }
416
417         lcdc_enable(0);
418         lcd_pin_cfg();
419
420         lcd_reg_write(VPW_VPW(ldim->width * ldim->bpp / 8 / 4), LCDC_VPW);
421         lcd_reg_write(HCR_H_WIDTH(ldim->hsync - 1) | HCR_H_WAIT_2(ldim->left - 3) |
422                                 HCR_H_WAIT_1(ldim->right - 1), LCDC_HCR);
423         lcd_reg_write(VCR_V_WIDTH(ldim->vsync) | VCR_V_WAIT_2(ldim->top) |
424                                 VCR_V_WAIT_1(ldim->bottom), LCDC_VCR);
425         lcd_reg_write(SIZE_XMAX(ldim->width) | SIZE_YMAX(ldim->height), LCDC_SIZE);
426         lcd_reg_write(pcr, LCDC_PCR);
427         lcd_reg_write(0, LCDC_PWMR);
428         lcd_reg_write(0, LCDC_LSCR1);
429         lcd_reg_write(0x80040060, LCDC_DMACR);
430
431         lcd_reg_write(disp_addr_phys, LCDC_SSA);
432         lcd_reg_write(0, LCDC_POS);
433         lcd_reg_write(0, LCDC_CPOS);
434         lcd_reg_write(0, LCDC_RMCR);
435
436         lcdc_enable(1);
437
438         while (!(lcd_reg_read(LCDC_LCDISR) & LCDISR_EOF));
439
440         gpio_set_bit(LCD_POWER_GPIO / 32 + 1, LCD_POWER_GPIO % 32);
441         gpio_set_bit(LCD_RESET_GPIO / 32 + 1, LCD_RESET_GPIO % 32);
442
443         HAL_DELAY_US(300000);
444         gpio_clr_bit(LCD_BACKLIGHT_GPIO / 32 + 1, LCD_BACKLIGHT_GPIO % 32);
445
446         return true;
447 }
448
449 static void set_pixel(LCDDIM *ldim, unsigned short x, unsigned short y,
450                         unsigned char red, unsigned char green, unsigned char blue)
451 {
452         unsigned int offset = y * ldim->width + x;
453         unsigned short *fb = (unsigned short *)(ldim->frame_buffer + offset);
454
455         *fb = ((red & 0x1f) << 11) |
456                 ((green & 0x3f) << 5) |
457                 ((blue & 0x1f) << 0);
458 }
459
460 static unsigned long paint_test_picture(LCDDIM *ldim)
461 {
462         const int stripes = 8;
463         const unsigned int fill_size = ldim->width * ldim->height / stripes;
464         cyg_uint16 *frame_pointer = ldim->frame_buffer;
465         int x;
466
467         memset(frame_pointer, 0, fill_size * bytes_per_pixel(ldim->bpp));
468         frame_pointer += fill_size;
469
470         for (x = 0; x < fill_size; x++) {
471                 *frame_pointer++ = 0xf800;                      // red screen
472         }
473
474         for (x = 0; x < fill_size; x++) {
475                 *frame_pointer++ = 0x07e0;                      // green screen
476         }
477
478         for (x = 0; x < fill_size; x++) {
479                 *frame_pointer++ = 0x001f;                      // blue screen
480         }
481
482         for (x = 0; x < fill_size; x++) {
483                 *frame_pointer++ = 0x07ff;                      // yellow screen
484         }
485
486         for (x = 0; x < fill_size; x++) {
487                 *frame_pointer++ = 0xf81f;                      // magenta screen
488         }
489
490         for (x = 0; x < fill_size; x++) {
491                 *frame_pointer++ = 0xffe0;                      // cyan screen
492         }
493
494         memset(frame_pointer, 0xff, fill_size * bytes_per_pixel(ldim->bpp));
495         frame_pointer += fill_size;
496
497         // draw a white frame
498         for (x = 0; x < ldim->width; x++)
499                 set_pixel(ldim, x, 0,
500                                 0xff, 0xff, 0xff);
501
502         for (x = 0; x < ldim->height; x++)
503                 set_pixel(ldim, ldim->width - 1, x,
504                                 0xff, 0xff, 0xff);
505
506         for (x = 0; x < ldim->width; x++)
507                 set_pixel(ldim, x, ldim->height - 1,
508                                 0xff, 0xff, 0xff);
509
510         for (x = 0; x < ldim->height; x++)
511                 set_pixel(ldim, 0, x,
512                                 0xff, 0xff, 0xff);
513
514         // diagonal lines
515         for (x = 0; x < ldim->width; x++)
516                 set_pixel(ldim, x, x * ldim->height / ldim->width,
517                                 (x & 1) * 0xff, (x & 1) * 0xff, (x & 1) * 0xff);
518
519         for (x = 0; x < ldim->width; x++)
520                 set_pixel(ldim, ldim->width - x - 1, x * ldim->height / ldim->width,
521                                 (x & 1) * 0xff, (x & 1) * 0xff, (x & 1) * 0xff);
522         return (frame_pointer - ldim->frame_buffer) * bytes_per_pixel(ldim->bpp);
523 }
524
525 static void load_bitmap(LCDDIM *ldim, void *ram_addr,
526                                                 unsigned long img_len)
527 {
528         cyg_uint8               *sp;
529         cyg_uint8               red, green, blue;
530         cyg_uint16              *ppixel;
531
532         BITMAPFILEHEADER        bmfh;
533         V3BITMAPINFOHEADER      bmih;
534         int line, col;
535
536         /* copy bitmap file header */
537         memcpy(&bmfh, ram_addr, sizeof(bmfh));
538
539         /* copy bitmap info header */
540         memcpy(&bmih, (cyg_uint8 *)ram_addr + sizeof(bmfh), sizeof(bmih));
541
542         if (bmfh.type != 0x4d42) {
543                 if (ldim->width * ldim->height * bytes_per_pixel(ldim->bpp) > img_len) {
544                         diag_printf("LCD panel size %lux%lux%u = %lu does not match image size %lu\n",
545                                                 ldim->width, ldim->height, bytes_per_pixel(ldim->bpp),
546                                                 ldim->width * ldim->height * bytes_per_pixel(ldim->bpp),
547                                                 img_len);
548                         goto end_failure;
549                 }
550                 memcpy(ldim->frame_buffer, ram_addr, img_len);
551                 return;
552         }
553
554         if (bmfh.offset >= bmfh.size) {
555                 diag_printf("Corrupted BMP header\n");
556                 goto end_failure;
557         }
558
559         if (bmih.size != BMP_HEADER_V3_SIZE ) {
560                 diag_printf("** ERROR: unsupported bitmap header version, structure size must be %u\n",
561                                         BMP_HEADER_V3_SIZE);
562                 goto end_failure;
563         }
564
565         if (bmih.bit_count != 24) {
566                 diag_printf("** ERROR: only 24 bit BMP files are supported\n");
567                 goto end_failure;
568         }
569
570         if ((bmih.width != ldim->width) || (bmih.height != ldim->height)) {
571                 diag_printf("** ERROR: BMP image size %ux%u does not match configured size: %lux%lu\n",
572                                         bmih.width, bmih.height, ldim->width, ldim->height);
573                 goto end_failure;
574         }
575
576         /* pointer to picture data */
577         sp = (cyg_uint8 *)ram_addr + bmfh.offset;
578
579         if (bmih.bit_count == 16) {
580                 for (line = ldim->height; line > 0; line--) {
581                         memcpy(ldim->frame_buffer + (line - 1) * ldim->width,
582                                 sp, ldim->width * 2);
583                         sp += ldim->width * 2;
584                 }
585                 return;
586         }
587
588         for (line = ldim->height; line > 0; line--) {
589                 ppixel = ldim->frame_buffer + (line - 1) * ldim->width;
590                 for (col = 0; col < ldim->width; col ++) {
591                         blue    = *sp++ >> 3;   // 5 bits
592                         green   = *sp++ >> 2;   // 6 bits
593                         red             = *sp++ >> 3;   // 5 bits
594                         *ppixel++       = ((red << 11) | (green << 5) | (blue << 0));
595                 }
596         }
597         return;
598
599 end_failure:
600         paint_test_picture(ldim);
601 }
602
603 /*
604  * load the logo from nand flash to memory.
605  */
606 static bool do_logo_load(LCDDIM *ldim)
607 {
608         void *fis_addr;
609         int ret = 0xFF;
610         void *err_addr;
611         unsigned int logo_size;
612         struct fis_image_desc *img;
613         void *ram_addr;
614
615         /* Read the logo from storage media */
616         if ((img = fis_lookup("logo", NULL)) == NULL) {
617                 diag_printf("No logo partition found in the fis table, logo not loaded\n");
618                 return false;
619         }
620
621         fis_addr = (void *)img->flash_base;
622         ram_addr = (void *)img->mem_base;
623
624         logo_size = img->data_length;
625         ret = FLASH_READ(fis_addr, ram_addr, logo_size, &err_addr);
626         if (ret != 0) {
627                 diag_printf("Loading logo from FLASH to MEMORY failed. error code: %d", ret);
628                 return false;
629         }
630         if (!bootsplash_setup(ldim, logo_size)) {
631                 diag_printf("Cannot init splash screen; Invalid display parameters\n");
632                 return false;
633         }
634         load_bitmap(ldim, ram_addr, logo_size);
635         bootsplash_display(ldim);
636         return true;
637 }
638
639 static void redboot_bootsplash_display(void)
640 {
641         bool bootsplash_feature_enable;
642         int ok;
643         LCDDIM ldim;
644
645         gpio_set_bit(LCD_RESET_GPIO / 32, LCD_RESET_GPIO % 32);
646         gpio_set_bit(LCD_POWER_GPIO / 32, LCD_POWER_GPIO % 32);
647         gpio_set_bit(LCD_BACKLIGHT_GPIO / 32, LCD_BACKLIGHT_GPIO % 32);
648
649         ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
650                                                                         "bootsplash_enable",
651                                                                         &bootsplash_feature_enable, CONFIG_BOOL);
652         if (!ok) {
653                 diag_printf("fconfig variable bootsplash_enable not found\n");
654         }
655         if (ok && bootsplash_feature_enable) {
656                 do_logo_load(&ldim);
657         }
658 }
659
660 #ifdef CYGPKG_REDBOOT
661 RedBoot_init(redboot_bootsplash_display, RedBoot_INIT_SECOND);
662
663 RedBoot_config_option("Enable splash display at boot",
664                                         bootsplash_enable,
665                                         ALWAYS_ENABLED, true,
666                                         CONFIG_BOOL,
667                                         false
668         );
669
670 RedBoot_config_option("LCD frame buffer address",
671                                         lcd_buffer_addr,
672                                         "bootsplash_enable", true,
673                                         CONFIG_INT,
674                                         RAM_BANK0_BASE + RAM_BANK0_SIZE
675         );
676
677 RedBoot_config_option("Pixel clock period (in ps)",
678                                         lcd_clk_period,
679                                         "bootsplash_enable", true,
680                                         CONFIG_INT,
681                                         33333
682         );
683
684 RedBoot_config_option("Pixel polarity active low",
685                                         lcd_pix_polarity,
686                                         "bootsplash_enable", true,
687                                         CONFIG_BOOL,
688                                         false
689         );
690
691 RedBoot_config_option("Pixel clock polarity active low",
692                                         lcd_clk_polarity,
693                                         "bootsplash_enable", true,
694                                         CONFIG_BOOL,
695                                         false
696         );
697
698 RedBoot_config_option("LCD panel width (in pixels)",
699                                         lcd_panel_width,
700                                         "bootsplash_enable", true,
701                                         CONFIG_INT,
702                                         640
703         );
704
705 RedBoot_config_option("LCD panel height (in pixels)",
706                                         lcd_panel_height,
707                                         "bootsplash_enable", true,
708                                         CONFIG_INT,
709                                         480
710         );
711
712 RedBoot_config_option("LCD color depth (BPP)",
713                                         lcd_bpp,
714                                         "bootsplash_enable", true,
715                                         CONFIG_INT,
716                                         16
717         );
718
719 RedBoot_config_option("HSYNC pulse width (in pixels)",
720                                         lcd_hsync_width,
721                                         "bootsplash_enable", true,
722                                         CONFIG_INT,
723                                         64
724         );
725
726 RedBoot_config_option("HSYNC polarity active low",
727                                         lcd_hsync_polarity,
728                                         "bootsplash_enable", true,
729                                         CONFIG_BOOL,
730                                         true
731         );
732
733 RedBoot_config_option("Left margin (in pixels)",
734                                         lcd_margin_left,
735                                         "bootsplash_enable", true,
736                                         CONFIG_INT,
737                                         96
738         );
739
740 RedBoot_config_option("Right margin (in pixels)",
741                                         lcd_margin_right,
742                                         "bootsplash_enable", true,
743                                         CONFIG_INT,
744                                         80
745         );
746
747 RedBoot_config_option("VSYNC pulse width (in scan lines)",
748                                         lcd_vsync_width,
749                                         "bootsplash_enable", true,
750                                         CONFIG_INT,
751                                         3
752         );
753
754 RedBoot_config_option("VSYNC polarity active low",
755                                         lcd_vsync_polarity,
756                                         "bootsplash_enable", true,
757                                         CONFIG_BOOL,
758                                         true
759         );
760
761 RedBoot_config_option("Top margin (in scan lines)",
762                                         lcd_margin_top,
763                                         "bootsplash_enable", true,
764                                         CONFIG_INT,
765                                         46
766         );
767
768 RedBoot_config_option("Bottom margin (in scan lines)",
769                                         lcd_margin_bottom,
770                                         "bootsplash_enable", true,
771                                         CONFIG_INT,
772                                         39
773         );
774 #endif