blob: cbee8fe09353aebd1aec34e72a081ac808372451 [file] [log] [blame]
York Sunb7145172007-10-29 13:58:39 -05001/*
2 * Copyright 2007 Freescale Semiconductor, Inc.
3 * York Sun <yorksun@freescale.com>
4 *
5 * FSL DIU Framebuffer driver
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
York Sunb7145172007-10-29 13:58:39 -050026#include <common.h>
27#include <i2c.h>
28#include <malloc.h>
29
York Sunb7145172007-10-29 13:58:39 -050030#include "fsl_diu_fb.h"
31
York Sunb7145172007-10-29 13:58:39 -050032struct fb_videomode {
33 const char *name; /* optional */
34 unsigned int refresh; /* optional */
35 unsigned int xres;
36 unsigned int yres;
37 unsigned int pixclock;
38 unsigned int left_margin;
39 unsigned int right_margin;
40 unsigned int upper_margin;
41 unsigned int lower_margin;
42 unsigned int hsync_len;
43 unsigned int vsync_len;
44 unsigned int sync;
45 unsigned int vmode;
46 unsigned int flag;
47};
48
49#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
50#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
51#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
52
Anatolij Gustschin81cad142010-04-24 19:27:09 +020053/* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */
54static struct fb_videomode fsl_diu_mode_800 = {
55 .refresh = 60,
56 .xres = 800,
57 .yres = 480,
58 .pixclock = 31250,
59 .left_margin = 86,
60 .right_margin = 42,
61 .upper_margin = 33,
62 .lower_margin = 10,
63 .hsync_len = 128,
64 .vsync_len = 2,
65 .sync = 0,
66 .vmode = FB_VMODE_NONINTERLACED
67};
68
York Sunb7145172007-10-29 13:58:39 -050069/*
70 * These parameters give default parameters
71 * for video output 1024x768,
72 * FIXME - change timing to proper amounts
73 * hsync 31.5kHz, vsync 60Hz
74 */
75static struct fb_videomode fsl_diu_mode_1024 = {
76 .refresh = 60,
77 .xres = 1024,
78 .yres = 768,
79 .pixclock = 15385,
80 .left_margin = 160,
81 .right_margin = 24,
82 .upper_margin = 29,
83 .lower_margin = 3,
84 .hsync_len = 136,
85 .vsync_len = 6,
86 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
87 .vmode = FB_VMODE_NONINTERLACED
88};
89
90static struct fb_videomode fsl_diu_mode_1280 = {
91 .name = "1280x1024-60",
92 .refresh = 60,
93 .xres = 1280,
94 .yres = 1024,
95 .pixclock = 9375,
96 .left_margin = 38,
97 .right_margin = 128,
98 .upper_margin = 2,
99 .lower_margin = 7,
100 .hsync_len = 216,
101 .vsync_len = 37,
102 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
103 .vmode = FB_VMODE_NONINTERLACED
104};
105
106/*
107 * These are the fields of area descriptor(in DDR memory) for every plane
108 */
109struct diu_ad {
110 /* Word 0(32-bit) in DDR memory */
111 unsigned int pix_fmt; /* hard coding pixel format */
112 /* Word 1(32-bit) in DDR memory */
113 unsigned int addr;
114 /* Word 2(32-bit) in DDR memory */
115 unsigned int src_size_g_alpha;
116 /* Word 3(32-bit) in DDR memory */
117 unsigned int aoi_size;
118 /* Word 4(32-bit) in DDR memory */
119 unsigned int offset_xyi;
120 /* Word 5(32-bit) in DDR memory */
121 unsigned int offset_xyd;
122 /* Word 6(32-bit) in DDR memory */
123 unsigned int ckmax_r:8;
124 unsigned int ckmax_g:8;
125 unsigned int ckmax_b:8;
126 unsigned int res9:8;
127 /* Word 7(32-bit) in DDR memory */
128 unsigned int ckmin_r:8;
129 unsigned int ckmin_g:8;
130 unsigned int ckmin_b:8;
131 unsigned int res10:8;
132 /* Word 8(32-bit) in DDR memory */
133 unsigned int next_ad;
134 /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
135 unsigned int res1;
136 unsigned int res2;
137 unsigned int res3;
138}__attribute__ ((packed));
139
140/*
141 * DIU register map
142 */
143struct diu {
144 unsigned int desc[3];
145 unsigned int gamma;
146 unsigned int pallete;
147 unsigned int cursor;
148 unsigned int curs_pos;
149 unsigned int diu_mode;
150 unsigned int bgnd;
151 unsigned int bgnd_wb;
152 unsigned int disp_size;
153 unsigned int wb_size;
154 unsigned int wb_mem_addr;
155 unsigned int hsyn_para;
156 unsigned int vsyn_para;
157 unsigned int syn_pol;
158 unsigned int thresholds;
159 unsigned int int_status;
160 unsigned int int_mask;
161 unsigned int colorbar[8];
162 unsigned int filling;
163 unsigned int plut;
164} __attribute__ ((packed));
165
166struct diu_hw {
167 struct diu *diu_reg;
168 volatile unsigned int mode; /* DIU operation mode */
169};
170
171struct diu_addr {
172 unsigned char * paddr; /* Virtual address */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200173 unsigned int offset;
York Sunb7145172007-10-29 13:58:39 -0500174};
175
York Sunb7145172007-10-29 13:58:39 -0500176/*
177 * Modes of operation of DIU
178 */
179#define MFB_MODE0 0 /* DIU off */
180#define MFB_MODE1 1 /* All three planes output to display */
181#define MFB_MODE2 2 /* Plane 1 to display,
182 * planes 2+3 written back to memory */
183#define MFB_MODE3 3 /* All three planes written back to memory */
184#define MFB_MODE4 4 /* Color bar generation */
185
186#define MAX_CURS 32
187
York Sunb7145172007-10-29 13:58:39 -0500188static struct fb_info fsl_fb_info;
189static struct diu_addr gamma, cursor;
190static struct diu_ad fsl_diu_fb_ad __attribute__ ((aligned(32)));
191static struct diu_ad dummy_ad __attribute__ ((aligned(32)));
192static unsigned char *dummy_fb;
193static struct diu_hw dr = {
194 .mode = MFB_MODE1,
195};
196
197int fb_enabled = 0;
198int fb_initialized = 0;
199const int default_xres = 1280;
200const int default_pixel_format = 0x88882317;
201
202static int map_video_memory(struct fb_info *info, unsigned long bytes_align);
203static void enable_lcdc(void);
204static void disable_lcdc(void);
205static int fsl_diu_enable_panel(struct fb_info *info);
206static int fsl_diu_disable_panel(struct fb_info *info);
207static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align);
York Sunc4964382008-05-05 10:19:59 -0500208void diu_set_pixel_clock(unsigned int pixclock);
York Sunb7145172007-10-29 13:58:39 -0500209
York Sunb7145172007-10-29 13:58:39 -0500210int fsl_diu_init(int xres,
211 unsigned int pixel_format,
212 int gamma_fix,
213 unsigned char *splash_bmp)
214{
215 struct fb_videomode *fsl_diu_mode_db;
216 struct diu_ad *ad = &fsl_diu_fb_ad;
217 struct diu *hw;
218 struct fb_info *info = &fsl_fb_info;
219 struct fb_var_screeninfo *var = &info->var;
York Sunb7145172007-10-29 13:58:39 -0500220 unsigned char *gamma_table_base;
221 unsigned int i, j;
York Sunb7145172007-10-29 13:58:39 -0500222
York Sun94cbda92008-05-05 10:20:00 -0500223 debug("Enter fsl_diu_init\n");
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200224 dr.diu_reg = (struct diu *) (CONFIG_SYS_DIU_ADDR);
York Sunb7145172007-10-29 13:58:39 -0500225 hw = (struct diu *) dr.diu_reg;
226
227 disable_lcdc();
228
Anatolij Gustschin81cad142010-04-24 19:27:09 +0200229 switch (xres) {
230 case 800:
231 fsl_diu_mode_db = &fsl_diu_mode_800;
232 break;
233 case 1280:
York Sunb7145172007-10-29 13:58:39 -0500234 fsl_diu_mode_db = &fsl_diu_mode_1280;
Anatolij Gustschin81cad142010-04-24 19:27:09 +0200235 break;
236 default:
York Sunb7145172007-10-29 13:58:39 -0500237 fsl_diu_mode_db = &fsl_diu_mode_1024;
238 }
239
240 if (0 == fb_initialized) {
241 allocate_buf(&gamma, 768, 32);
York Sun94cbda92008-05-05 10:20:00 -0500242 debug("gamma is allocated @ 0x%x\n",
York Sunb7145172007-10-29 13:58:39 -0500243 (unsigned int)gamma.paddr);
244 allocate_buf(&cursor, MAX_CURS * MAX_CURS * 2, 32);
York Sun94cbda92008-05-05 10:20:00 -0500245 debug("curosr is allocated @ 0x%x\n",
York Sunb7145172007-10-29 13:58:39 -0500246 (unsigned int)cursor.paddr);
247
248 /* create a dummy fb and dummy ad */
249 dummy_fb = malloc(64);
250 if (NULL == dummy_fb) {
251 printf("Cannot allocate dummy fb\n");
252 return -1;
253 }
254 dummy_ad.addr = cpu_to_le32((unsigned int)dummy_fb);
255 dummy_ad.pix_fmt = 0x88882317;
256 dummy_ad.src_size_g_alpha = 0x04400000; /* alpha = 0 */
257 dummy_ad.aoi_size = 0x02000400;
258 dummy_ad.offset_xyi = 0;
259 dummy_ad.offset_xyd = 0;
260 dummy_ad.next_ad = 0;
261 /* Memory allocation for framebuffer */
262 if (map_video_memory(info, 32)) {
263 printf("Unable to allocate fb memory 1\n");
264 return -1;
265 }
York Sunb7145172007-10-29 13:58:39 -0500266 }
267
Nikita V. Youshchenko7e6647e2008-10-03 00:03:55 +0400268 memset(info->screen_base, 0, info->smem_len);
269
York Sunb7145172007-10-29 13:58:39 -0500270 dr.diu_reg->desc[0] = (unsigned int) &dummy_ad;
271 dr.diu_reg->desc[1] = (unsigned int) &dummy_ad;
272 dr.diu_reg->desc[2] = (unsigned int) &dummy_ad;
York Sun94cbda92008-05-05 10:20:00 -0500273 debug("dummy dr.diu_reg->desc[0] = 0x%x\n", dr.diu_reg->desc[0]);
274 debug("dummy desc[0] = 0x%x\n", hw->desc[0]);
York Sunb7145172007-10-29 13:58:39 -0500275
276 /* read mode info */
277 var->xres = fsl_diu_mode_db->xres;
278 var->yres = fsl_diu_mode_db->yres;
279 var->bits_per_pixel = 32;
280 var->pixclock = fsl_diu_mode_db->pixclock;
281 var->left_margin = fsl_diu_mode_db->left_margin;
282 var->right_margin = fsl_diu_mode_db->right_margin;
283 var->upper_margin = fsl_diu_mode_db->upper_margin;
284 var->lower_margin = fsl_diu_mode_db->lower_margin;
285 var->hsync_len = fsl_diu_mode_db->hsync_len;
286 var->vsync_len = fsl_diu_mode_db->vsync_len;
287 var->sync = fsl_diu_mode_db->sync;
288 var->vmode = fsl_diu_mode_db->vmode;
289 info->line_length = var->xres * var->bits_per_pixel / 8;
290 info->logo_size = 0;
291 info->logo_height = 0;
292
293 ad->pix_fmt = pixel_format;
294 ad->addr = cpu_to_le32((unsigned int)info->screen_base);
295 ad->src_size_g_alpha
296 = cpu_to_le32((var->yres << 12) | var->xres);
297 /* fix me. AOI should not be greater than display size */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200298 ad->aoi_size = cpu_to_le32(( var->yres << 16) | var->xres);
York Sunb7145172007-10-29 13:58:39 -0500299 ad->offset_xyi = 0;
300 ad->offset_xyd = 0;
301
302 /* Disable chroma keying function */
303 ad->ckmax_r = 0;
304 ad->ckmax_g = 0;
305 ad->ckmax_b = 0;
306
307 ad->ckmin_r = 255;
308 ad->ckmin_g = 255;
309 ad->ckmin_b = 255;
310
311 gamma_table_base = gamma.paddr;
York Sun94cbda92008-05-05 10:20:00 -0500312 debug("gamma_table_base is allocated @ 0x%x\n",
York Sunb7145172007-10-29 13:58:39 -0500313 (unsigned int)gamma_table_base);
314
315 /* Prep for DIU init - gamma table */
316
317 for (i = 0; i <= 2; i++)
318 for (j = 0; j <= 255; j++)
319 *gamma_table_base++ = j;
320
321 if (gamma_fix == 1) { /* fix the gamma */
York Sun94cbda92008-05-05 10:20:00 -0500322 debug("Fix gamma table\n");
York Sunb7145172007-10-29 13:58:39 -0500323 gamma_table_base = gamma.paddr;
324 for (i = 0; i < 256*3; i++) {
325 gamma_table_base[i] = (gamma_table_base[i] << 2)
326 | ((gamma_table_base[i] >> 6) & 0x03);
327 }
328 }
329
York Sun94cbda92008-05-05 10:20:00 -0500330 debug("update-lcdc: HW - %p\n Disabling DIU\n", hw);
York Sunb7145172007-10-29 13:58:39 -0500331
332 /* Program DIU registers */
333
334 hw->gamma = (unsigned int) gamma.paddr;
335 hw->cursor= (unsigned int) cursor.paddr;
336 hw->bgnd = 0x007F7F7F; /* BGND */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200337 hw->bgnd_wb = 0; /* BGND_WB */
York Sunb7145172007-10-29 13:58:39 -0500338 hw->disp_size = var->yres << 16 | var->xres; /* DISP SIZE */
339 hw->wb_size = 0; /* WB SIZE */
340 hw->wb_mem_addr = 0; /* WB MEM ADDR */
341 hw->hsyn_para = var->left_margin << 22 | /* BP_H */
342 var->hsync_len << 11 | /* PW_H */
343 var->right_margin; /* FP_H */
344 hw->vsyn_para = var->upper_margin << 22 | /* BP_V */
345 var->vsync_len << 11 | /* PW_V */
346 var->lower_margin; /* FP_V */
347
York Sunb7145172007-10-29 13:58:39 -0500348 hw->syn_pol = 0; /* SYNC SIGNALS POLARITY */
349 hw->thresholds = 0x00037800; /* The Thresholds */
350 hw->int_status = 0; /* INTERRUPT STATUS */
351 hw->int_mask = 0; /* INT MASK */
352 hw->plut = 0x01F5F666;
353
York Sunc4964382008-05-05 10:19:59 -0500354 /* Pixel Clock configuration */
York Sun94cbda92008-05-05 10:20:00 -0500355 debug("DIU pixclock in ps - %d\n", var->pixclock);
York Sunc4964382008-05-05 10:19:59 -0500356 diu_set_pixel_clock(var->pixclock);
York Sunb7145172007-10-29 13:58:39 -0500357
358 fb_initialized = 1;
359
360 if (splash_bmp) {
361 info->logo_height = fsl_diu_display_bmp(splash_bmp, 0, 0, 0);
362 info->logo_size = info->logo_height * info->line_length;
York Sun94cbda92008-05-05 10:20:00 -0500363 debug("logo height %d, logo_size 0x%x\n",
York Sunb7145172007-10-29 13:58:39 -0500364 info->logo_height,info->logo_size);
365 }
366
367 /* Enable the DIU */
368 fsl_diu_enable_panel(info);
369 enable_lcdc();
370
371 return 0;
372}
373
374char *fsl_fb_open(struct fb_info **info)
375{
376 *info = &fsl_fb_info;
377 return (char *) ((unsigned int)(*info)->screen_base
378 + (*info)->logo_size);
379}
380
381void fsl_diu_close(void)
382{
383 struct fb_info *info = &fsl_fb_info;
384 fsl_diu_disable_panel(info);
385}
386
387static int fsl_diu_enable_panel(struct fb_info *info)
388{
389 struct diu *hw = dr.diu_reg;
390 struct diu_ad *ad = &fsl_diu_fb_ad;
391
York Sun94cbda92008-05-05 10:20:00 -0500392 debug("Entered: enable_panel\n");
York Sunb7145172007-10-29 13:58:39 -0500393 if (hw->desc[0] != (unsigned int)ad)
394 hw->desc[0] = (unsigned int)ad;
York Sun94cbda92008-05-05 10:20:00 -0500395 debug("desc[0] = 0x%x\n", hw->desc[0]);
York Sunb7145172007-10-29 13:58:39 -0500396 return 0;
397}
398
399static int fsl_diu_disable_panel(struct fb_info *info)
400{
401 struct diu *hw = dr.diu_reg;
402
York Sun94cbda92008-05-05 10:20:00 -0500403 debug("Entered: disable_panel\n");
York Sunb7145172007-10-29 13:58:39 -0500404 if (hw->desc[0] != (unsigned int)&dummy_ad)
405 hw->desc[0] = (unsigned int)&dummy_ad;
406 return 0;
407}
408
409static int map_video_memory(struct fb_info *info, unsigned long bytes_align)
410{
411 unsigned long offset;
412 unsigned long mask;
413
York Sun94cbda92008-05-05 10:20:00 -0500414 debug("Entered: map_video_memory\n");
York Sunb7145172007-10-29 13:58:39 -0500415 /* allocate maximum 1280*1024 with 32bpp */
416 info->smem_len = 1280 * 4 *1024 + bytes_align;
York Sun94cbda92008-05-05 10:20:00 -0500417 debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->smem_len);
York Sunb7145172007-10-29 13:58:39 -0500418 info->screen_base = malloc(info->smem_len);
419 if (info->screen_base == NULL) {
420 printf("Unable to allocate fb memory\n");
421 return -1;
422 }
423 info->smem_start = (unsigned int) info->screen_base;
424 mask = bytes_align - 1;
425 offset = (unsigned long)info->screen_base & mask;
426 if (offset) {
Nikita V. Youshchenko7e6647e2008-10-03 00:03:55 +0400427 info->screen_base += (bytes_align - offset);
York Sunb7145172007-10-29 13:58:39 -0500428 info->smem_len = info->smem_len - (bytes_align - offset);
429 } else
430 info->smem_len = info->smem_len - bytes_align;
431
432 info->screen_size = info->smem_len;
433
York Sun94cbda92008-05-05 10:20:00 -0500434 debug("Allocated fb @ 0x%08lx, size=%d.\n",
York Sunb7145172007-10-29 13:58:39 -0500435 info->smem_start, info->smem_len);
436
437 return 0;
438}
439
440static void enable_lcdc(void)
441{
442 struct diu *hw = dr.diu_reg;
443
York Sun94cbda92008-05-05 10:20:00 -0500444 debug("Entered: enable_lcdc, fb_enabled = %d\n", fb_enabled);
York Sunb7145172007-10-29 13:58:39 -0500445 if (!fb_enabled) {
446 hw->diu_mode = dr.mode;
447 fb_enabled++;
448 }
York Sun94cbda92008-05-05 10:20:00 -0500449 debug("diu_mode = %d\n", hw->diu_mode);
York Sunb7145172007-10-29 13:58:39 -0500450}
451
452static void disable_lcdc(void)
453{
454 struct diu *hw = dr.diu_reg;
455
York Sun94cbda92008-05-05 10:20:00 -0500456 debug("Entered: disable_lcdc, fb_enabled = %d\n", fb_enabled);
York Sunb7145172007-10-29 13:58:39 -0500457 if (fb_enabled) {
458 hw->diu_mode = 0;
459 fb_enabled = 0;
460 }
461}
462
York Sunb7145172007-10-29 13:58:39 -0500463/*
464 * Align to 64-bit(8-byte), 32-byte, etc.
465 */
466static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
467{
468 u32 offset, ssize;
469 u32 mask;
470
York Sun94cbda92008-05-05 10:20:00 -0500471 debug("Entered: allocate_buf\n");
York Sunb7145172007-10-29 13:58:39 -0500472 ssize = size + bytes_align;
473 buf->paddr = malloc(ssize);
474 if (!buf->paddr)
475 return -1;
476
477 memset(buf->paddr, 0, ssize);
478 mask = bytes_align - 1;
479 offset = (u32)buf->paddr & mask;
480 if (offset) {
481 buf->offset = bytes_align - offset;
482 buf->paddr = (unsigned char *) ((u32)buf->paddr + offset);
483 } else
484 buf->offset = 0;
485 return 0;
486}
487
488int fsl_diu_display_bmp(unsigned char *bmp,
489 int xoffset,
490 int yoffset,
491 int transpar)
492{
493 struct fb_info *info = &fsl_fb_info;
494 unsigned char r, g, b;
495 unsigned int *fb_t, val;
496 unsigned char *bitmap;
497 unsigned int palette[256];
498 int width, height, bpp, ncolors, raster, offset, x, y, i, k, cpp;
499
500 if (!bmp) {
501 printf("Must supply a bitmap address\n");
502 return 0;
503 }
504
505 raster = bmp[10] + (bmp[11] << 8) + (bmp[12] << 16) + (bmp[13] << 24);
506 width = (bmp[21] << 24) | (bmp[20] << 16) | (bmp[19] << 8) | bmp[18];
507 height = (bmp[25] << 24) | (bmp[24] << 16) | (bmp[23] << 8) | bmp[22];
508 bpp = (bmp[29] << 8) | (bmp[28]);
509 ncolors = bmp[46] + (bmp[47] << 8) + (bmp[48] << 16) + (bmp[49] << 24);
510 bitmap = bmp + raster;
511 cpp = info->var.bits_per_pixel / 8;
512
York Sun94cbda92008-05-05 10:20:00 -0500513 debug("bmp = 0x%08x\n", (unsigned int)bmp);
514 debug("bitmap = 0x%08x\n", (unsigned int)bitmap);
515 debug("width = %d\n", width);
516 debug("height = %d\n", height);
517 debug("bpp = %d\n", bpp);
518 debug("ncolors = %d\n", ncolors);
York Sunb7145172007-10-29 13:58:39 -0500519
York Sun94cbda92008-05-05 10:20:00 -0500520 debug("xres = %d\n", info->var.xres);
521 debug("yres = %d\n", info->var.yres);
522 debug("Screen_base = 0x%x\n", (unsigned int)info->screen_base);
York Sunb7145172007-10-29 13:58:39 -0500523
524 if (((width+xoffset) > info->var.xres) ||
525 ((height+yoffset) > info->var.yres)) {
526 printf("bitmap is out of range, image too large or too much offset\n");
527 return 0;
528 }
529 if (bpp < 24) {
530 for (i = 0, offset = 54; i < ncolors; i++, offset += 4)
531 palette[i] = (bmp[offset+2] << 16)
532 + (bmp[offset+1] << 8) + bmp[offset];
533 }
534
535 switch (bpp) {
536 case 1:
537 for (y = height - 1; y >= 0; y--) {
538 fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
539 for (x = 0; x < width; x += 8) {
540 b = *bitmap++;
541 for (k = 0; k < 8; k++) {
542 if (b & 0x80)
Anatolij Gustschin81cad142010-04-24 19:27:09 +0200543 *fb_t++ = palette[1];
York Sunb7145172007-10-29 13:58:39 -0500544 else
Anatolij Gustschin81cad142010-04-24 19:27:09 +0200545 *fb_t++ = palette[0];
York Sunb7145172007-10-29 13:58:39 -0500546 b = b << 1;
547 }
548 }
549 for (i = (width / 2) % 4; i > 0; i--)
550 bitmap++;
551 }
552 break;
553 case 4:
554 for (y = height - 1; y >= 0; y--) {
555 fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
556 for (x = 0; x < width; x += 2) {
557 b = *bitmap++;
558 r = (b >> 4) & 0x0F;
559 g = b & 0x0F;
560 *fb_t++ = palette[r];
561 *fb_t++ = palette[g];
562 }
563 for (i = (width / 2) % 4; i > 0; i--)
564 bitmap++;
565 }
566 break;
567 case 8:
568 for (y = height - 1; y >= 0; y--) {
569 fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
570 for (x = 0; x < width; x++) {
571 *fb_t++ = palette[ *bitmap++ ];
572 }
573 for (i = (width / 2) % 4; i > 0; i--)
574 bitmap++;
575 }
576 break;
577 case 24:
578 for (y = height - 1; y >= 0; y--) {
579 fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
580 for (x = 0; x < width; x++) {
581 b = *bitmap++;
582 g = *bitmap++;
583 r = *bitmap++;
584 val = (r << 16) + (g << 8) + b;
585 *fb_t++ = val;
586 }
587 for (; (x % 4) != 0; x++) /* 4-byte alignment */
588 bitmap++;
589 }
590 break;
591 }
592
593 return height;
594}
595
596void fsl_diu_clear_screen(void)
597{
598 struct fb_info *info = &fsl_fb_info;
599
600 memset(info->screen_base, 0, info->smem_len);
601}