fsl_diu_fb.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. /*
  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. #include <common.h>
  26. #include <i2c.h>
  27. #include <malloc.h>
  28. #ifdef CONFIG_FSL_DIU_FB
  29. #include "fsl_diu_fb.h"
  30. #ifdef DEBUG
  31. #define DPRINTF(fmt, args...) printf("%s: " fmt,__FUNCTION__,## args)
  32. #else
  33. #define DPRINTF(fmt, args...)
  34. #endif
  35. struct fb_var_screeninfo {
  36. unsigned int xres; /* visible resolution */
  37. unsigned int yres;
  38. unsigned int bits_per_pixel; /* guess what */
  39. /* Timing: All values in pixclocks, except pixclock (of course) */
  40. unsigned int pixclock; /* pixel clock in ps (pico seconds) */
  41. unsigned int left_margin; /* time from sync to picture */
  42. unsigned int right_margin; /* time from picture to sync */
  43. unsigned int upper_margin; /* time from sync to picture */
  44. unsigned int lower_margin;
  45. unsigned int hsync_len; /* length of horizontal sync */
  46. unsigned int vsync_len; /* length of vertical sync */
  47. unsigned int sync; /* see FB_SYNC_* */
  48. unsigned int vmode; /* see FB_VMODE_* */
  49. unsigned int rotate; /* angle we rotate counter clockwise */
  50. };
  51. struct fb_info {
  52. struct fb_var_screeninfo var; /* Current var */
  53. unsigned long smem_start; /* Start of frame buffer mem */
  54. /* (physical address) */
  55. unsigned int smem_len; /* Length of frame buffer mem */
  56. unsigned int type; /* see FB_TYPE_* */
  57. unsigned int line_length; /* length of a line in bytes */
  58. char *screen_base;
  59. unsigned long screen_size;
  60. int logo_height;
  61. unsigned int logo_size;
  62. };
  63. struct fb_videomode {
  64. const char *name; /* optional */
  65. unsigned int refresh; /* optional */
  66. unsigned int xres;
  67. unsigned int yres;
  68. unsigned int pixclock;
  69. unsigned int left_margin;
  70. unsigned int right_margin;
  71. unsigned int upper_margin;
  72. unsigned int lower_margin;
  73. unsigned int hsync_len;
  74. unsigned int vsync_len;
  75. unsigned int sync;
  76. unsigned int vmode;
  77. unsigned int flag;
  78. };
  79. #define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
  80. #define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
  81. #define FB_VMODE_NONINTERLACED 0 /* non interlaced */
  82. /*
  83. * These parameters give default parameters
  84. * for video output 1024x768,
  85. * FIXME - change timing to proper amounts
  86. * hsync 31.5kHz, vsync 60Hz
  87. */
  88. static struct fb_videomode fsl_diu_mode_1024 = {
  89. .refresh = 60,
  90. .xres = 1024,
  91. .yres = 768,
  92. .pixclock = 15385,
  93. .left_margin = 160,
  94. .right_margin = 24,
  95. .upper_margin = 29,
  96. .lower_margin = 3,
  97. .hsync_len = 136,
  98. .vsync_len = 6,
  99. .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  100. .vmode = FB_VMODE_NONINTERLACED
  101. };
  102. static struct fb_videomode fsl_diu_mode_1280 = {
  103. .name = "1280x1024-60",
  104. .refresh = 60,
  105. .xres = 1280,
  106. .yres = 1024,
  107. .pixclock = 9375,
  108. .left_margin = 38,
  109. .right_margin = 128,
  110. .upper_margin = 2,
  111. .lower_margin = 7,
  112. .hsync_len = 216,
  113. .vsync_len = 37,
  114. .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  115. .vmode = FB_VMODE_NONINTERLACED
  116. };
  117. /*
  118. * These are the fields of area descriptor(in DDR memory) for every plane
  119. */
  120. struct diu_ad {
  121. /* Word 0(32-bit) in DDR memory */
  122. unsigned int pix_fmt; /* hard coding pixel format */
  123. /* Word 1(32-bit) in DDR memory */
  124. unsigned int addr;
  125. /* Word 2(32-bit) in DDR memory */
  126. unsigned int src_size_g_alpha;
  127. /* Word 3(32-bit) in DDR memory */
  128. unsigned int aoi_size;
  129. /* Word 4(32-bit) in DDR memory */
  130. unsigned int offset_xyi;
  131. /* Word 5(32-bit) in DDR memory */
  132. unsigned int offset_xyd;
  133. /* Word 6(32-bit) in DDR memory */
  134. unsigned int ckmax_r:8;
  135. unsigned int ckmax_g:8;
  136. unsigned int ckmax_b:8;
  137. unsigned int res9:8;
  138. /* Word 7(32-bit) in DDR memory */
  139. unsigned int ckmin_r:8;
  140. unsigned int ckmin_g:8;
  141. unsigned int ckmin_b:8;
  142. unsigned int res10:8;
  143. /* Word 8(32-bit) in DDR memory */
  144. unsigned int next_ad;
  145. /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
  146. unsigned int res1;
  147. unsigned int res2;
  148. unsigned int res3;
  149. }__attribute__ ((packed));
  150. /*
  151. * DIU register map
  152. */
  153. struct diu {
  154. unsigned int desc[3];
  155. unsigned int gamma;
  156. unsigned int pallete;
  157. unsigned int cursor;
  158. unsigned int curs_pos;
  159. unsigned int diu_mode;
  160. unsigned int bgnd;
  161. unsigned int bgnd_wb;
  162. unsigned int disp_size;
  163. unsigned int wb_size;
  164. unsigned int wb_mem_addr;
  165. unsigned int hsyn_para;
  166. unsigned int vsyn_para;
  167. unsigned int syn_pol;
  168. unsigned int thresholds;
  169. unsigned int int_status;
  170. unsigned int int_mask;
  171. unsigned int colorbar[8];
  172. unsigned int filling;
  173. unsigned int plut;
  174. } __attribute__ ((packed));
  175. struct diu_hw {
  176. struct diu *diu_reg;
  177. volatile unsigned int mode; /* DIU operation mode */
  178. };
  179. struct diu_addr {
  180. unsigned char * paddr; /* Virtual address */
  181. unsigned int offset;
  182. };
  183. #define FSL_DIU_BASE_OFFSET 0x2C000 /* Offset of Display Interface Unit */
  184. /*
  185. * Modes of operation of DIU
  186. */
  187. #define MFB_MODE0 0 /* DIU off */
  188. #define MFB_MODE1 1 /* All three planes output to display */
  189. #define MFB_MODE2 2 /* Plane 1 to display,
  190. * planes 2+3 written back to memory */
  191. #define MFB_MODE3 3 /* All three planes written back to memory */
  192. #define MFB_MODE4 4 /* Color bar generation */
  193. #define MAX_CURS 32
  194. static struct fb_info fsl_fb_info;
  195. static struct diu_addr gamma, cursor;
  196. static struct diu_ad fsl_diu_fb_ad __attribute__ ((aligned(32)));
  197. static struct diu_ad dummy_ad __attribute__ ((aligned(32)));
  198. static unsigned char *dummy_fb;
  199. static struct diu_hw dr = {
  200. .mode = MFB_MODE1,
  201. };
  202. int fb_enabled = 0;
  203. int fb_initialized = 0;
  204. const int default_xres = 1280;
  205. const int default_pixel_format = 0x88882317;
  206. static int map_video_memory(struct fb_info *info, unsigned long bytes_align);
  207. static void enable_lcdc(void);
  208. static void disable_lcdc(void);
  209. static int fsl_diu_enable_panel(struct fb_info *info);
  210. static int fsl_diu_disable_panel(struct fb_info *info);
  211. static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align);
  212. static u32 get_busfreq(void);
  213. int fsl_diu_init(int xres,
  214. unsigned int pixel_format,
  215. int gamma_fix,
  216. unsigned char *splash_bmp)
  217. {
  218. struct fb_videomode *fsl_diu_mode_db;
  219. struct diu_ad *ad = &fsl_diu_fb_ad;
  220. struct diu *hw;
  221. struct fb_info *info = &fsl_fb_info;
  222. struct fb_var_screeninfo *var = &info->var;
  223. volatile immap_t *immap = (immap_t *)CFG_IMMR;
  224. volatile ccsr_gur_t *gur = &immap->im_gur;
  225. volatile unsigned int *guts_clkdvdr = &gur->clkdvdr;
  226. unsigned char *gamma_table_base;
  227. unsigned int i, j;
  228. unsigned long speed_ccb, temp, pixval;
  229. DPRINTF("Enter fsl_diu_init\n");
  230. dr.diu_reg = (struct diu *) (CFG_IMMR + FSL_DIU_BASE_OFFSET);
  231. hw = (struct diu *) dr.diu_reg;
  232. disable_lcdc();
  233. if (xres == 1280) {
  234. fsl_diu_mode_db = &fsl_diu_mode_1280;
  235. } else {
  236. fsl_diu_mode_db = &fsl_diu_mode_1024;
  237. }
  238. if (0 == fb_initialized) {
  239. allocate_buf(&gamma, 768, 32);
  240. DPRINTF("gamma is allocated @ 0x%x\n",
  241. (unsigned int)gamma.paddr);
  242. allocate_buf(&cursor, MAX_CURS * MAX_CURS * 2, 32);
  243. DPRINTF("curosr is allocated @ 0x%x\n",
  244. (unsigned int)cursor.paddr);
  245. /* create a dummy fb and dummy ad */
  246. dummy_fb = malloc(64);
  247. if (NULL == dummy_fb) {
  248. printf("Cannot allocate dummy fb\n");
  249. return -1;
  250. }
  251. dummy_ad.addr = cpu_to_le32((unsigned int)dummy_fb);
  252. dummy_ad.pix_fmt = 0x88882317;
  253. dummy_ad.src_size_g_alpha = 0x04400000; /* alpha = 0 */
  254. dummy_ad.aoi_size = 0x02000400;
  255. dummy_ad.offset_xyi = 0;
  256. dummy_ad.offset_xyd = 0;
  257. dummy_ad.next_ad = 0;
  258. /* Memory allocation for framebuffer */
  259. if (map_video_memory(info, 32)) {
  260. printf("Unable to allocate fb memory 1\n");
  261. return -1;
  262. }
  263. } else {
  264. memset(info->screen_base, 0, info->smem_len);
  265. }
  266. dr.diu_reg->desc[0] = (unsigned int) &dummy_ad;
  267. dr.diu_reg->desc[1] = (unsigned int) &dummy_ad;
  268. dr.diu_reg->desc[2] = (unsigned int) &dummy_ad;
  269. DPRINTF("dummy dr.diu_reg->desc[0] = 0x%x\n", dr.diu_reg->desc[0]);
  270. DPRINTF("dummy desc[0] = 0x%x\n", hw->desc[0]);
  271. /* read mode info */
  272. var->xres = fsl_diu_mode_db->xres;
  273. var->yres = fsl_diu_mode_db->yres;
  274. var->bits_per_pixel = 32;
  275. var->pixclock = fsl_diu_mode_db->pixclock;
  276. var->left_margin = fsl_diu_mode_db->left_margin;
  277. var->right_margin = fsl_diu_mode_db->right_margin;
  278. var->upper_margin = fsl_diu_mode_db->upper_margin;
  279. var->lower_margin = fsl_diu_mode_db->lower_margin;
  280. var->hsync_len = fsl_diu_mode_db->hsync_len;
  281. var->vsync_len = fsl_diu_mode_db->vsync_len;
  282. var->sync = fsl_diu_mode_db->sync;
  283. var->vmode = fsl_diu_mode_db->vmode;
  284. info->line_length = var->xres * var->bits_per_pixel / 8;
  285. info->logo_size = 0;
  286. info->logo_height = 0;
  287. ad->pix_fmt = pixel_format;
  288. ad->addr = cpu_to_le32((unsigned int)info->screen_base);
  289. ad->src_size_g_alpha
  290. = cpu_to_le32((var->yres << 12) | var->xres);
  291. /* fix me. AOI should not be greater than display size */
  292. ad->aoi_size = cpu_to_le32(( var->yres << 16) | var->xres);
  293. ad->offset_xyi = 0;
  294. ad->offset_xyd = 0;
  295. /* Disable chroma keying function */
  296. ad->ckmax_r = 0;
  297. ad->ckmax_g = 0;
  298. ad->ckmax_b = 0;
  299. ad->ckmin_r = 255;
  300. ad->ckmin_g = 255;
  301. ad->ckmin_b = 255;
  302. gamma_table_base = gamma.paddr;
  303. DPRINTF("gamma_table_base is allocated @ 0x%x\n",
  304. (unsigned int)gamma_table_base);
  305. /* Prep for DIU init - gamma table */
  306. for (i = 0; i <= 2; i++)
  307. for (j = 0; j <= 255; j++)
  308. *gamma_table_base++ = j;
  309. if (gamma_fix == 1) { /* fix the gamma */
  310. DPRINTF("Fix gamma table\n");
  311. gamma_table_base = gamma.paddr;
  312. for (i = 0; i < 256*3; i++) {
  313. gamma_table_base[i] = (gamma_table_base[i] << 2)
  314. | ((gamma_table_base[i] >> 6) & 0x03);
  315. }
  316. }
  317. DPRINTF("update-lcdc: HW - %p\n Disabling DIU\n", hw);
  318. /* Program DIU registers */
  319. hw->gamma = (unsigned int) gamma.paddr;
  320. hw->cursor= (unsigned int) cursor.paddr;
  321. hw->bgnd = 0x007F7F7F; /* BGND */
  322. hw->bgnd_wb = 0; /* BGND_WB */
  323. hw->disp_size = var->yres << 16 | var->xres; /* DISP SIZE */
  324. hw->wb_size = 0; /* WB SIZE */
  325. hw->wb_mem_addr = 0; /* WB MEM ADDR */
  326. hw->hsyn_para = var->left_margin << 22 | /* BP_H */
  327. var->hsync_len << 11 | /* PW_H */
  328. var->right_margin; /* FP_H */
  329. hw->vsyn_para = var->upper_margin << 22 | /* BP_V */
  330. var->vsync_len << 11 | /* PW_V */
  331. var->lower_margin; /* FP_V */
  332. /* Pixel Clock configuration */
  333. DPRINTF("DIU: Bus Frequency = %d\n", get_busfreq());
  334. speed_ccb = get_busfreq();
  335. DPRINTF("DIU pixclock in ps - %d\n", var->pixclock);
  336. temp = 1;
  337. temp *= 1000000000;
  338. temp /= var->pixclock;
  339. temp *= 1000;
  340. pixval = speed_ccb / temp;
  341. DPRINTF("DIU pixval = %lu\n", pixval);
  342. hw->syn_pol = 0; /* SYNC SIGNALS POLARITY */
  343. hw->thresholds = 0x00037800; /* The Thresholds */
  344. hw->int_status = 0; /* INTERRUPT STATUS */
  345. hw->int_mask = 0; /* INT MASK */
  346. hw->plut = 0x01F5F666;
  347. /* Modify PXCLK in GUTS CLKDVDR */
  348. DPRINTF("DIU: Current value of CLKDVDR = 0x%08x\n", *guts_clkdvdr);
  349. temp = *guts_clkdvdr & 0x2000FFFF;
  350. *guts_clkdvdr = temp; /* turn off clock */
  351. *guts_clkdvdr = temp | 0x80000000 | ((pixval & 0x1F) << 16);
  352. DPRINTF("DIU: Modified value of CLKDVDR = 0x%08x\n", *guts_clkdvdr);
  353. fb_initialized = 1;
  354. if (splash_bmp) {
  355. info->logo_height = fsl_diu_display_bmp(splash_bmp, 0, 0, 0);
  356. info->logo_size = info->logo_height * info->line_length;
  357. DPRINTF("logo height %d, logo_size 0x%x\n",
  358. info->logo_height,info->logo_size);
  359. }
  360. /* Enable the DIU */
  361. fsl_diu_enable_panel(info);
  362. enable_lcdc();
  363. return 0;
  364. }
  365. char *fsl_fb_open(struct fb_info **info)
  366. {
  367. *info = &fsl_fb_info;
  368. return (char *) ((unsigned int)(*info)->screen_base
  369. + (*info)->logo_size);
  370. }
  371. void fsl_diu_close(void)
  372. {
  373. struct fb_info *info = &fsl_fb_info;
  374. fsl_diu_disable_panel(info);
  375. }
  376. static int fsl_diu_enable_panel(struct fb_info *info)
  377. {
  378. struct diu *hw = dr.diu_reg;
  379. struct diu_ad *ad = &fsl_diu_fb_ad;
  380. DPRINTF("Entered: enable_panel\n");
  381. if (hw->desc[0] != (unsigned int)ad)
  382. hw->desc[0] = (unsigned int)ad;
  383. DPRINTF("desc[0] = 0x%x\n", hw->desc[0]);
  384. return 0;
  385. }
  386. static int fsl_diu_disable_panel(struct fb_info *info)
  387. {
  388. struct diu *hw = dr.diu_reg;
  389. DPRINTF("Entered: disable_panel\n");
  390. if (hw->desc[0] != (unsigned int)&dummy_ad)
  391. hw->desc[0] = (unsigned int)&dummy_ad;
  392. return 0;
  393. }
  394. static int map_video_memory(struct fb_info *info, unsigned long bytes_align)
  395. {
  396. unsigned long offset;
  397. unsigned long mask;
  398. DPRINTF("Entered: map_video_memory\n");
  399. /* allocate maximum 1280*1024 with 32bpp */
  400. info->smem_len = 1280 * 4 *1024 + bytes_align;
  401. DPRINTF("MAP_VIDEO_MEMORY: smem_len = %d\n", info->smem_len);
  402. info->screen_base = malloc(info->smem_len);
  403. if (info->screen_base == NULL) {
  404. printf("Unable to allocate fb memory\n");
  405. return -1;
  406. }
  407. info->smem_start = (unsigned int) info->screen_base;
  408. mask = bytes_align - 1;
  409. offset = (unsigned long)info->screen_base & mask;
  410. if (offset) {
  411. info->screen_base += offset;
  412. info->smem_len = info->smem_len - (bytes_align - offset);
  413. } else
  414. info->smem_len = info->smem_len - bytes_align;
  415. info->screen_size = info->smem_len;
  416. DPRINTF("Allocated fb @ 0x%08lx, size=%d.\n",
  417. info->smem_start, info->smem_len);
  418. return 0;
  419. }
  420. static void enable_lcdc(void)
  421. {
  422. struct diu *hw = dr.diu_reg;
  423. DPRINTF("Entered: enable_lcdc, fb_enabled = %d\n", fb_enabled);
  424. if (!fb_enabled) {
  425. hw->diu_mode = dr.mode;
  426. fb_enabled++;
  427. }
  428. DPRINTF("diu_mode = %d\n", hw->diu_mode);
  429. }
  430. static void disable_lcdc(void)
  431. {
  432. struct diu *hw = dr.diu_reg;
  433. DPRINTF("Entered: disable_lcdc, fb_enabled = %d\n", fb_enabled);
  434. if (fb_enabled) {
  435. hw->diu_mode = 0;
  436. fb_enabled = 0;
  437. }
  438. }
  439. static u32 get_busfreq(void)
  440. {
  441. u32 fs_busfreq = 0;
  442. fs_busfreq = get_bus_freq(0);
  443. return fs_busfreq;
  444. }
  445. /*
  446. * Align to 64-bit(8-byte), 32-byte, etc.
  447. */
  448. static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
  449. {
  450. u32 offset, ssize;
  451. u32 mask;
  452. DPRINTF("Entered: allocate_buf\n");
  453. ssize = size + bytes_align;
  454. buf->paddr = malloc(ssize);
  455. if (!buf->paddr)
  456. return -1;
  457. memset(buf->paddr, 0, ssize);
  458. mask = bytes_align - 1;
  459. offset = (u32)buf->paddr & mask;
  460. if (offset) {
  461. buf->offset = bytes_align - offset;
  462. buf->paddr = (unsigned char *) ((u32)buf->paddr + offset);
  463. } else
  464. buf->offset = 0;
  465. return 0;
  466. }
  467. int fsl_diu_display_bmp(unsigned char *bmp,
  468. int xoffset,
  469. int yoffset,
  470. int transpar)
  471. {
  472. struct fb_info *info = &fsl_fb_info;
  473. unsigned char r, g, b;
  474. unsigned int *fb_t, val;
  475. unsigned char *bitmap;
  476. unsigned int palette[256];
  477. int width, height, bpp, ncolors, raster, offset, x, y, i, k, cpp;
  478. if (!bmp) {
  479. printf("Must supply a bitmap address\n");
  480. return 0;
  481. }
  482. raster = bmp[10] + (bmp[11] << 8) + (bmp[12] << 16) + (bmp[13] << 24);
  483. width = (bmp[21] << 24) | (bmp[20] << 16) | (bmp[19] << 8) | bmp[18];
  484. height = (bmp[25] << 24) | (bmp[24] << 16) | (bmp[23] << 8) | bmp[22];
  485. bpp = (bmp[29] << 8) | (bmp[28]);
  486. ncolors = bmp[46] + (bmp[47] << 8) + (bmp[48] << 16) + (bmp[49] << 24);
  487. bitmap = bmp + raster;
  488. cpp = info->var.bits_per_pixel / 8;
  489. DPRINTF("bmp = 0x%08x\n", (unsigned int)bmp);
  490. DPRINTF("bitmap = 0x%08x\n", (unsigned int)bitmap);
  491. DPRINTF("width = %d\n", width);
  492. DPRINTF("height = %d\n", height);
  493. DPRINTF("bpp = %d\n", bpp);
  494. DPRINTF("ncolors = %d\n", ncolors);
  495. DPRINTF("xres = %d\n", info->var.xres);
  496. DPRINTF("yres = %d\n", info->var.yres);
  497. DPRINTF("Screen_base = 0x%x\n", (unsigned int)info->screen_base);
  498. if (((width+xoffset) > info->var.xres) ||
  499. ((height+yoffset) > info->var.yres)) {
  500. printf("bitmap is out of range, image too large or too much offset\n");
  501. return 0;
  502. }
  503. if (bpp < 24) {
  504. for (i = 0, offset = 54; i < ncolors; i++, offset += 4)
  505. palette[i] = (bmp[offset+2] << 16)
  506. + (bmp[offset+1] << 8) + bmp[offset];
  507. }
  508. switch (bpp) {
  509. case 1:
  510. for (y = height - 1; y >= 0; y--) {
  511. fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
  512. for (x = 0; x < width; x += 8) {
  513. b = *bitmap++;
  514. for (k = 0; k < 8; k++) {
  515. if (b & 0x80)
  516. *fb_t = palette[1];
  517. else
  518. *fb_t = palette[0];
  519. b = b << 1;
  520. }
  521. }
  522. for (i = (width / 2) % 4; i > 0; i--)
  523. bitmap++;
  524. }
  525. break;
  526. case 4:
  527. for (y = height - 1; y >= 0; y--) {
  528. fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
  529. for (x = 0; x < width; x += 2) {
  530. b = *bitmap++;
  531. r = (b >> 4) & 0x0F;
  532. g = b & 0x0F;
  533. *fb_t++ = palette[r];
  534. *fb_t++ = palette[g];
  535. }
  536. for (i = (width / 2) % 4; i > 0; i--)
  537. bitmap++;
  538. }
  539. break;
  540. case 8:
  541. for (y = height - 1; y >= 0; y--) {
  542. fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
  543. for (x = 0; x < width; x++) {
  544. *fb_t++ = palette[ *bitmap++ ];
  545. }
  546. for (i = (width / 2) % 4; i > 0; i--)
  547. bitmap++;
  548. }
  549. break;
  550. case 24:
  551. for (y = height - 1; y >= 0; y--) {
  552. fb_t = (unsigned int *) ((unsigned int)info->screen_base + (((y+yoffset) * info->var.xres) + xoffset)*cpp);
  553. for (x = 0; x < width; x++) {
  554. b = *bitmap++;
  555. g = *bitmap++;
  556. r = *bitmap++;
  557. val = (r << 16) + (g << 8) + b;
  558. *fb_t++ = val;
  559. }
  560. for (; (x % 4) != 0; x++) /* 4-byte alignment */
  561. bitmap++;
  562. }
  563. break;
  564. }
  565. return height;
  566. }
  567. void fsl_diu_clear_screen(void)
  568. {
  569. struct fb_info *info = &fsl_fb_info;
  570. memset(info->screen_base, 0, info->smem_len);
  571. }
  572. #endif /* CONFIG_FSL_DIU_FB */