lcd.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. /*
  2. * (C) Copyright 2001-2002
  3. * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /************************************************************************/
  24. /* ** HEADER FILES */
  25. /************************************************************************/
  26. #include <config.h>
  27. #include <common.h>
  28. #include <version.h>
  29. #include <stdarg.h>
  30. #include <lcdvideo.h>
  31. #include <linux/types.h>
  32. #include <devices.h>
  33. #ifdef CONFIG_LCD
  34. /************************************************************************/
  35. /* ** CONFIG STUFF -- should be moved to board config file */
  36. /************************************************************************/
  37. #ifndef CONFIG_EDT32F10
  38. #define CONFIG_LCD_LOGO
  39. #define LCD_INFO /* Display Logo, (C) and system info */
  40. #endif
  41. #ifdef CONFIG_V37
  42. #undef CONFIG_LCD_LOGO
  43. #undef LCD_INFO
  44. #endif
  45. /* #define LCD_TEST_PATTERN */ /* color backgnd for frame/color adjust */
  46. /* #define CFG_INVERT_COLORS */ /* Not needed - adjust vl_dp instead */
  47. /************************************************************************/
  48. /************************************************************************/
  49. /* ** FONT AND LOGO DATA */
  50. /************************************************************************/
  51. #include <video_font.h> /* Get font data, width and height */
  52. #ifdef CONFIG_LCD_LOGO
  53. # include <bmp_logo.h> /* Get logo data, width and height */
  54. #endif
  55. /************************************************************************/
  56. /************************************************************************/
  57. /*
  58. * Information about displays we are using. This is for configuring
  59. * the LCD controller and memory allocation. Someone has to know what
  60. * is connected, as we can't autodetect anything.
  61. */
  62. #define CFG_HIGH 0 /* Pins are active high */
  63. #define CFG_LOW 1 /* Pins are active low */
  64. typedef struct vidinfo {
  65. ushort vl_col; /* Number of columns (i.e. 640) */
  66. ushort vl_row; /* Number of rows (i.e. 480) */
  67. ushort vl_width; /* Width of display area in millimeters */
  68. ushort vl_height; /* Height of display area in millimeters */
  69. /* LCD configuration register.
  70. */
  71. u_char vl_clkp; /* Clock polarity */
  72. u_char vl_oep; /* Output Enable polarity */
  73. u_char vl_hsp; /* Horizontal Sync polarity */
  74. u_char vl_vsp; /* Vertical Sync polarity */
  75. u_char vl_dp; /* Data polarity */
  76. u_char vl_bpix; /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
  77. u_char vl_lbw; /* LCD Bus width, 0 = 4, 1 = 8 */
  78. u_char vl_splt; /* Split display, 0 = single-scan, 1 = dual-scan */
  79. u_char vl_clor; /* Color, 0 = mono, 1 = color */
  80. u_char vl_tft; /* 0 = passive, 1 = TFT */
  81. /* Horizontal control register. Timing from data sheet.
  82. */
  83. ushort vl_wbl; /* Wait between lines */
  84. /* Vertical control register.
  85. */
  86. u_char vl_vpw; /* Vertical sync pulse width */
  87. u_char vl_lcdac; /* LCD AC timing */
  88. u_char vl_wbf; /* Wait between frames */
  89. } vidinfo_t;
  90. #define LCD_MONOCHROME 0
  91. #define LCD_COLOR2 1
  92. #define LCD_COLOR4 2
  93. #define LCD_COLOR8 3
  94. /*----------------------------------------------------------------------*/
  95. #ifdef CONFIG_KYOCERA_KCS057QV1AJ
  96. /*
  97. * Kyocera KCS057QV1AJ-G23. Passive, color, single scan.
  98. */
  99. #define LCD_BPP LCD_COLOR4
  100. static vidinfo_t panel_info = {
  101. 640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH,
  102. LCD_BPP, 1, 0, 1, 0, 5, 0, 0, 0
  103. /* wbl, vpw, lcdac, wbf */
  104. };
  105. #endif /* CONFIG_KYOCERA_KCS057QV1AJ */
  106. /*----------------------------------------------------------------------*/
  107. /*----------------------------------------------------------------------*/
  108. #ifdef CONFIG_NEC_NL6648AC33
  109. /*
  110. * NEC NL6648AC33-18. Active, color, single scan.
  111. */
  112. static vidinfo_t panel_info = {
  113. 640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
  114. 3, 0, 0, 1, 1, 144, 2, 0, 33
  115. /* wbl, vpw, lcdac, wbf */
  116. };
  117. #endif /* CONFIG_NEC_NL6648AC33 */
  118. /*----------------------------------------------------------------------*/
  119. #ifdef CONFIG_NEC_NL6648BC20
  120. /*
  121. * NEC NL6648BC20-08. 6.5", 640x480. Active, color, single scan.
  122. */
  123. static vidinfo_t panel_info = {
  124. 640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
  125. 3, 0, 0, 1, 1, 144, 2, 0, 33
  126. /* wbl, vpw, lcdac, wbf */
  127. };
  128. #endif /* CONFIG_NEC_NL6648BC20 */
  129. /*----------------------------------------------------------------------*/
  130. #ifdef CONFIG_SHARP_LQ104V7DS01
  131. /*
  132. * SHARP LQ104V7DS01. 6.5", 640x480. Active, color, single scan.
  133. */
  134. static vidinfo_t panel_info = {
  135. 640, 480, 132, 99, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_LOW,
  136. 3, 0, 0, 1, 1, 25, 1, 0, 33
  137. /* wbl, vpw, lcdac, wbf */
  138. };
  139. #endif /* CONFIG_SHARP_LQ104V7DS01 */
  140. /*----------------------------------------------------------------------*/
  141. #ifdef CONFIG_SHARP_16x9
  142. /*
  143. * Sharp 320x240. Active, color, single scan. It isn't 16x9, and I am
  144. * not sure what it is.......
  145. */
  146. static vidinfo_t panel_info = {
  147. 320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH,
  148. 3, 0, 0, 1, 1, 15, 4, 0, 3
  149. };
  150. #endif /* CONFIG_SHARP_16x9 */
  151. /*----------------------------------------------------------------------*/
  152. #ifdef CONFIG_SHARP_LQ057Q3DC02
  153. /*
  154. * Sharp LQ057Q3DC02 display. Active, color, single scan.
  155. */
  156. #define LCD_DF 12
  157. static vidinfo_t panel_info = {
  158. 320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
  159. 3, 0, 0, 1, 1, 15, 4, 0, 3
  160. /* wbl, vpw, lcdac, wbf */
  161. };
  162. #define LCD_INFO_BELOW_LOGO
  163. #endif /* CONFIG_SHARP_LQ057Q3DC02 */
  164. /*----------------------------------------------------------------------*/
  165. #ifdef CONFIG_SHARP_LQ64D341
  166. /*
  167. * Sharp LQ64D341 display, 640x480. Active, color, single scan.
  168. */
  169. static vidinfo_t panel_info = {
  170. 640, 480, 0, 0, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
  171. 3, 0, 0, 1, 1, 128, 16, 0, 32
  172. /* wbl, vpw, lcdac, wbf */
  173. };
  174. #endif /* CONFIG_SHARP_LQ64D341 */
  175. #ifdef CONFIG_SHARP_LQ084V1DG21
  176. /*
  177. * Sharp LQ084V1DG21 display, 640x480. Active, color, single scan.
  178. */
  179. static vidinfo_t panel_info = {
  180. 640, 480, 171, 129, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_LOW,
  181. 3, 0, 0, 1, 1, 160, 3, 0, 48
  182. /* wbl, vpw, lcdac, wbf */
  183. };
  184. #endif /* CONFIG_SHARP_LQ084V1DG21 */
  185. /*----------------------------------------------------------------------*/
  186. #ifdef CONFIG_HLD1045
  187. /*
  188. * HLD1045 display, 640x480. Active, color, single scan.
  189. */
  190. static vidinfo_t panel_info = {
  191. 640, 480, 0, 0, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
  192. 3, 0, 0, 1, 1, 160, 3, 0, 48
  193. /* wbl, vpw, lcdac, wbf */
  194. };
  195. #endif /* CONFIG_HLD1045 */
  196. /*----------------------------------------------------------------------*/
  197. #ifdef CONFIG_PRIMEVIEW_V16C6448AC
  198. /*
  199. * Prime View V16C6448AC
  200. */
  201. static vidinfo_t panel_info = {
  202. 640, 480, 130, 98, CFG_HIGH, CFG_HIGH, CFG_LOW, CFG_LOW, CFG_HIGH,
  203. 3, 0, 0, 1, 1, 144, 2, 0, 35
  204. /* wbl, vpw, lcdac, wbf */
  205. };
  206. #endif /* CONFIG_PRIMEVIEW_V16C6448AC */
  207. /*----------------------------------------------------------------------*/
  208. #ifdef CONFIG_OPTREX_BW
  209. /*
  210. * Optrex CBL50840-2 NF-FW 99 22 M5
  211. * or
  212. * Hitachi LMG6912RPFC-00T
  213. * or
  214. * Hitachi SP14Q002
  215. *
  216. * 320x240. Black & white.
  217. */
  218. #define OPTREX_BPP 0 /* 0 - monochrome, 1 bpp */
  219. /* 1 - 4 grey levels, 2 bpp */
  220. /* 2 - 16 grey levels, 4 bpp */
  221. static vidinfo_t panel_info = {
  222. 320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_LOW,
  223. OPTREX_BPP, 0, 0, 0, 0, 0, 0, 0, 0, 4
  224. };
  225. #endif /* CONFIG_OPTREX_BW */
  226. /*-----------------------------------------------------------------*/
  227. #ifdef CONFIG_EDT32F10
  228. /*
  229. * Emerging Display Technologies 320x240. Passive, monochrome, single scan.
  230. */
  231. #define LCD_BPP LCD_MONOCHROME
  232. #define LCD_DF 10
  233. static vidinfo_t panel_info = {
  234. 320, 240, 0, 0, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_HIGH, CFG_LOW,
  235. LCD_BPP, 0, 0, 0, 0, 33, 0, 0, 0
  236. };
  237. #endif
  238. /*----------------------------------------------------------------------*/
  239. #if defined(LCD_INFO_BELOW_LOGO)
  240. # define LCD_INFO_X 0
  241. # define LCD_INFO_Y (BMP_LOGO_HEIGHT + VIDEO_FONT_HEIGHT)
  242. #elif defined(CONFIG_LCD_LOGO)
  243. # define LCD_INFO_X (BMP_LOGO_WIDTH + 4 * VIDEO_FONT_WIDTH)
  244. # define LCD_INFO_Y (VIDEO_FONT_HEIGHT)
  245. #else
  246. # define LCD_INFO_X (VIDEO_FONT_WIDTH)
  247. # define LCD_INFO_Y (VIDEO_FONT_HEIGHT)
  248. #endif
  249. #ifndef LCD_BPP
  250. #define LCD_BPP LCD_COLOR8
  251. #endif
  252. #ifndef LCD_DF
  253. #define LCD_DF 1
  254. #endif
  255. #define NBITS(bit_code) (1 << (bit_code))
  256. #define NCOLORS(bit_code) (1 << NBITS(bit_code))
  257. static int lcd_line_length;
  258. static int lcd_color_fg;
  259. static int lcd_color_bg;
  260. static char lcd_is_enabled = 0; /* Indicate that LCD is enabled */
  261. /*
  262. * Frame buffer memory information
  263. */
  264. static void *lcd_base; /* Start of framebuffer memory */
  265. static void *lcd_console_address; /* Start of console buffer */
  266. /************************************************************************/
  267. /* ** CONSOLE CONSTANTS */
  268. /************************************************************************/
  269. #if LCD_BPP == LCD_MONOCHROME
  270. /*
  271. * Simple color definitions
  272. */
  273. #define CONSOLE_COLOR_BLACK 0
  274. #define CONSOLE_COLOR_WHITE 1 /* Must remain last / highest */
  275. #else
  276. /*
  277. * Simple color definitions
  278. */
  279. #define CONSOLE_COLOR_BLACK 0
  280. #define CONSOLE_COLOR_RED 1
  281. #define CONSOLE_COLOR_GREEN 2
  282. #define CONSOLE_COLOR_YELLOW 3
  283. #define CONSOLE_COLOR_BLUE 4
  284. #define CONSOLE_COLOR_MAGENTA 5
  285. #define CONSOLE_COLOR_CYAN 6
  286. #define CONSOLE_COLOR_GREY 14
  287. #define CONSOLE_COLOR_WHITE 15 /* Must remain last / highest */
  288. #endif
  289. #if defined(CONFIG_LCD_LOGO) && (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET)
  290. #error Default Color Map overlaps with Logo Color Map
  291. #endif
  292. /************************************************************************/
  293. #ifndef PAGE_SIZE
  294. #define PAGE_SIZE 4096
  295. #endif
  296. /************************************************************************/
  297. /* ** CONSOLE DEFINITIONS & FUNCTIONS */
  298. /************************************************************************/
  299. #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
  300. #define CONSOLE_ROWS ((panel_info.vl_row-BMP_LOGO_HEIGHT) \
  301. / VIDEO_FONT_HEIGHT)
  302. #else
  303. #define CONSOLE_ROWS (panel_info.vl_row / VIDEO_FONT_HEIGHT)
  304. #endif
  305. #define CONSOLE_COLS (panel_info.vl_col / VIDEO_FONT_WIDTH)
  306. #define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * lcd_line_length)
  307. #define CONSOLE_ROW_FIRST (lcd_console_address)
  308. #define CONSOLE_ROW_SECOND (lcd_console_address + CONSOLE_ROW_SIZE)
  309. #define CONSOLE_ROW_LAST (lcd_console_address + CONSOLE_SIZE \
  310. - CONSOLE_ROW_SIZE)
  311. #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
  312. #define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
  313. #if LCD_BPP == LCD_MONOCHROME
  314. #define COLOR_MASK(c) ((c) | (c) << 1 | (c) << 2 | (c) << 3 | \
  315. (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
  316. #elif LCD_BPP == LCD_COLOR8
  317. #define COLOR_MASK(c) (c)
  318. #else
  319. #error Unsupported LCD BPP.
  320. #endif
  321. static short console_col;
  322. static short console_row;
  323. /************************************************************************/
  324. ulong lcd_setmem (ulong addr);
  325. static void lcd_drawchars (ushort x, ushort y, uchar *str, int count);
  326. static inline void lcd_puts_xy (ushort x, ushort y, uchar *s);
  327. static inline void lcd_putc_xy (ushort x, ushort y, uchar c);
  328. static int lcd_init (void *lcdbase);
  329. static void lcd_ctrl_init (void *lcdbase);
  330. static void lcd_enable (void);
  331. static void *lcd_logo (void);
  332. #if LCD_BPP == LCD_COLOR8
  333. static void lcd_setcolreg (ushort regno,
  334. ushort red, ushort green, ushort blue);
  335. #endif
  336. #if LCD_BPP == LCD_MONOCHROME
  337. static void lcd_initcolregs (void);
  338. #endif
  339. static int lcd_getbgcolor (void);
  340. static void lcd_setfgcolor (int color);
  341. static void lcd_setbgcolor (int color);
  342. #ifdef NOT_USED_SO_FAR
  343. static void lcd_disable (void);
  344. static void lcd_getcolreg (ushort regno,
  345. ushort *red, ushort *green, ushort *blue);
  346. static int lcd_getfgcolor (void);
  347. #endif /* NOT_USED_SO_FAR */
  348. /************************************************************************/
  349. /*----------------------------------------------------------------------*/
  350. static void console_scrollup (void)
  351. {
  352. #if 1
  353. /* Copy up rows ignoring the first one */
  354. memcpy (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE);
  355. /* Clear the last one */
  356. memset (CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
  357. #else
  358. /*
  359. * Poor attempt to optimize speed by moving "long"s.
  360. * But the code is ugly, and not a bit faster :-(
  361. */
  362. ulong *t = (ulong *)CONSOLE_ROW_FIRST;
  363. ulong *s = (ulong *)CONSOLE_ROW_SECOND;
  364. ulong l = CONSOLE_SCROLL_SIZE / sizeof(ulong);
  365. uchar c = lcd_color_bg & 0xFF;
  366. ulong val= (c<<24) | (c<<16) | (c<<8) | c;
  367. while (l--)
  368. *t++ = *s++;
  369. t = (ulong *)CONSOLE_ROW_LAST;
  370. l = CONSOLE_ROW_SIZE / sizeof(ulong);
  371. while (l-- > 0)
  372. *t++ = val;
  373. #endif
  374. }
  375. /*----------------------------------------------------------------------*/
  376. static inline void console_back (void)
  377. {
  378. if (--console_col < 0) {
  379. console_col = CONSOLE_COLS-1 ;
  380. if (--console_row < 0) {
  381. console_row = 0;
  382. }
  383. }
  384. lcd_putc_xy (console_col * VIDEO_FONT_WIDTH,
  385. console_row * VIDEO_FONT_HEIGHT,
  386. ' ');
  387. }
  388. /*----------------------------------------------------------------------*/
  389. static inline void console_newline (void)
  390. {
  391. ++console_row;
  392. console_col = 0;
  393. /* Check if we need to scroll the terminal */
  394. if (console_row >= CONSOLE_ROWS) {
  395. /* Scroll everything up */
  396. console_scrollup () ;
  397. --console_row;
  398. }
  399. }
  400. /*----------------------------------------------------------------------*/
  401. void lcd_putc (const char c)
  402. {
  403. if (!lcd_is_enabled) {
  404. serial_putc(c);
  405. return;
  406. }
  407. switch (c) {
  408. case '\r': console_col = 0;
  409. return;
  410. case '\n': console_newline();
  411. return;
  412. case '\t': /* Tab (8 chars alignment) */
  413. console_col |= 8;
  414. console_col &= ~7;
  415. if (console_col >= CONSOLE_COLS) {
  416. console_newline();
  417. }
  418. return;
  419. case '\b': console_back();
  420. return;
  421. default: lcd_putc_xy (console_col * VIDEO_FONT_WIDTH,
  422. console_row * VIDEO_FONT_HEIGHT,
  423. c);
  424. if (++console_col >= CONSOLE_COLS) {
  425. console_newline();
  426. }
  427. return;
  428. }
  429. /* NOTREACHED */
  430. }
  431. /*----------------------------------------------------------------------*/
  432. void lcd_puts (const char *s)
  433. {
  434. if (!lcd_is_enabled) {
  435. serial_puts (s);
  436. return;
  437. }
  438. while (*s) {
  439. lcd_putc (*s++);
  440. }
  441. }
  442. /************************************************************************/
  443. /* ** Low-Level Graphics Routines */
  444. /************************************************************************/
  445. static void lcd_drawchars (ushort x, ushort y, uchar *str, int count)
  446. {
  447. uchar *dest;
  448. ushort off, row;
  449. dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
  450. off = x * (1 << LCD_BPP) % 8;
  451. for (row=0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
  452. uchar *s = str;
  453. uchar *d = dest;
  454. int i;
  455. #if LCD_BPP == LCD_MONOCHROME
  456. uchar rest = *d & -(1 << (8-off));
  457. uchar sym;
  458. #endif
  459. for (i=0; i<count; ++i) {
  460. uchar c, bits;
  461. c = *s++;
  462. bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
  463. #if LCD_BPP == LCD_MONOCHROME
  464. sym = (COLOR_MASK(lcd_color_fg) & bits) |
  465. (COLOR_MASK(lcd_color_bg) & ~bits);
  466. *d++ = rest | (sym >> off);
  467. rest = sym << (8-off);
  468. #elif LCD_BPP == LCD_COLOR8
  469. for (c=0; c<8; ++c) {
  470. *d++ = (bits & 0x80) ?
  471. lcd_color_fg : lcd_color_bg;
  472. bits <<= 1;
  473. }
  474. #endif
  475. }
  476. #if LCD_BPP == LCD_MONOCHROME
  477. *d = rest | (*d & ((1 << (8-off)) - 1));
  478. #endif
  479. }
  480. }
  481. /*----------------------------------------------------------------------*/
  482. static inline void lcd_puts_xy (ushort x, ushort y, uchar *s)
  483. {
  484. #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
  485. lcd_drawchars (x, y+BMP_LOGO_HEIGHT, s, strlen (s));
  486. #else
  487. lcd_drawchars (x, y, s, strlen (s));
  488. #endif
  489. }
  490. /*----------------------------------------------------------------------*/
  491. static inline void lcd_putc_xy (ushort x, ushort y, uchar c)
  492. {
  493. #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
  494. lcd_drawchars (x, y+BMP_LOGO_HEIGHT, &c, 1);
  495. #else
  496. lcd_drawchars (x, y, &c, 1);
  497. #endif
  498. }
  499. /************************************************************************/
  500. /** Small utility to check that you got the colours right */
  501. /************************************************************************/
  502. #ifdef LCD_TEST_PATTERN
  503. #define N_BLK_VERT 2
  504. #define N_BLK_HOR 3
  505. static int test_colors[N_BLK_HOR*N_BLK_VERT] = {
  506. CONSOLE_COLOR_RED, CONSOLE_COLOR_GREEN, CONSOLE_COLOR_YELLOW,
  507. CONSOLE_COLOR_BLUE, CONSOLE_COLOR_MAGENTA, CONSOLE_COLOR_CYAN,
  508. };
  509. static void test_pattern (void)
  510. {
  511. ushort v_max = panel_info.vl_row;
  512. ushort h_max = panel_info.vl_col;
  513. ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT;
  514. ushort h_step = (h_max + N_BLK_HOR - 1) / N_BLK_HOR;
  515. ushort v, h;
  516. uchar *pix = (uchar *)lcd_base;
  517. printf ("[LCD] Test Pattern: %d x %d [%d x %d]\n",
  518. h_max, v_max, h_step, v_step);
  519. /* WARNING: Code silently assumes 8bit/pixel */
  520. for (v=0; v<v_max; ++v) {
  521. uchar iy = v / v_step;
  522. for (h=0; h<h_max; ++h) {
  523. uchar ix = N_BLK_HOR * iy + (h/h_step);
  524. *pix++ = test_colors[ix];
  525. }
  526. }
  527. }
  528. #endif /* LCD_TEST_PATTERN */
  529. /************************************************************************/
  530. /* ** GENERIC Initialization Routines */
  531. /************************************************************************/
  532. int drv_lcd_init (void)
  533. {
  534. DECLARE_GLOBAL_DATA_PTR;
  535. device_t lcddev;
  536. int rc;
  537. lcd_base = (void *)(gd->fb_base);
  538. lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
  539. lcd_init (lcd_base); /* LCD initialization */
  540. /* Device initialization */
  541. memset (&lcddev, 0, sizeof (lcddev));
  542. strcpy (lcddev.name, "lcd");
  543. lcddev.ext = 0; /* No extensions */
  544. lcddev.flags = DEV_FLAGS_OUTPUT; /* Output only */
  545. lcddev.putc = lcd_putc; /* 'putc' function */
  546. lcddev.puts = lcd_puts; /* 'puts' function */
  547. rc = device_register (&lcddev);
  548. return (rc == 0) ? 1 : rc;
  549. }
  550. /*----------------------------------------------------------------------*/
  551. static int lcd_init (void *lcdbase)
  552. {
  553. /* Initialize the lcd controller */
  554. debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
  555. lcd_ctrl_init (lcdbase);
  556. #if LCD_BPP == LCD_MONOCHROME
  557. /* Setting the palette */
  558. lcd_initcolregs();
  559. #elif LCD_BPP == LCD_COLOR8
  560. /* Setting the palette */
  561. lcd_setcolreg (CONSOLE_COLOR_BLACK, 0, 0, 0);
  562. lcd_setcolreg (CONSOLE_COLOR_RED, 0xFF, 0, 0);
  563. lcd_setcolreg (CONSOLE_COLOR_GREEN, 0, 0xFF, 0);
  564. lcd_setcolreg (CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0);
  565. lcd_setcolreg (CONSOLE_COLOR_BLUE, 0, 0, 0xFF);
  566. lcd_setcolreg (CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF);
  567. lcd_setcolreg (CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF);
  568. lcd_setcolreg (CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA);
  569. lcd_setcolreg (CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF);
  570. #endif
  571. #ifndef CFG_WHITE_ON_BLACK
  572. lcd_setfgcolor (CONSOLE_COLOR_BLACK);
  573. lcd_setbgcolor (CONSOLE_COLOR_WHITE);
  574. #else
  575. lcd_setfgcolor (CONSOLE_COLOR_WHITE);
  576. lcd_setbgcolor (CONSOLE_COLOR_BLACK);
  577. #endif /* CFG_WHITE_ON_BLACK */
  578. #ifdef LCD_TEST_PATTERN
  579. test_pattern();
  580. #else
  581. /* set framebuffer to background color */
  582. memset ((char *)lcd_base,
  583. COLOR_MASK(lcd_getbgcolor()),
  584. lcd_line_length*panel_info.vl_row);
  585. #endif
  586. lcd_enable ();
  587. /* Paint the logo and retrieve LCD base address */
  588. debug ("[LCD] Drawing the logo...\n");
  589. lcd_console_address = lcd_logo ();
  590. /* Initialize the console */
  591. console_col = 0;
  592. #ifdef LCD_INFO_BELOW_LOGO
  593. console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
  594. #else
  595. console_row = 1; /* leave 1 blank line below logo */
  596. #endif
  597. lcd_is_enabled = 1;
  598. return 0;
  599. }
  600. /************************************************************************/
  601. /* ** ROM capable initialization part - needed to reserve FB memory */
  602. /************************************************************************/
  603. /*
  604. * This is called early in the system initialization to grab memory
  605. * for the LCD controller.
  606. * Returns new address for monitor, after reserving LCD buffer memory
  607. *
  608. * Note that this is running from ROM, so no write access to global data.
  609. */
  610. ulong lcd_setmem (ulong addr)
  611. {
  612. ulong size;
  613. int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
  614. debug ("LCD panel info: %d x %d, %d bit/pix\n",
  615. panel_info.vl_col, panel_info.vl_row, NBITS (panel_info.vl_bpix) );
  616. size = line_length * panel_info.vl_row;
  617. /* Round up to nearest full page */
  618. size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
  619. /* Allocate pages for the frame buffer. */
  620. addr -= size;
  621. debug ("Reserving %ldk for LCD Framebuffer at: %08lx\n", size>>10, addr);
  622. return (addr);
  623. }
  624. /************************************************************************/
  625. /* ----------------- chipset specific functions ----------------------- */
  626. /************************************************************************/
  627. static void lcd_ctrl_init (void *lcdbase)
  628. {
  629. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  630. volatile lcd823_t *lcdp = &immr->im_lcd;
  631. uint lccrtmp;
  632. /* Initialize the LCD control register according to the LCD
  633. * parameters defined. We do everything here but enable
  634. * the controller.
  635. */
  636. lccrtmp = LCDBIT (LCCR_BNUM_BIT,
  637. (((panel_info.vl_row * panel_info.vl_col) * (1 << LCD_BPP)) / 128));
  638. lccrtmp |= LCDBIT (LCCR_CLKP_BIT, panel_info.vl_clkp) |
  639. LCDBIT (LCCR_OEP_BIT, panel_info.vl_oep) |
  640. LCDBIT (LCCR_HSP_BIT, panel_info.vl_hsp) |
  641. LCDBIT (LCCR_VSP_BIT, panel_info.vl_vsp) |
  642. LCDBIT (LCCR_DP_BIT, panel_info.vl_dp) |
  643. LCDBIT (LCCR_BPIX_BIT, panel_info.vl_bpix) |
  644. LCDBIT (LCCR_LBW_BIT, panel_info.vl_lbw) |
  645. LCDBIT (LCCR_SPLT_BIT, panel_info.vl_splt) |
  646. LCDBIT (LCCR_CLOR_BIT, panel_info.vl_clor) |
  647. LCDBIT (LCCR_TFT_BIT, panel_info.vl_tft);
  648. #if 0
  649. lccrtmp |= ((SIU_LEVEL5 / 2) << 12);
  650. lccrtmp |= LCCR_EIEN;
  651. #endif
  652. lcdp->lcd_lccr = lccrtmp;
  653. lcdp->lcd_lcsr = 0xFF; /* Clear pending interrupts */
  654. /* Initialize LCD controller bus priorities.
  655. */
  656. immr->im_siu_conf.sc_sdcr &= ~0x0f; /* RAID = LAID = 0 */
  657. /* set SHFT/CLOCK division factor 4
  658. * This needs to be set based upon display type and processor
  659. * speed. The TFT displays run about 20 to 30 MHz.
  660. * I was running 64 MHz processor speed.
  661. * The value for this divider must be chosen so the result is
  662. * an integer of the processor speed (i.e., divide by 3 with
  663. * 64 MHz would be bad).
  664. */
  665. immr->im_clkrst.car_sccr &= ~0x1F;
  666. immr->im_clkrst.car_sccr |= LCD_DF; /* was 8 */
  667. #ifndef CONFIG_EDT32F10
  668. /* Enable LCD on port D.
  669. */
  670. immr->im_ioport.iop_pdpar |= 0x1FFF;
  671. immr->im_ioport.iop_pddir |= 0x1FFF;
  672. /* Enable LCD_A/B/C on port B.
  673. */
  674. immr->im_cpm.cp_pbpar |= 0x00005001;
  675. immr->im_cpm.cp_pbdir |= 0x00005001;
  676. #else
  677. /* Enable LCD on port D.
  678. */
  679. immr->im_ioport.iop_pdpar |= 0x1DFF;
  680. immr->im_ioport.iop_pdpar &= ~0x0200;
  681. immr->im_ioport.iop_pddir |= 0x1FFF;
  682. immr->im_ioport.iop_pddat |= 0x0200;
  683. #endif
  684. /* Load the physical address of the linear frame buffer
  685. * into the LCD controller.
  686. * BIG NOTE: This has to be modified to load A and B depending
  687. * upon the split mode of the LCD.
  688. */
  689. lcdp->lcd_lcfaa = (ulong)lcd_base;
  690. lcdp->lcd_lcfba = (ulong)lcd_base;
  691. /* MORE HACKS...This must be updated according to 823 manual
  692. * for different panels.
  693. */
  694. #ifndef CONFIG_EDT32F10
  695. lcdp->lcd_lchcr = LCHCR_BO |
  696. LCDBIT (LCHCR_AT_BIT, 4) |
  697. LCDBIT (LCHCR_HPC_BIT, panel_info.vl_col) |
  698. panel_info.vl_wbl;
  699. #else
  700. lcdp->lcd_lchcr = LCHCR_BO |
  701. LCDBIT (LCHCR_AT_BIT, 4) |
  702. LCDBIT (LCHCR_HPC_BIT, panel_info.vl_col/4) |
  703. panel_info.vl_wbl;
  704. #endif
  705. lcdp->lcd_lcvcr = LCDBIT (LCVCR_VPW_BIT, panel_info.vl_vpw) |
  706. LCDBIT (LCVCR_LCD_AC_BIT, panel_info.vl_lcdac) |
  707. LCDBIT (LCVCR_VPC_BIT, panel_info.vl_row) |
  708. panel_info.vl_wbf;
  709. }
  710. /*----------------------------------------------------------------------*/
  711. #ifdef NOT_USED_SO_FAR
  712. static void
  713. lcd_getcolreg (ushort regno, ushort *red, ushort *green, ushort *blue)
  714. {
  715. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  716. volatile cpm8xx_t *cp = &(immr->im_cpm);
  717. unsigned short colreg, *cmap_ptr;
  718. cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2];
  719. colreg = *cmap_ptr;
  720. #ifdef CFG_INVERT_COLORS
  721. colreg ^= 0x0FFF;
  722. #endif
  723. *red = (colreg >> 8) & 0x0F;
  724. *green = (colreg >> 4) & 0x0F;
  725. *blue = colreg & 0x0F;
  726. }
  727. #endif /* NOT_USED_SO_FAR */
  728. /*----------------------------------------------------------------------*/
  729. #if LCD_BPP == LCD_COLOR8
  730. static void
  731. lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue)
  732. {
  733. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  734. volatile cpm8xx_t *cp = &(immr->im_cpm);
  735. unsigned short colreg, *cmap_ptr;
  736. cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2];
  737. colreg = ((red & 0x0F) << 8) |
  738. ((green & 0x0F) << 4) |
  739. (blue & 0x0F) ;
  740. #ifdef CFG_INVERT_COLORS
  741. colreg ^= 0x0FFF;
  742. #endif
  743. *cmap_ptr = colreg;
  744. debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %02X%02X\n",
  745. regno, &(cp->lcd_cmap[regno * 2]),
  746. red, green, blue,
  747. cp->lcd_cmap[ regno * 2 ], cp->lcd_cmap[(regno * 2) + 1]);
  748. }
  749. #endif /* LCD_COLOR8 */
  750. /*----------------------------------------------------------------------*/
  751. #if LCD_BPP == LCD_MONOCHROME
  752. static
  753. void lcd_initcolregs (void)
  754. {
  755. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  756. volatile cpm8xx_t *cp = &(immr->im_cpm);
  757. ushort regno;
  758. for (regno = 0; regno < 16; regno++) {
  759. cp->lcd_cmap[regno * 2] = 0;
  760. cp->lcd_cmap[(regno * 2) + 1] = regno & 0x0f;
  761. }
  762. }
  763. #endif
  764. /*----------------------------------------------------------------------*/
  765. static void lcd_setfgcolor (int color)
  766. {
  767. lcd_color_fg = color & 0x0F;
  768. }
  769. /*----------------------------------------------------------------------*/
  770. static void lcd_setbgcolor (int color)
  771. {
  772. lcd_color_bg = color & 0x0F;
  773. }
  774. /*----------------------------------------------------------------------*/
  775. #ifdef NOT_USED_SO_FAR
  776. static int lcd_getfgcolor (void)
  777. {
  778. return lcd_color_fg;
  779. }
  780. #endif /* NOT_USED_SO_FAR */
  781. /*----------------------------------------------------------------------*/
  782. static int lcd_getbgcolor (void)
  783. {
  784. return lcd_color_bg;
  785. }
  786. /*----------------------------------------------------------------------*/
  787. static void lcd_enable (void)
  788. {
  789. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  790. volatile lcd823_t *lcdp = &immr->im_lcd;
  791. /* Enable the LCD panel */
  792. immr->im_siu_conf.sc_sdcr |= (1 << (31 - 25)); /* LAM = 1 */
  793. lcdp->lcd_lccr |= LCCR_PON;
  794. #ifdef CONFIG_V37
  795. /* Turn on display backlight */
  796. immr->im_cpm.cp_pbpar |= 0x00008000;
  797. immr->im_cpm.cp_pbdir |= 0x00008000;
  798. #endif
  799. #if defined(CONFIG_LWMON)
  800. { uchar c = pic_read (0x60);
  801. c |= 0x07; /* Power on CCFL, Enable CCFL, Chip Enable LCD */
  802. pic_write (0x60, c);
  803. }
  804. #endif /* CONFIG_LWMON */
  805. #if defined(CONFIG_R360MPI)
  806. {
  807. extern void r360_i2c_lcd_write (uchar data0, uchar data1);
  808. r360_i2c_lcd_write(0x10, 0x01);
  809. r360_i2c_lcd_write(0x20, 0x01);
  810. r360_i2c_lcd_write(0x3F, 0xFF);
  811. r360_i2c_lcd_write(0x47, 0xFF);
  812. }
  813. #endif /* CONFIG_R360MPI */
  814. }
  815. /*----------------------------------------------------------------------*/
  816. #ifdef NOT_USED_SO_FAR
  817. static void lcd_disable (void)
  818. {
  819. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  820. volatile lcd823_t *lcdp = &immr->im_lcd;
  821. #if defined(CONFIG_LWMON)
  822. { uchar c = pic_read (0x60);
  823. c &= ~0x07; /* Power off CCFL, Disable CCFL, Chip Disable LCD */
  824. pic_write (0x60, c);
  825. }
  826. #elif defined(CONFIG_R360MPI)
  827. {
  828. extern void r360_i2c_lcd_write (uchar data0, uchar data1);
  829. r360_i2c_lcd_write(0x10, 0x00);
  830. r360_i2c_lcd_write(0x20, 0x00);
  831. r360_i2c_lcd_write(0x30, 0x00);
  832. r360_i2c_lcd_write(0x40, 0x00);
  833. }
  834. #endif /* CONFIG_LWMON */
  835. /* Disable the LCD panel */
  836. lcdp->lcd_lccr &= ~LCCR_PON;
  837. immr->im_siu_conf.sc_sdcr &= ~(1 << (31 - 25)); /* LAM = 0 */
  838. }
  839. #endif /* NOT_USED_SO_FAR */
  840. /************************************************************************/
  841. /* ** Chipset depending Bitmap / Logo stuff... */
  842. /************************************************************************/
  843. #ifdef CONFIG_LCD_LOGO
  844. static void bitmap_plot (int x, int y)
  845. {
  846. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  847. volatile cpm8xx_t *cp = &(immr->im_cpm);
  848. ushort *cmap;
  849. ushort i;
  850. uchar *bmap;
  851. uchar *fb;
  852. debug ("Logo: width %d height %d colors %d cmap %d\n",
  853. BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,
  854. sizeof(bmp_logo_palette)/(sizeof(ushort))
  855. );
  856. /* Leave room for default color map */
  857. cmap = (ushort *)&(cp->lcd_cmap[BMP_LOGO_OFFSET*sizeof(ushort)]);
  858. /* Set color map */
  859. for (i=0; i<(sizeof(bmp_logo_palette)/(sizeof(ushort))); ++i) {
  860. ushort colreg = bmp_logo_palette[i];
  861. #ifdef CFG_INVERT_COLORS
  862. colreg ^= 0xFFF;
  863. #endif
  864. *cmap++ = colreg;
  865. }
  866. bmap = &bmp_logo_bitmap[0];
  867. fb = (char *)(lcd_base + y * lcd_line_length + x);
  868. for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
  869. memcpy (fb, bmap, BMP_LOGO_WIDTH);
  870. bmap += BMP_LOGO_WIDTH;
  871. fb += panel_info.vl_col;
  872. }
  873. }
  874. #endif /* CONFIG_LCD_LOGO */
  875. /*----------------------------------------------------------------------*/
  876. static void *lcd_logo (void)
  877. {
  878. #ifdef LCD_INFO
  879. DECLARE_GLOBAL_DATA_PTR;
  880. char info[80];
  881. char temp[32];
  882. #endif /* LCD_INFO */
  883. #ifdef CONFIG_LCD_LOGO
  884. bitmap_plot (0, 0);
  885. #endif /* CONFIG_LCD_LOGO */
  886. #ifdef LCD_INFO
  887. sprintf (info, "%s (%s - %s) ", U_BOOT_VERSION, __DATE__, __TIME__);
  888. lcd_drawchars (LCD_INFO_X, LCD_INFO_Y, info, strlen(info));
  889. sprintf (info, "(C) 2002 DENX Software Engineering");
  890. lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT,
  891. info, strlen(info));
  892. sprintf (info, " Wolfgang DENK, wd@denx.de");
  893. lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 2,
  894. info, strlen(info));
  895. #ifdef LCD_INFO_BELOW_LOGO
  896. sprintf (info, "MPC823 CPU at %s MHz",
  897. strmhz(temp, gd->cpu_clk));
  898. lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 3,
  899. info, strlen(info));
  900. sprintf (info, " %ld MB RAM, %ld MB Flash",
  901. gd->ram_size >> 20,
  902. gd->bd->bi_flashsize >> 20 );
  903. lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
  904. info, strlen(info));
  905. #else
  906. /* leave one blank line */
  907. sprintf (info, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
  908. strmhz(temp, gd->cpu_clk),
  909. gd->ram_size >> 20,
  910. gd->bd->bi_flashsize >> 20 );
  911. lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
  912. info, strlen(info));
  913. #endif /* LCD_INFO_BELOW_LOGO */
  914. #endif /* LCD_INFO */
  915. #if defined(CONFIG_LCD_LOGO) && !defined(LCD_INFO_BELOW_LOGO)
  916. return ((void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length));
  917. #else
  918. return ((void *)lcd_base);
  919. #endif /* CONFIG_LCD_LOGO */
  920. }
  921. /************************************************************************/
  922. /************************************************************************/
  923. #endif /* CONFIG_LCD */