cfb_console.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259
  1. /*
  2. * (C) Copyright 2002 ELTEC Elektronik AG
  3. * Frank Gottschling <fgottschling@eltec.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. * cfb_console.c
  25. *
  26. * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
  27. *
  28. * At the moment only the 8x16 font is tested and the font fore- and
  29. * background color is limited to black/white/gray colors. The Linux
  30. * logo can be placed in the upper left corner and additional board
  31. * information strings (that normally goes to serial port) can be drawn.
  32. *
  33. * The console driver can use the standard PC keyboard interface (i8042)
  34. * for character input. Character output goes to a memory mapped video
  35. * framebuffer with little or big-endian organisation.
  36. * With environment setting 'console=serial' the console i/o can be
  37. * forced to serial port.
  38. *
  39. * The driver uses graphic specific defines/parameters/functions:
  40. *
  41. * (for SMI LynxE graphic chip)
  42. *
  43. * CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810
  44. * VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian
  45. * VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill
  46. * VIDEO_HW_BITBLT - graphic driver supports hardware bit blt
  47. *
  48. * Console Parameters are set by graphic drivers global struct:
  49. *
  50. * VIDEO_VISIBLE_COLS - x resolution
  51. * VIDEO_VISIBLE_ROWS - y resolution
  52. * VIDEO_PIXEL_SIZE - storage size in byte per pixel
  53. * VIDEO_DATA_FORMAT - graphical data format GDF
  54. * VIDEO_FB_ADRS - start of video memory
  55. *
  56. * CONFIG_I8042_KBD - AT Keyboard driver for i8042
  57. * VIDEO_KBD_INIT_FCT - init function for keyboard
  58. * VIDEO_TSTC_FCT - keyboard_tstc function
  59. * VIDEO_GETC_FCT - keyboard_getc function
  60. *
  61. * CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with
  62. * delay loop in VIDEO_TSTC_FCT (i8042)
  63. *
  64. * CONFIG_SYS_CONSOLE_BLINK_COUNT - value for delay loop - blink rate
  65. * CONFIG_CONSOLE_TIME - display time/date in upper right
  66. * corner, needs CONFIG_CMD_DATE and
  67. * CONFIG_CONSOLE_CURSOR
  68. * CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner.
  69. * Use CONFIG_SPLASH_SCREEN_ALIGN with
  70. * environment variable "splashpos" to place
  71. * the logo on other position. In this case
  72. * no CONSOLE_EXTRA_INFO is possible.
  73. * CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
  74. * CONFIG_CONSOLE_EXTRA_INFO - display additional board information
  75. * strings that normaly goes to serial
  76. * port. This define requires a board
  77. * specific function:
  78. * video_drawstring (VIDEO_INFO_X,
  79. * VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
  80. * info);
  81. * that fills a info buffer at i=row.
  82. * s.a: board/eltec/bab7xx.
  83. * CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be
  84. * initialized as an output only device.
  85. * The Keyboard driver will not be
  86. * set-up. This may be used, if you have
  87. * no or more than one Keyboard devices
  88. * (USB Keyboard, AT Keyboard).
  89. *
  90. * CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last
  91. * character. No blinking is provided.
  92. * Uses the macros CURSOR_SET and
  93. * CURSOR_OFF.
  94. *
  95. * CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability
  96. * of the graphic chip. Uses the macro
  97. * CURSOR_SET. ATTENTION: If booting an
  98. * OS, the display driver must disable
  99. * the hardware register of the graphic
  100. * chip. Otherwise a blinking field is
  101. * displayed.
  102. */
  103. #include <common.h>
  104. #include <version.h>
  105. #include <malloc.h>
  106. #include <linux/compiler.h>
  107. /*
  108. * Console device defines with SMI graphic
  109. * Any other graphic must change this section
  110. */
  111. #ifdef CONFIG_VIDEO_SMI_LYNXEM
  112. #define VIDEO_FB_LITTLE_ENDIAN
  113. #define VIDEO_HW_RECTFILL
  114. #define VIDEO_HW_BITBLT
  115. #endif
  116. /*
  117. * Defines for the CT69000 driver
  118. */
  119. #ifdef CONFIG_VIDEO_CT69000
  120. #define VIDEO_FB_LITTLE_ENDIAN
  121. #define VIDEO_HW_RECTFILL
  122. #define VIDEO_HW_BITBLT
  123. #endif
  124. /*
  125. * Defines for the SED13806 driver
  126. */
  127. #ifdef CONFIG_VIDEO_SED13806
  128. #ifndef CONFIG_TOTAL5200
  129. #define VIDEO_FB_LITTLE_ENDIAN
  130. #endif
  131. #define VIDEO_HW_RECTFILL
  132. #define VIDEO_HW_BITBLT
  133. #endif
  134. /*
  135. * Defines for the SED13806 driver
  136. */
  137. #ifdef CONFIG_VIDEO_SM501
  138. #ifdef CONFIG_HH405
  139. #define VIDEO_FB_LITTLE_ENDIAN
  140. #endif
  141. #endif
  142. /*
  143. * Defines for the MB862xx driver
  144. */
  145. #ifdef CONFIG_VIDEO_MB862xx
  146. #ifdef CONFIG_VIDEO_CORALP
  147. #define VIDEO_FB_LITTLE_ENDIAN
  148. #endif
  149. #ifdef CONFIG_VIDEO_MB862xx_ACCEL
  150. #define VIDEO_HW_RECTFILL
  151. #define VIDEO_HW_BITBLT
  152. #endif
  153. #endif
  154. /*
  155. * Defines for the i.MX31 driver (mx3fb.c)
  156. */
  157. #if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
  158. #define VIDEO_FB_16BPP_WORD_SWAP
  159. #endif
  160. /*
  161. * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
  162. */
  163. #include <video_fb.h>
  164. /*
  165. * some Macros
  166. */
  167. #define VIDEO_VISIBLE_COLS (pGD->winSizeX)
  168. #define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
  169. #define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
  170. #define VIDEO_DATA_FORMAT (pGD->gdfIndex)
  171. #define VIDEO_FB_ADRS (pGD->frameAdrs)
  172. /*
  173. * Console device defines with i8042 keyboard controller
  174. * Any other keyboard controller must change this section
  175. */
  176. #ifdef CONFIG_I8042_KBD
  177. #include <i8042.h>
  178. #define VIDEO_KBD_INIT_FCT i8042_kbd_init()
  179. #define VIDEO_TSTC_FCT i8042_tstc
  180. #define VIDEO_GETC_FCT i8042_getc
  181. #endif
  182. /*
  183. * Console device
  184. */
  185. #include <version.h>
  186. #include <linux/types.h>
  187. #include <stdio_dev.h>
  188. #include <video_font.h>
  189. #include <video_font_data.h>
  190. #if defined(CONFIG_CMD_DATE)
  191. #include <rtc.h>
  192. #endif
  193. #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
  194. #include <watchdog.h>
  195. #include <bmp_layout.h>
  196. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  197. #define BMP_ALIGN_CENTER 0x7FFF
  198. #endif
  199. #endif
  200. /*
  201. * Cursor definition:
  202. * CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/input/i8042.c)
  203. * to let the cursor blink. Uses the macros
  204. * CURSOR_OFF and CURSOR_ON.
  205. * CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No
  206. * blinking is provided. Uses the macros CURSOR_SET
  207. * and CURSOR_OFF.
  208. * CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the
  209. * graphic chip. Uses the macro CURSOR_SET.
  210. * ATTENTION: If booting an OS, the display driver
  211. * must disable the hardware register of the graphic
  212. * chip. Otherwise a blinking field is displayed
  213. */
  214. #if !defined(CONFIG_CONSOLE_CURSOR) && \
  215. !defined(CONFIG_VIDEO_SW_CURSOR) && \
  216. !defined(CONFIG_VIDEO_HW_CURSOR)
  217. /* no Cursor defined */
  218. #define CURSOR_ON
  219. #define CURSOR_OFF
  220. #define CURSOR_SET
  221. #endif
  222. #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
  223. #if defined(CURSOR_ON) || \
  224. (defined(CONFIG_CONSOLE_CURSOR) && defined(CONFIG_VIDEO_SW_CURSOR))
  225. #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
  226. or CONFIG_VIDEO_HW_CURSOR can be defined
  227. #endif
  228. void console_cursor(int state);
  229. #define CURSOR_ON console_cursor(1)
  230. #define CURSOR_OFF console_cursor(0)
  231. #define CURSOR_SET video_set_cursor()
  232. #endif /* CONFIG_CONSOLE_CURSOR || CONFIG_VIDEO_SW_CURSOR */
  233. #ifdef CONFIG_CONSOLE_CURSOR
  234. #ifndef CONFIG_CONSOLE_TIME
  235. #error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
  236. #endif
  237. #ifndef CONFIG_I8042_KBD
  238. #warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
  239. #endif
  240. #endif /* CONFIG_CONSOLE_CURSOR */
  241. #ifdef CONFIG_VIDEO_HW_CURSOR
  242. #ifdef CURSOR_ON
  243. #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
  244. or CONFIG_VIDEO_HW_CURSOR can be defined
  245. #endif
  246. #define CURSOR_ON
  247. #define CURSOR_OFF
  248. #define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
  249. (console_row * VIDEO_FONT_HEIGHT) + video_logo_height)
  250. #endif /* CONFIG_VIDEO_HW_CURSOR */
  251. #ifdef CONFIG_VIDEO_LOGO
  252. #ifdef CONFIG_VIDEO_BMP_LOGO
  253. #include <bmp_logo.h>
  254. #include <bmp_logo_data.h>
  255. #define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH
  256. #define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT
  257. #define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET
  258. #define VIDEO_LOGO_COLORS BMP_LOGO_COLORS
  259. #else /* CONFIG_VIDEO_BMP_LOGO */
  260. #define LINUX_LOGO_WIDTH 80
  261. #define LINUX_LOGO_HEIGHT 80
  262. #define LINUX_LOGO_COLORS 214
  263. #define LINUX_LOGO_LUT_OFFSET 0x20
  264. #define __initdata
  265. #include <linux_logo.h>
  266. #define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
  267. #define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
  268. #define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
  269. #define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
  270. #endif /* CONFIG_VIDEO_BMP_LOGO */
  271. #define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
  272. #define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
  273. #else /* CONFIG_VIDEO_LOGO */
  274. #define VIDEO_LOGO_WIDTH 0
  275. #define VIDEO_LOGO_HEIGHT 0
  276. #endif /* CONFIG_VIDEO_LOGO */
  277. #define VIDEO_COLS VIDEO_VISIBLE_COLS
  278. #define VIDEO_ROWS VIDEO_VISIBLE_ROWS
  279. #define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
  280. #define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2)
  281. #define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE)
  282. #define VIDEO_BURST_LEN (VIDEO_COLS/8)
  283. #ifdef CONFIG_VIDEO_LOGO
  284. #define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
  285. #else
  286. #define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
  287. #endif
  288. #define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
  289. #define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
  290. #define CONSOLE_ROW_FIRST (video_console_address)
  291. #define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
  292. #define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
  293. #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
  294. #define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
  295. /* Macros */
  296. #ifdef VIDEO_FB_LITTLE_ENDIAN
  297. #define SWAP16(x) ((((x) & 0x00ff) << 8) | \
  298. ((x) >> 8) \
  299. )
  300. #define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
  301. (((x) & 0x0000ff00) << 8) | \
  302. (((x) & 0x00ff0000) >> 8) | \
  303. (((x) & 0xff000000) >> 24) \
  304. )
  305. #define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
  306. (((x) & 0x0000ff00) >> 8) | \
  307. (((x) & 0x00ff0000) << 8) | \
  308. (((x) & 0xff000000) >> 8) \
  309. )
  310. #else
  311. #define SWAP16(x) (x)
  312. #define SWAP32(x) (x)
  313. #if defined(VIDEO_FB_16BPP_WORD_SWAP)
  314. #define SHORTSWAP32(x) (((x) >> 16) | ((x) << 16))
  315. #else
  316. #define SHORTSWAP32(x) (x)
  317. #endif
  318. #endif
  319. #ifdef CONFIG_CONSOLE_EXTRA_INFO
  320. /*
  321. * setup a board string: type, speed, etc.
  322. *
  323. * line_number: location to place info string beside logo
  324. * info: buffer for info string
  325. */
  326. extern void video_get_info_str(int line_number, char *info);
  327. #endif
  328. DECLARE_GLOBAL_DATA_PTR;
  329. /* Locals */
  330. static GraphicDevice *pGD; /* Pointer to Graphic array */
  331. static void *video_fb_address; /* frame buffer address */
  332. static void *video_console_address; /* console buffer start address */
  333. static int video_logo_height = VIDEO_LOGO_HEIGHT;
  334. static int __maybe_unused cursor_state;
  335. static int __maybe_unused old_col;
  336. static int __maybe_unused old_row;
  337. static int console_col; /* cursor col */
  338. static int console_row; /* cursor row */
  339. static u32 eorx, fgx, bgx; /* color pats */
  340. static int cfb_do_flush_cache;
  341. #ifdef CONFIG_CFB_CONSOLE_ANSI
  342. static char ansi_buf[10];
  343. static int ansi_buf_size;
  344. static int ansi_colors_need_revert;
  345. static int ansi_cursor_hidden;
  346. #endif
  347. static const int video_font_draw_table8[] = {
  348. 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
  349. 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
  350. 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
  351. 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
  352. };
  353. static const int video_font_draw_table15[] = {
  354. 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
  355. };
  356. static const int video_font_draw_table16[] = {
  357. 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
  358. };
  359. static const int video_font_draw_table24[16][3] = {
  360. {0x00000000, 0x00000000, 0x00000000},
  361. {0x00000000, 0x00000000, 0x00ffffff},
  362. {0x00000000, 0x0000ffff, 0xff000000},
  363. {0x00000000, 0x0000ffff, 0xffffffff},
  364. {0x000000ff, 0xffff0000, 0x00000000},
  365. {0x000000ff, 0xffff0000, 0x00ffffff},
  366. {0x000000ff, 0xffffffff, 0xff000000},
  367. {0x000000ff, 0xffffffff, 0xffffffff},
  368. {0xffffff00, 0x00000000, 0x00000000},
  369. {0xffffff00, 0x00000000, 0x00ffffff},
  370. {0xffffff00, 0x0000ffff, 0xff000000},
  371. {0xffffff00, 0x0000ffff, 0xffffffff},
  372. {0xffffffff, 0xffff0000, 0x00000000},
  373. {0xffffffff, 0xffff0000, 0x00ffffff},
  374. {0xffffffff, 0xffffffff, 0xff000000},
  375. {0xffffffff, 0xffffffff, 0xffffffff}
  376. };
  377. static const int video_font_draw_table32[16][4] = {
  378. {0x00000000, 0x00000000, 0x00000000, 0x00000000},
  379. {0x00000000, 0x00000000, 0x00000000, 0x00ffffff},
  380. {0x00000000, 0x00000000, 0x00ffffff, 0x00000000},
  381. {0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff},
  382. {0x00000000, 0x00ffffff, 0x00000000, 0x00000000},
  383. {0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff},
  384. {0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000},
  385. {0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff},
  386. {0x00ffffff, 0x00000000, 0x00000000, 0x00000000},
  387. {0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff},
  388. {0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000},
  389. {0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff},
  390. {0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000},
  391. {0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff},
  392. {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000},
  393. {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
  394. };
  395. static void video_drawchars(int xx, int yy, unsigned char *s, int count)
  396. {
  397. u8 *cdat, *dest, *dest0;
  398. int rows, offset, c;
  399. offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
  400. dest0 = video_fb_address + offset;
  401. switch (VIDEO_DATA_FORMAT) {
  402. case GDF__8BIT_INDEX:
  403. case GDF__8BIT_332RGB:
  404. while (count--) {
  405. c = *s;
  406. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  407. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  408. rows--; dest += VIDEO_LINE_LEN) {
  409. u8 bits = *cdat++;
  410. ((u32 *) dest)[0] =
  411. (video_font_draw_table8[bits >> 4] &
  412. eorx) ^ bgx;
  413. ((u32 *) dest)[1] =
  414. (video_font_draw_table8[bits & 15] &
  415. eorx) ^ bgx;
  416. }
  417. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  418. s++;
  419. }
  420. break;
  421. case GDF_15BIT_555RGB:
  422. while (count--) {
  423. c = *s;
  424. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  425. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  426. rows--; dest += VIDEO_LINE_LEN) {
  427. u8 bits = *cdat++;
  428. ((u32 *) dest)[0] =
  429. SHORTSWAP32((video_font_draw_table15
  430. [bits >> 6] & eorx) ^
  431. bgx);
  432. ((u32 *) dest)[1] =
  433. SHORTSWAP32((video_font_draw_table15
  434. [bits >> 4 & 3] & eorx) ^
  435. bgx);
  436. ((u32 *) dest)[2] =
  437. SHORTSWAP32((video_font_draw_table15
  438. [bits >> 2 & 3] & eorx) ^
  439. bgx);
  440. ((u32 *) dest)[3] =
  441. SHORTSWAP32((video_font_draw_table15
  442. [bits & 3] & eorx) ^
  443. bgx);
  444. }
  445. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  446. s++;
  447. }
  448. break;
  449. case GDF_16BIT_565RGB:
  450. while (count--) {
  451. c = *s;
  452. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  453. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  454. rows--; dest += VIDEO_LINE_LEN) {
  455. u8 bits = *cdat++;
  456. ((u32 *) dest)[0] =
  457. SHORTSWAP32((video_font_draw_table16
  458. [bits >> 6] & eorx) ^
  459. bgx);
  460. ((u32 *) dest)[1] =
  461. SHORTSWAP32((video_font_draw_table16
  462. [bits >> 4 & 3] & eorx) ^
  463. bgx);
  464. ((u32 *) dest)[2] =
  465. SHORTSWAP32((video_font_draw_table16
  466. [bits >> 2 & 3] & eorx) ^
  467. bgx);
  468. ((u32 *) dest)[3] =
  469. SHORTSWAP32((video_font_draw_table16
  470. [bits & 3] & eorx) ^
  471. bgx);
  472. }
  473. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  474. s++;
  475. }
  476. break;
  477. case GDF_32BIT_X888RGB:
  478. while (count--) {
  479. c = *s;
  480. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  481. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  482. rows--; dest += VIDEO_LINE_LEN) {
  483. u8 bits = *cdat++;
  484. ((u32 *) dest)[0] =
  485. SWAP32((video_font_draw_table32
  486. [bits >> 4][0] & eorx) ^ bgx);
  487. ((u32 *) dest)[1] =
  488. SWAP32((video_font_draw_table32
  489. [bits >> 4][1] & eorx) ^ bgx);
  490. ((u32 *) dest)[2] =
  491. SWAP32((video_font_draw_table32
  492. [bits >> 4][2] & eorx) ^ bgx);
  493. ((u32 *) dest)[3] =
  494. SWAP32((video_font_draw_table32
  495. [bits >> 4][3] & eorx) ^ bgx);
  496. ((u32 *) dest)[4] =
  497. SWAP32((video_font_draw_table32
  498. [bits & 15][0] & eorx) ^ bgx);
  499. ((u32 *) dest)[5] =
  500. SWAP32((video_font_draw_table32
  501. [bits & 15][1] & eorx) ^ bgx);
  502. ((u32 *) dest)[6] =
  503. SWAP32((video_font_draw_table32
  504. [bits & 15][2] & eorx) ^ bgx);
  505. ((u32 *) dest)[7] =
  506. SWAP32((video_font_draw_table32
  507. [bits & 15][3] & eorx) ^ bgx);
  508. }
  509. if (cfb_do_flush_cache)
  510. flush_cache((ulong)dest0, 32);
  511. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  512. s++;
  513. }
  514. break;
  515. case GDF_24BIT_888RGB:
  516. while (count--) {
  517. c = *s;
  518. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  519. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  520. rows--; dest += VIDEO_LINE_LEN) {
  521. u8 bits = *cdat++;
  522. ((u32 *) dest)[0] =
  523. (video_font_draw_table24[bits >> 4][0]
  524. & eorx) ^ bgx;
  525. ((u32 *) dest)[1] =
  526. (video_font_draw_table24[bits >> 4][1]
  527. & eorx) ^ bgx;
  528. ((u32 *) dest)[2] =
  529. (video_font_draw_table24[bits >> 4][2]
  530. & eorx) ^ bgx;
  531. ((u32 *) dest)[3] =
  532. (video_font_draw_table24[bits & 15][0]
  533. & eorx) ^ bgx;
  534. ((u32 *) dest)[4] =
  535. (video_font_draw_table24[bits & 15][1]
  536. & eorx) ^ bgx;
  537. ((u32 *) dest)[5] =
  538. (video_font_draw_table24[bits & 15][2]
  539. & eorx) ^ bgx;
  540. }
  541. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  542. s++;
  543. }
  544. break;
  545. }
  546. }
  547. static inline void video_drawstring(int xx, int yy, unsigned char *s)
  548. {
  549. video_drawchars(xx, yy, s, strlen((char *) s));
  550. }
  551. static void video_putchar(int xx, int yy, unsigned char c)
  552. {
  553. video_drawchars(xx, yy + video_logo_height, &c, 1);
  554. }
  555. #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
  556. static void video_set_cursor(void)
  557. {
  558. if (cursor_state)
  559. console_cursor(0);
  560. console_cursor(1);
  561. }
  562. static void video_invertchar(int xx, int yy)
  563. {
  564. int firstx = xx * VIDEO_PIXEL_SIZE;
  565. int lastx = (xx + VIDEO_FONT_WIDTH) * VIDEO_PIXEL_SIZE;
  566. int firsty = yy * VIDEO_LINE_LEN;
  567. int lasty = (yy + VIDEO_FONT_HEIGHT) * VIDEO_LINE_LEN;
  568. int x, y;
  569. for (y = firsty; y < lasty; y += VIDEO_LINE_LEN) {
  570. for (x = firstx; x < lastx; x++) {
  571. u8 *dest = (u8 *)(video_fb_address) + x + y;
  572. *dest = ~*dest;
  573. if (cfb_do_flush_cache)
  574. flush_cache((ulong)dest, 4);
  575. }
  576. }
  577. }
  578. void console_cursor(int state)
  579. {
  580. #ifdef CONFIG_CONSOLE_TIME
  581. struct rtc_time tm;
  582. char info[16];
  583. /* time update only if cursor is on (faster scroll) */
  584. if (state) {
  585. rtc_get(&tm);
  586. sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
  587. tm.tm_sec);
  588. video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
  589. VIDEO_INFO_Y, (uchar *) info);
  590. sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
  591. tm.tm_year);
  592. video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
  593. VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT,
  594. (uchar *) info);
  595. }
  596. #endif
  597. if (cursor_state != state) {
  598. if (cursor_state) {
  599. /* turn off the cursor */
  600. video_invertchar(old_col * VIDEO_FONT_WIDTH,
  601. old_row * VIDEO_FONT_HEIGHT +
  602. video_logo_height);
  603. } else {
  604. /* turn off the cursor and record where it is */
  605. video_invertchar(console_col * VIDEO_FONT_WIDTH,
  606. console_row * VIDEO_FONT_HEIGHT +
  607. video_logo_height);
  608. old_col = console_col;
  609. old_row = console_row;
  610. }
  611. cursor_state = state;
  612. }
  613. }
  614. #endif
  615. #ifndef VIDEO_HW_RECTFILL
  616. static void memsetl(int *p, int c, int v)
  617. {
  618. while (c--)
  619. *(p++) = v;
  620. }
  621. #endif
  622. #ifndef VIDEO_HW_BITBLT
  623. static void memcpyl(int *d, int *s, int c)
  624. {
  625. while (c--)
  626. *(d++) = *(s++);
  627. }
  628. #endif
  629. static void console_clear_line(int line, int begin, int end)
  630. {
  631. #ifdef VIDEO_HW_RECTFILL
  632. video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  633. VIDEO_FONT_WIDTH * begin, /* dest pos x */
  634. video_logo_height +
  635. VIDEO_FONT_HEIGHT * line, /* dest pos y */
  636. VIDEO_FONT_WIDTH * (end - begin + 1), /* fr. width */
  637. VIDEO_FONT_HEIGHT, /* frame height */
  638. bgx /* fill color */
  639. );
  640. #else
  641. if (begin == 0 && (end + 1) == CONSOLE_COLS) {
  642. memsetl(CONSOLE_ROW_FIRST +
  643. CONSOLE_ROW_SIZE * line, /* offset of row */
  644. CONSOLE_ROW_SIZE >> 2, /* length of row */
  645. bgx /* fill color */
  646. );
  647. } else {
  648. void *offset;
  649. int i, size;
  650. offset = CONSOLE_ROW_FIRST +
  651. CONSOLE_ROW_SIZE * line + /* offset of row */
  652. VIDEO_FONT_WIDTH *
  653. VIDEO_PIXEL_SIZE * begin; /* offset of col */
  654. size = VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE * (end - begin + 1);
  655. size >>= 2; /* length to end for memsetl() */
  656. /* fill at col offset of i'th line using bgx as fill color */
  657. for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  658. memsetl(offset + i * VIDEO_LINE_LEN, size, bgx);
  659. }
  660. #endif
  661. if (cfb_do_flush_cache)
  662. flush_cache((ulong)CONSOLE_ROW_FIRST, CONSOLE_SIZE);
  663. }
  664. static void console_scrollup(void)
  665. {
  666. /* copy up rows ignoring the first one */
  667. #ifdef VIDEO_HW_BITBLT
  668. video_hw_bitblt(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  669. 0, /* source pos x */
  670. video_logo_height +
  671. VIDEO_FONT_HEIGHT, /* source pos y */
  672. 0, /* dest pos x */
  673. video_logo_height, /* dest pos y */
  674. VIDEO_VISIBLE_COLS, /* frame width */
  675. VIDEO_VISIBLE_ROWS
  676. - video_logo_height
  677. - VIDEO_FONT_HEIGHT /* frame height */
  678. );
  679. #else
  680. memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
  681. CONSOLE_SCROLL_SIZE >> 2);
  682. #endif
  683. /* clear the last one */
  684. console_clear_line(CONSOLE_ROWS - 1, 0, CONSOLE_COLS - 1);
  685. }
  686. static void console_back(void)
  687. {
  688. console_col--;
  689. if (console_col < 0) {
  690. console_col = CONSOLE_COLS - 1;
  691. console_row--;
  692. if (console_row < 0)
  693. console_row = 0;
  694. }
  695. }
  696. #ifdef CONFIG_CFB_CONSOLE_ANSI
  697. static void console_clear(void)
  698. {
  699. #ifdef VIDEO_HW_RECTFILL
  700. video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  701. 0, /* dest pos x */
  702. video_logo_height, /* dest pos y */
  703. VIDEO_VISIBLE_COLS, /* frame width */
  704. VIDEO_VISIBLE_ROWS, /* frame height */
  705. bgx /* fill color */
  706. );
  707. #else
  708. memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
  709. #endif
  710. }
  711. static void console_cursor_fix(void)
  712. {
  713. if (console_row < 0)
  714. console_row = 0;
  715. if (console_row >= CONSOLE_ROWS)
  716. console_row = CONSOLE_ROWS - 1;
  717. if (console_col < 0)
  718. console_col = 0;
  719. if (console_col >= CONSOLE_COLS)
  720. console_col = CONSOLE_COLS - 1;
  721. }
  722. static void console_cursor_up(int n)
  723. {
  724. console_row -= n;
  725. console_cursor_fix();
  726. }
  727. static void console_cursor_down(int n)
  728. {
  729. console_row += n;
  730. console_cursor_fix();
  731. }
  732. static void console_cursor_left(int n)
  733. {
  734. console_col -= n;
  735. console_cursor_fix();
  736. }
  737. static void console_cursor_right(int n)
  738. {
  739. console_col += n;
  740. console_cursor_fix();
  741. }
  742. static void console_cursor_set_position(int row, int col)
  743. {
  744. if (console_row != -1)
  745. console_row = row;
  746. if (console_col != -1)
  747. console_col = col;
  748. console_cursor_fix();
  749. }
  750. static void console_previousline(int n)
  751. {
  752. /* FIXME: also scroll terminal ? */
  753. console_row -= n;
  754. console_cursor_fix();
  755. }
  756. static void console_swap_colors(void)
  757. {
  758. eorx = fgx;
  759. fgx = bgx;
  760. bgx = eorx;
  761. eorx = fgx ^ bgx;
  762. }
  763. static inline int console_cursor_is_visible(void)
  764. {
  765. return !ansi_cursor_hidden;
  766. }
  767. #else
  768. static inline int console_cursor_is_visible(void)
  769. {
  770. return 1;
  771. }
  772. #endif
  773. static void console_newline(int n)
  774. {
  775. console_row += n;
  776. console_col = 0;
  777. /* Check if we need to scroll the terminal */
  778. if (console_row >= CONSOLE_ROWS) {
  779. /* Scroll everything up */
  780. console_scrollup();
  781. /* Decrement row number */
  782. console_row = CONSOLE_ROWS - 1;
  783. }
  784. }
  785. static void console_cr(void)
  786. {
  787. console_col = 0;
  788. }
  789. static void parse_putc(const char c)
  790. {
  791. static int nl = 1;
  792. if (console_cursor_is_visible())
  793. CURSOR_OFF;
  794. switch (c) {
  795. case 13: /* back to first column */
  796. console_cr();
  797. break;
  798. case '\n': /* next line */
  799. if (console_col || (!console_col && nl))
  800. console_newline(1);
  801. nl = 1;
  802. break;
  803. case 9: /* tab 8 */
  804. console_col |= 0x0008;
  805. console_col &= ~0x0007;
  806. if (console_col >= CONSOLE_COLS)
  807. console_newline(1);
  808. break;
  809. case 8: /* backspace */
  810. console_back();
  811. break;
  812. case 7: /* bell */
  813. break; /* ignored */
  814. default: /* draw the char */
  815. video_putchar(console_col * VIDEO_FONT_WIDTH,
  816. console_row * VIDEO_FONT_HEIGHT, c);
  817. console_col++;
  818. /* check for newline */
  819. if (console_col >= CONSOLE_COLS) {
  820. console_newline(1);
  821. nl = 0;
  822. }
  823. }
  824. if (console_cursor_is_visible())
  825. CURSOR_SET;
  826. }
  827. void video_putc(const char c)
  828. {
  829. #ifdef CONFIG_CFB_CONSOLE_ANSI
  830. int i;
  831. if (c == 27) {
  832. for (i = 0; i < ansi_buf_size; ++i)
  833. parse_putc(ansi_buf[i]);
  834. ansi_buf[0] = 27;
  835. ansi_buf_size = 1;
  836. return;
  837. }
  838. if (ansi_buf_size > 0) {
  839. /*
  840. * 0 - ESC
  841. * 1 - [
  842. * 2 - num1
  843. * 3 - ..
  844. * 4 - ;
  845. * 5 - num2
  846. * 6 - ..
  847. * - cchar
  848. */
  849. int next = 0;
  850. int flush = 0;
  851. int fail = 0;
  852. int num1 = 0;
  853. int num2 = 0;
  854. int cchar = 0;
  855. ansi_buf[ansi_buf_size++] = c;
  856. if (ansi_buf_size >= sizeof(ansi_buf))
  857. fail = 1;
  858. for (i = 0; i < ansi_buf_size; ++i) {
  859. if (fail)
  860. break;
  861. switch (next) {
  862. case 0:
  863. if (ansi_buf[i] == 27)
  864. next = 1;
  865. else
  866. fail = 1;
  867. break;
  868. case 1:
  869. if (ansi_buf[i] == '[')
  870. next = 2;
  871. else
  872. fail = 1;
  873. break;
  874. case 2:
  875. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  876. num1 = ansi_buf[i]-'0';
  877. next = 3;
  878. } else if (ansi_buf[i] != '?') {
  879. --i;
  880. num1 = 1;
  881. next = 4;
  882. }
  883. break;
  884. case 3:
  885. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  886. num1 *= 10;
  887. num1 += ansi_buf[i]-'0';
  888. } else {
  889. --i;
  890. next = 4;
  891. }
  892. break;
  893. case 4:
  894. if (ansi_buf[i] != ';') {
  895. --i;
  896. next = 7;
  897. } else
  898. next = 5;
  899. break;
  900. case 5:
  901. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  902. num2 = ansi_buf[i]-'0';
  903. next = 6;
  904. } else
  905. fail = 1;
  906. break;
  907. case 6:
  908. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  909. num2 *= 10;
  910. num2 += ansi_buf[i]-'0';
  911. } else {
  912. --i;
  913. next = 7;
  914. }
  915. break;
  916. case 7:
  917. if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H')
  918. || ansi_buf[i] == 'J'
  919. || ansi_buf[i] == 'K'
  920. || ansi_buf[i] == 'h'
  921. || ansi_buf[i] == 'l'
  922. || ansi_buf[i] == 'm') {
  923. cchar = ansi_buf[i];
  924. flush = 1;
  925. } else
  926. fail = 1;
  927. break;
  928. }
  929. }
  930. if (fail) {
  931. for (i = 0; i < ansi_buf_size; ++i)
  932. parse_putc(ansi_buf[i]);
  933. ansi_buf_size = 0;
  934. return;
  935. }
  936. if (flush) {
  937. if (!ansi_cursor_hidden)
  938. CURSOR_OFF;
  939. ansi_buf_size = 0;
  940. switch (cchar) {
  941. case 'A':
  942. /* move cursor num1 rows up */
  943. console_cursor_up(num1);
  944. break;
  945. case 'B':
  946. /* move cursor num1 rows down */
  947. console_cursor_down(num1);
  948. break;
  949. case 'C':
  950. /* move cursor num1 columns forward */
  951. console_cursor_right(num1);
  952. break;
  953. case 'D':
  954. /* move cursor num1 columns back */
  955. console_cursor_left(num1);
  956. break;
  957. case 'E':
  958. /* move cursor num1 rows up at begin of row */
  959. console_previousline(num1);
  960. break;
  961. case 'F':
  962. /* move cursor num1 rows down at begin of row */
  963. console_newline(num1);
  964. break;
  965. case 'G':
  966. /* move cursor to column num1 */
  967. console_cursor_set_position(-1, num1-1);
  968. break;
  969. case 'H':
  970. /* move cursor to row num1, column num2 */
  971. console_cursor_set_position(num1-1, num2-1);
  972. break;
  973. case 'J':
  974. /* clear console and move cursor to 0, 0 */
  975. console_clear();
  976. console_cursor_set_position(0, 0);
  977. break;
  978. case 'K':
  979. /* clear line */
  980. if (num1 == 0)
  981. console_clear_line(console_row,
  982. console_col,
  983. CONSOLE_COLS-1);
  984. else if (num1 == 1)
  985. console_clear_line(console_row,
  986. 0, console_col);
  987. else
  988. console_clear_line(console_row,
  989. 0, CONSOLE_COLS-1);
  990. break;
  991. case 'h':
  992. ansi_cursor_hidden = 0;
  993. break;
  994. case 'l':
  995. ansi_cursor_hidden = 1;
  996. break;
  997. case 'm':
  998. if (num1 == 0) { /* reset swapped colors */
  999. if (ansi_colors_need_revert) {
  1000. console_swap_colors();
  1001. ansi_colors_need_revert = 0;
  1002. }
  1003. } else if (num1 == 7) { /* once swap colors */
  1004. if (!ansi_colors_need_revert) {
  1005. console_swap_colors();
  1006. ansi_colors_need_revert = 1;
  1007. }
  1008. }
  1009. break;
  1010. }
  1011. if (!ansi_cursor_hidden)
  1012. CURSOR_SET;
  1013. }
  1014. } else {
  1015. parse_putc(c);
  1016. }
  1017. #else
  1018. parse_putc(c);
  1019. #endif
  1020. }
  1021. void video_puts(const char *s)
  1022. {
  1023. int count = strlen(s);
  1024. while (count--)
  1025. video_putc(*s++);
  1026. }
  1027. /*
  1028. * Do not enforce drivers (or board code) to provide empty
  1029. * video_set_lut() if they do not support 8 bpp format.
  1030. * Implement weak default function instead.
  1031. */
  1032. void __video_set_lut(unsigned int index, unsigned char r,
  1033. unsigned char g, unsigned char b)
  1034. {
  1035. }
  1036. void video_set_lut(unsigned int, unsigned char, unsigned char, unsigned char)
  1037. __attribute__ ((weak, alias("__video_set_lut")));
  1038. #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
  1039. #define FILL_8BIT_332RGB(r,g,b) { \
  1040. *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
  1041. fb ++; \
  1042. }
  1043. #define FILL_15BIT_555RGB(r,g,b) { \
  1044. *(unsigned short *)fb = \
  1045. SWAP16((unsigned short)(((r>>3)<<10) | \
  1046. ((g>>3)<<5) | \
  1047. (b>>3))); \
  1048. fb += 2; \
  1049. }
  1050. #define FILL_16BIT_565RGB(r,g,b) { \
  1051. *(unsigned short *)fb = \
  1052. SWAP16((unsigned short)((((r)>>3)<<11)| \
  1053. (((g)>>2)<<5) | \
  1054. ((b)>>3))); \
  1055. fb += 2; \
  1056. }
  1057. #define FILL_32BIT_X888RGB(r,g,b) { \
  1058. *(unsigned long *)fb = \
  1059. SWAP32((unsigned long)(((r<<16) | \
  1060. (g<<8) | \
  1061. b))); \
  1062. fb += 4; \
  1063. }
  1064. #ifdef VIDEO_FB_LITTLE_ENDIAN
  1065. #define FILL_24BIT_888RGB(r,g,b) { \
  1066. fb[0] = b; \
  1067. fb[1] = g; \
  1068. fb[2] = r; \
  1069. fb += 3; \
  1070. }
  1071. #else
  1072. #define FILL_24BIT_888RGB(r,g,b) { \
  1073. fb[0] = r; \
  1074. fb[1] = g; \
  1075. fb[2] = b; \
  1076. fb += 3; \
  1077. }
  1078. #endif
  1079. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1080. static inline void fill_555rgb_pswap(uchar *fb, int x, u8 r, u8 g, u8 b)
  1081. {
  1082. ushort *dst = (ushort *) fb;
  1083. ushort color = (ushort) (((r >> 3) << 10) |
  1084. ((g >> 3) << 5) |
  1085. (b >> 3));
  1086. if (x & 1)
  1087. *(--dst) = color;
  1088. else
  1089. *(++dst) = color;
  1090. }
  1091. #endif
  1092. /*
  1093. * RLE8 bitmap support
  1094. */
  1095. #ifdef CONFIG_VIDEO_BMP_RLE8
  1096. /* Pre-calculated color table entry */
  1097. struct palette {
  1098. union {
  1099. unsigned short w; /* word */
  1100. unsigned int dw; /* double word */
  1101. } ce; /* color entry */
  1102. };
  1103. /*
  1104. * Helper to draw encoded/unencoded run.
  1105. */
  1106. static void draw_bitmap(uchar **fb, uchar *bm, struct palette *p,
  1107. int cnt, int enc)
  1108. {
  1109. ulong addr = (ulong) *fb;
  1110. int *off;
  1111. int enc_off = 1;
  1112. int i;
  1113. /*
  1114. * Setup offset of the color index in the bitmap.
  1115. * Color index of encoded run is at offset 1.
  1116. */
  1117. off = enc ? &enc_off : &i;
  1118. switch (VIDEO_DATA_FORMAT) {
  1119. case GDF__8BIT_INDEX:
  1120. for (i = 0; i < cnt; i++)
  1121. *(unsigned char *) addr++ = bm[*off];
  1122. break;
  1123. case GDF_15BIT_555RGB:
  1124. case GDF_16BIT_565RGB:
  1125. /* differences handled while pre-calculating palette */
  1126. for (i = 0; i < cnt; i++) {
  1127. *(unsigned short *) addr = p[bm[*off]].ce.w;
  1128. addr += 2;
  1129. }
  1130. break;
  1131. case GDF_32BIT_X888RGB:
  1132. for (i = 0; i < cnt; i++) {
  1133. *(unsigned long *) addr = p[bm[*off]].ce.dw;
  1134. addr += 4;
  1135. }
  1136. break;
  1137. }
  1138. *fb = (uchar *) addr; /* return modified address */
  1139. }
  1140. static int display_rle8_bitmap(bmp_image_t *img, int xoff, int yoff,
  1141. int width, int height)
  1142. {
  1143. unsigned char *bm;
  1144. unsigned char *fbp;
  1145. unsigned int cnt, runlen;
  1146. int decode = 1;
  1147. int x, y, bpp, i, ncolors;
  1148. struct palette p[256];
  1149. bmp_color_table_entry_t cte;
  1150. int green_shift, red_off;
  1151. int limit = VIDEO_COLS * VIDEO_ROWS;
  1152. int pixels = 0;
  1153. x = 0;
  1154. y = __le32_to_cpu(img->header.height) - 1;
  1155. ncolors = __le32_to_cpu(img->header.colors_used);
  1156. bpp = VIDEO_PIXEL_SIZE;
  1157. fbp = (unsigned char *) ((unsigned int) video_fb_address +
  1158. (((y + yoff) * VIDEO_COLS) + xoff) * bpp);
  1159. bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
  1160. /* pre-calculate and setup palette */
  1161. switch (VIDEO_DATA_FORMAT) {
  1162. case GDF__8BIT_INDEX:
  1163. for (i = 0; i < ncolors; i++) {
  1164. cte = img->color_table[i];
  1165. video_set_lut(i, cte.red, cte.green, cte.blue);
  1166. }
  1167. break;
  1168. case GDF_15BIT_555RGB:
  1169. case GDF_16BIT_565RGB:
  1170. if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) {
  1171. green_shift = 3;
  1172. red_off = 10;
  1173. } else {
  1174. green_shift = 2;
  1175. red_off = 11;
  1176. }
  1177. for (i = 0; i < ncolors; i++) {
  1178. cte = img->color_table[i];
  1179. p[i].ce.w = SWAP16((unsigned short)
  1180. (((cte.red >> 3) << red_off) |
  1181. ((cte.green >> green_shift) << 5) |
  1182. cte.blue >> 3));
  1183. }
  1184. break;
  1185. case GDF_32BIT_X888RGB:
  1186. for (i = 0; i < ncolors; i++) {
  1187. cte = img->color_table[i];
  1188. p[i].ce.dw = SWAP32((cte.red << 16) |
  1189. (cte.green << 8) |
  1190. cte.blue);
  1191. }
  1192. break;
  1193. default:
  1194. printf("RLE Bitmap unsupported in video mode 0x%x\n",
  1195. VIDEO_DATA_FORMAT);
  1196. return -1;
  1197. }
  1198. while (decode) {
  1199. switch (bm[0]) {
  1200. case 0:
  1201. switch (bm[1]) {
  1202. case 0:
  1203. /* scan line end marker */
  1204. bm += 2;
  1205. x = 0;
  1206. y--;
  1207. fbp = (unsigned char *)
  1208. ((unsigned int) video_fb_address +
  1209. (((y + yoff) * VIDEO_COLS) +
  1210. xoff) * bpp);
  1211. continue;
  1212. case 1:
  1213. /* end of bitmap data marker */
  1214. decode = 0;
  1215. break;
  1216. case 2:
  1217. /* run offset marker */
  1218. x += bm[2];
  1219. y -= bm[3];
  1220. fbp = (unsigned char *)
  1221. ((unsigned int) video_fb_address +
  1222. (((y + yoff) * VIDEO_COLS) +
  1223. x + xoff) * bpp);
  1224. bm += 4;
  1225. break;
  1226. default:
  1227. /* unencoded run */
  1228. cnt = bm[1];
  1229. runlen = cnt;
  1230. pixels += cnt;
  1231. if (pixels > limit)
  1232. goto error;
  1233. bm += 2;
  1234. if (y < height) {
  1235. if (x >= width) {
  1236. x += runlen;
  1237. goto next_run;
  1238. }
  1239. if (x + runlen > width)
  1240. cnt = width - x;
  1241. draw_bitmap(&fbp, bm, p, cnt, 0);
  1242. x += runlen;
  1243. }
  1244. next_run:
  1245. bm += runlen;
  1246. if (runlen & 1)
  1247. bm++; /* 0 padding if length is odd */
  1248. }
  1249. break;
  1250. default:
  1251. /* encoded run */
  1252. cnt = bm[0];
  1253. runlen = cnt;
  1254. pixels += cnt;
  1255. if (pixels > limit)
  1256. goto error;
  1257. if (y < height) { /* only draw into visible area */
  1258. if (x >= width) {
  1259. x += runlen;
  1260. bm += 2;
  1261. continue;
  1262. }
  1263. if (x + runlen > width)
  1264. cnt = width - x;
  1265. draw_bitmap(&fbp, bm, p, cnt, 1);
  1266. x += runlen;
  1267. }
  1268. bm += 2;
  1269. break;
  1270. }
  1271. }
  1272. return 0;
  1273. error:
  1274. printf("Error: Too much encoded pixel data, validate your bitmap\n");
  1275. return -1;
  1276. }
  1277. #endif
  1278. /*
  1279. * Display the BMP file located at address bmp_image.
  1280. */
  1281. int video_display_bitmap(ulong bmp_image, int x, int y)
  1282. {
  1283. ushort xcount, ycount;
  1284. uchar *fb;
  1285. bmp_image_t *bmp = (bmp_image_t *) bmp_image;
  1286. uchar *bmap;
  1287. ushort padded_line;
  1288. unsigned long width, height, bpp;
  1289. unsigned colors;
  1290. unsigned long compression;
  1291. bmp_color_table_entry_t cte;
  1292. #ifdef CONFIG_VIDEO_BMP_GZIP
  1293. unsigned char *dst = NULL;
  1294. ulong len;
  1295. #endif
  1296. WATCHDOG_RESET();
  1297. if (!((bmp->header.signature[0] == 'B') &&
  1298. (bmp->header.signature[1] == 'M'))) {
  1299. #ifdef CONFIG_VIDEO_BMP_GZIP
  1300. /*
  1301. * Could be a gzipped bmp image, try to decrompress...
  1302. */
  1303. len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
  1304. dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
  1305. if (dst == NULL) {
  1306. printf("Error: malloc in gunzip failed!\n");
  1307. return 1;
  1308. }
  1309. if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE,
  1310. (uchar *) bmp_image,
  1311. &len) != 0) {
  1312. printf("Error: no valid bmp or bmp.gz image at %lx\n",
  1313. bmp_image);
  1314. free(dst);
  1315. return 1;
  1316. }
  1317. if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
  1318. printf("Image could be truncated "
  1319. "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
  1320. }
  1321. /*
  1322. * Set addr to decompressed image
  1323. */
  1324. bmp = (bmp_image_t *) dst;
  1325. if (!((bmp->header.signature[0] == 'B') &&
  1326. (bmp->header.signature[1] == 'M'))) {
  1327. printf("Error: no valid bmp.gz image at %lx\n",
  1328. bmp_image);
  1329. free(dst);
  1330. return 1;
  1331. }
  1332. #else
  1333. printf("Error: no valid bmp image at %lx\n", bmp_image);
  1334. return 1;
  1335. #endif /* CONFIG_VIDEO_BMP_GZIP */
  1336. }
  1337. width = le32_to_cpu(bmp->header.width);
  1338. height = le32_to_cpu(bmp->header.height);
  1339. bpp = le16_to_cpu(bmp->header.bit_count);
  1340. colors = le32_to_cpu(bmp->header.colors_used);
  1341. compression = le32_to_cpu(bmp->header.compression);
  1342. debug("Display-bmp: %ld x %ld with %d colors\n",
  1343. width, height, colors);
  1344. if (compression != BMP_BI_RGB
  1345. #ifdef CONFIG_VIDEO_BMP_RLE8
  1346. && compression != BMP_BI_RLE8
  1347. #endif
  1348. ) {
  1349. printf("Error: compression type %ld not supported\n",
  1350. compression);
  1351. #ifdef CONFIG_VIDEO_BMP_GZIP
  1352. if (dst)
  1353. free(dst);
  1354. #endif
  1355. return 1;
  1356. }
  1357. padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
  1358. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  1359. if (x == BMP_ALIGN_CENTER)
  1360. x = max(0, (VIDEO_VISIBLE_COLS - width) / 2);
  1361. else if (x < 0)
  1362. x = max(0, VIDEO_VISIBLE_COLS - width + x + 1);
  1363. if (y == BMP_ALIGN_CENTER)
  1364. y = max(0, (VIDEO_VISIBLE_ROWS - height) / 2);
  1365. else if (y < 0)
  1366. y = max(0, VIDEO_VISIBLE_ROWS - height + y + 1);
  1367. #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
  1368. if ((x + width) > VIDEO_VISIBLE_COLS)
  1369. width = VIDEO_VISIBLE_COLS - x;
  1370. if ((y + height) > VIDEO_VISIBLE_ROWS)
  1371. height = VIDEO_VISIBLE_ROWS - y;
  1372. bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
  1373. fb = (uchar *) (video_fb_address +
  1374. ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
  1375. x * VIDEO_PIXEL_SIZE);
  1376. #ifdef CONFIG_VIDEO_BMP_RLE8
  1377. if (compression == BMP_BI_RLE8) {
  1378. return display_rle8_bitmap(bmp, x, y, width, height);
  1379. }
  1380. #endif
  1381. /* We handle only 4, 8, or 24 bpp bitmaps */
  1382. switch (le16_to_cpu(bmp->header.bit_count)) {
  1383. case 4:
  1384. padded_line -= width / 2;
  1385. ycount = height;
  1386. switch (VIDEO_DATA_FORMAT) {
  1387. case GDF_32BIT_X888RGB:
  1388. while (ycount--) {
  1389. WATCHDOG_RESET();
  1390. /*
  1391. * Don't assume that 'width' is an
  1392. * even number
  1393. */
  1394. for (xcount = 0; xcount < width; xcount++) {
  1395. uchar idx;
  1396. if (xcount & 1) {
  1397. idx = *bmap & 0xF;
  1398. bmap++;
  1399. } else
  1400. idx = *bmap >> 4;
  1401. cte = bmp->color_table[idx];
  1402. FILL_32BIT_X888RGB(cte.red, cte.green,
  1403. cte.blue);
  1404. }
  1405. bmap += padded_line;
  1406. fb -= (VIDEO_VISIBLE_COLS + width) *
  1407. VIDEO_PIXEL_SIZE;
  1408. }
  1409. break;
  1410. default:
  1411. puts("4bpp bitmap unsupported with current "
  1412. "video mode\n");
  1413. break;
  1414. }
  1415. break;
  1416. case 8:
  1417. padded_line -= width;
  1418. if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
  1419. /* Copy colormap */
  1420. for (xcount = 0; xcount < colors; ++xcount) {
  1421. cte = bmp->color_table[xcount];
  1422. video_set_lut(xcount, cte.red, cte.green,
  1423. cte.blue);
  1424. }
  1425. }
  1426. ycount = height;
  1427. switch (VIDEO_DATA_FORMAT) {
  1428. case GDF__8BIT_INDEX:
  1429. while (ycount--) {
  1430. WATCHDOG_RESET();
  1431. xcount = width;
  1432. while (xcount--) {
  1433. *fb++ = *bmap++;
  1434. }
  1435. bmap += padded_line;
  1436. fb -= (VIDEO_VISIBLE_COLS + width) *
  1437. VIDEO_PIXEL_SIZE;
  1438. }
  1439. break;
  1440. case GDF__8BIT_332RGB:
  1441. while (ycount--) {
  1442. WATCHDOG_RESET();
  1443. xcount = width;
  1444. while (xcount--) {
  1445. cte = bmp->color_table[*bmap++];
  1446. FILL_8BIT_332RGB(cte.red, cte.green,
  1447. cte.blue);
  1448. }
  1449. bmap += padded_line;
  1450. fb -= (VIDEO_VISIBLE_COLS + width) *
  1451. VIDEO_PIXEL_SIZE;
  1452. }
  1453. break;
  1454. case GDF_15BIT_555RGB:
  1455. while (ycount--) {
  1456. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1457. int xpos = x;
  1458. #endif
  1459. WATCHDOG_RESET();
  1460. xcount = width;
  1461. while (xcount--) {
  1462. cte = bmp->color_table[*bmap++];
  1463. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1464. fill_555rgb_pswap(fb, xpos++, cte.red,
  1465. cte.green,
  1466. cte.blue);
  1467. fb += 2;
  1468. #else
  1469. FILL_15BIT_555RGB(cte.red, cte.green,
  1470. cte.blue);
  1471. #endif
  1472. }
  1473. bmap += padded_line;
  1474. fb -= (VIDEO_VISIBLE_COLS + width) *
  1475. VIDEO_PIXEL_SIZE;
  1476. }
  1477. break;
  1478. case GDF_16BIT_565RGB:
  1479. while (ycount--) {
  1480. WATCHDOG_RESET();
  1481. xcount = width;
  1482. while (xcount--) {
  1483. cte = bmp->color_table[*bmap++];
  1484. FILL_16BIT_565RGB(cte.red, cte.green,
  1485. cte.blue);
  1486. }
  1487. bmap += padded_line;
  1488. fb -= (VIDEO_VISIBLE_COLS + width) *
  1489. VIDEO_PIXEL_SIZE;
  1490. }
  1491. break;
  1492. case GDF_32BIT_X888RGB:
  1493. while (ycount--) {
  1494. WATCHDOG_RESET();
  1495. xcount = width;
  1496. while (xcount--) {
  1497. cte = bmp->color_table[*bmap++];
  1498. FILL_32BIT_X888RGB(cte.red, cte.green,
  1499. cte.blue);
  1500. }
  1501. bmap += padded_line;
  1502. fb -= (VIDEO_VISIBLE_COLS + width) *
  1503. VIDEO_PIXEL_SIZE;
  1504. }
  1505. break;
  1506. case GDF_24BIT_888RGB:
  1507. while (ycount--) {
  1508. WATCHDOG_RESET();
  1509. xcount = width;
  1510. while (xcount--) {
  1511. cte = bmp->color_table[*bmap++];
  1512. FILL_24BIT_888RGB(cte.red, cte.green,
  1513. cte.blue);
  1514. }
  1515. bmap += padded_line;
  1516. fb -= (VIDEO_VISIBLE_COLS + width) *
  1517. VIDEO_PIXEL_SIZE;
  1518. }
  1519. break;
  1520. }
  1521. break;
  1522. case 24:
  1523. padded_line -= 3 * width;
  1524. ycount = height;
  1525. switch (VIDEO_DATA_FORMAT) {
  1526. case GDF__8BIT_332RGB:
  1527. while (ycount--) {
  1528. WATCHDOG_RESET();
  1529. xcount = width;
  1530. while (xcount--) {
  1531. FILL_8BIT_332RGB(bmap[2], bmap[1],
  1532. bmap[0]);
  1533. bmap += 3;
  1534. }
  1535. bmap += padded_line;
  1536. fb -= (VIDEO_VISIBLE_COLS + width) *
  1537. VIDEO_PIXEL_SIZE;
  1538. }
  1539. break;
  1540. case GDF_15BIT_555RGB:
  1541. while (ycount--) {
  1542. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1543. int xpos = x;
  1544. #endif
  1545. WATCHDOG_RESET();
  1546. xcount = width;
  1547. while (xcount--) {
  1548. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1549. fill_555rgb_pswap(fb, xpos++, bmap[2],
  1550. bmap[1], bmap[0]);
  1551. fb += 2;
  1552. #else
  1553. FILL_15BIT_555RGB(bmap[2], bmap[1],
  1554. bmap[0]);
  1555. #endif
  1556. bmap += 3;
  1557. }
  1558. bmap += padded_line;
  1559. fb -= (VIDEO_VISIBLE_COLS + width) *
  1560. VIDEO_PIXEL_SIZE;
  1561. }
  1562. break;
  1563. case GDF_16BIT_565RGB:
  1564. while (ycount--) {
  1565. WATCHDOG_RESET();
  1566. xcount = width;
  1567. while (xcount--) {
  1568. FILL_16BIT_565RGB(bmap[2], bmap[1],
  1569. bmap[0]);
  1570. bmap += 3;
  1571. }
  1572. bmap += padded_line;
  1573. fb -= (VIDEO_VISIBLE_COLS + width) *
  1574. VIDEO_PIXEL_SIZE;
  1575. }
  1576. break;
  1577. case GDF_32BIT_X888RGB:
  1578. while (ycount--) {
  1579. WATCHDOG_RESET();
  1580. xcount = width;
  1581. while (xcount--) {
  1582. FILL_32BIT_X888RGB(bmap[2], bmap[1],
  1583. bmap[0]);
  1584. bmap += 3;
  1585. }
  1586. bmap += padded_line;
  1587. fb -= (VIDEO_VISIBLE_COLS + width) *
  1588. VIDEO_PIXEL_SIZE;
  1589. }
  1590. break;
  1591. case GDF_24BIT_888RGB:
  1592. while (ycount--) {
  1593. WATCHDOG_RESET();
  1594. xcount = width;
  1595. while (xcount--) {
  1596. FILL_24BIT_888RGB(bmap[2], bmap[1],
  1597. bmap[0]);
  1598. bmap += 3;
  1599. }
  1600. bmap += padded_line;
  1601. fb -= (VIDEO_VISIBLE_COLS + width) *
  1602. VIDEO_PIXEL_SIZE;
  1603. }
  1604. break;
  1605. default:
  1606. printf("Error: 24 bits/pixel bitmap incompatible "
  1607. "with current video mode\n");
  1608. break;
  1609. }
  1610. break;
  1611. default:
  1612. printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
  1613. le16_to_cpu(bmp->header.bit_count));
  1614. break;
  1615. }
  1616. #ifdef CONFIG_VIDEO_BMP_GZIP
  1617. if (dst) {
  1618. free(dst);
  1619. }
  1620. #endif
  1621. return (0);
  1622. }
  1623. #endif
  1624. #ifdef CONFIG_VIDEO_LOGO
  1625. static int video_logo_xpos;
  1626. static int video_logo_ypos;
  1627. static void plot_logo_or_black(void *screen, int width, int x, int y, \
  1628. int black);
  1629. static void logo_plot(void *screen, int width, int x, int y)
  1630. {
  1631. plot_logo_or_black(screen, width, x, y, 0);
  1632. }
  1633. static void logo_black(void)
  1634. {
  1635. plot_logo_or_black(video_fb_address, \
  1636. VIDEO_COLS, \
  1637. video_logo_xpos, \
  1638. video_logo_ypos, \
  1639. 1);
  1640. }
  1641. static int do_clrlogo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  1642. {
  1643. if (argc != 1)
  1644. return cmd_usage(cmdtp);
  1645. logo_black();
  1646. return 0;
  1647. }
  1648. U_BOOT_CMD(
  1649. clrlogo, 1, 0, do_clrlogo,
  1650. "fill the boot logo area with black",
  1651. " "
  1652. );
  1653. static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
  1654. {
  1655. int xcount, i;
  1656. int skip = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
  1657. int ycount = video_logo_height;
  1658. unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
  1659. unsigned char *source;
  1660. unsigned char *dest;
  1661. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  1662. if (x == BMP_ALIGN_CENTER)
  1663. x = max(0, (VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
  1664. else if (x < 0)
  1665. x = max(0, VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1);
  1666. if (y == BMP_ALIGN_CENTER)
  1667. y = max(0, (VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
  1668. else if (y < 0)
  1669. y = max(0, VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1);
  1670. #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
  1671. dest = (unsigned char *)screen + (y * width + x) * VIDEO_PIXEL_SIZE;
  1672. #ifdef CONFIG_VIDEO_BMP_LOGO
  1673. source = bmp_logo_bitmap;
  1674. /* Allocate temporary space for computing colormap */
  1675. logo_red = malloc(BMP_LOGO_COLORS);
  1676. logo_green = malloc(BMP_LOGO_COLORS);
  1677. logo_blue = malloc(BMP_LOGO_COLORS);
  1678. /* Compute color map */
  1679. for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
  1680. logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
  1681. logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
  1682. logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
  1683. }
  1684. #else
  1685. source = linux_logo;
  1686. logo_red = linux_logo_red;
  1687. logo_green = linux_logo_green;
  1688. logo_blue = linux_logo_blue;
  1689. #endif
  1690. if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
  1691. for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
  1692. video_set_lut(i + VIDEO_LOGO_LUT_OFFSET,
  1693. logo_red[i], logo_green[i],
  1694. logo_blue[i]);
  1695. }
  1696. }
  1697. while (ycount--) {
  1698. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1699. int xpos = x;
  1700. #endif
  1701. xcount = VIDEO_LOGO_WIDTH;
  1702. while (xcount--) {
  1703. if (black) {
  1704. r = 0x00;
  1705. g = 0x00;
  1706. b = 0x00;
  1707. } else {
  1708. r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
  1709. g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
  1710. b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
  1711. }
  1712. switch (VIDEO_DATA_FORMAT) {
  1713. case GDF__8BIT_INDEX:
  1714. *dest = *source;
  1715. break;
  1716. case GDF__8BIT_332RGB:
  1717. *dest = ((r >> 5) << 5) |
  1718. ((g >> 5) << 2) |
  1719. (b >> 6);
  1720. break;
  1721. case GDF_15BIT_555RGB:
  1722. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1723. fill_555rgb_pswap(dest, xpos++, r, g, b);
  1724. #else
  1725. *(unsigned short *) dest =
  1726. SWAP16((unsigned short) (
  1727. ((r >> 3) << 10) |
  1728. ((g >> 3) << 5) |
  1729. (b >> 3)));
  1730. #endif
  1731. break;
  1732. case GDF_16BIT_565RGB:
  1733. *(unsigned short *) dest =
  1734. SWAP16((unsigned short) (
  1735. ((r >> 3) << 11) |
  1736. ((g >> 2) << 5) |
  1737. (b >> 3)));
  1738. break;
  1739. case GDF_32BIT_X888RGB:
  1740. *(unsigned long *) dest =
  1741. SWAP32((unsigned long) (
  1742. (r << 16) |
  1743. (g << 8) |
  1744. b));
  1745. break;
  1746. case GDF_24BIT_888RGB:
  1747. #ifdef VIDEO_FB_LITTLE_ENDIAN
  1748. dest[0] = b;
  1749. dest[1] = g;
  1750. dest[2] = r;
  1751. #else
  1752. dest[0] = r;
  1753. dest[1] = g;
  1754. dest[2] = b;
  1755. #endif
  1756. break;
  1757. }
  1758. source++;
  1759. dest += VIDEO_PIXEL_SIZE;
  1760. }
  1761. dest += skip;
  1762. }
  1763. #ifdef CONFIG_VIDEO_BMP_LOGO
  1764. free(logo_red);
  1765. free(logo_green);
  1766. free(logo_blue);
  1767. #endif
  1768. }
  1769. static void *video_logo(void)
  1770. {
  1771. char info[128];
  1772. int space, len;
  1773. __maybe_unused int y_off = 0;
  1774. __maybe_unused ulong addr;
  1775. __maybe_unused char *s;
  1776. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  1777. s = getenv("splashpos");
  1778. if (s != NULL) {
  1779. if (s[0] == 'm')
  1780. video_logo_xpos = BMP_ALIGN_CENTER;
  1781. else
  1782. video_logo_xpos = simple_strtol(s, NULL, 0);
  1783. s = strchr(s + 1, ',');
  1784. if (s != NULL) {
  1785. if (s[1] == 'm')
  1786. video_logo_ypos = BMP_ALIGN_CENTER;
  1787. else
  1788. video_logo_ypos = simple_strtol(s + 1, NULL, 0);
  1789. }
  1790. }
  1791. #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
  1792. #ifdef CONFIG_SPLASH_SCREEN
  1793. s = getenv("splashimage");
  1794. if (s != NULL) {
  1795. addr = simple_strtoul(s, NULL, 16);
  1796. if (video_display_bitmap(addr,
  1797. video_logo_xpos,
  1798. video_logo_ypos) == 0) {
  1799. video_logo_height = 0;
  1800. return ((void *) (video_fb_address));
  1801. }
  1802. }
  1803. #endif /* CONFIG_SPLASH_SCREEN */
  1804. logo_plot(video_fb_address, VIDEO_COLS,
  1805. video_logo_xpos, video_logo_ypos);
  1806. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  1807. /*
  1808. * when using splashpos for video_logo, skip any info
  1809. * output on video console if the logo is not at 0,0
  1810. */
  1811. if (video_logo_xpos || video_logo_ypos) {
  1812. /*
  1813. * video_logo_height is used in text and cursor offset
  1814. * calculations. Since the console is below the logo,
  1815. * we need to adjust the logo height
  1816. */
  1817. if (video_logo_ypos == BMP_ALIGN_CENTER)
  1818. video_logo_height += max(0, (VIDEO_VISIBLE_ROWS - \
  1819. VIDEO_LOGO_HEIGHT) / 2);
  1820. else if (video_logo_ypos > 0)
  1821. video_logo_height += video_logo_ypos;
  1822. return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
  1823. }
  1824. #endif
  1825. sprintf(info, " %s", version_string);
  1826. space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
  1827. len = strlen(info);
  1828. if (len > space) {
  1829. video_drawchars(VIDEO_INFO_X, VIDEO_INFO_Y,
  1830. (uchar *) info, space);
  1831. video_drawchars(VIDEO_INFO_X + VIDEO_FONT_WIDTH,
  1832. VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
  1833. (uchar *) info + space, len - space);
  1834. y_off = 1;
  1835. } else
  1836. video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
  1837. #ifdef CONFIG_CONSOLE_EXTRA_INFO
  1838. {
  1839. int i, n =
  1840. ((video_logo_height -
  1841. VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
  1842. for (i = 1; i < n; i++) {
  1843. video_get_info_str(i, info);
  1844. if (!*info)
  1845. continue;
  1846. len = strlen(info);
  1847. if (len > space) {
  1848. video_drawchars(VIDEO_INFO_X,
  1849. VIDEO_INFO_Y +
  1850. (i + y_off) *
  1851. VIDEO_FONT_HEIGHT,
  1852. (uchar *) info, space);
  1853. y_off++;
  1854. video_drawchars(VIDEO_INFO_X +
  1855. VIDEO_FONT_WIDTH,
  1856. VIDEO_INFO_Y +
  1857. (i + y_off) *
  1858. VIDEO_FONT_HEIGHT,
  1859. (uchar *) info + space,
  1860. len - space);
  1861. } else {
  1862. video_drawstring(VIDEO_INFO_X,
  1863. VIDEO_INFO_Y +
  1864. (i + y_off) *
  1865. VIDEO_FONT_HEIGHT,
  1866. (uchar *) info);
  1867. }
  1868. }
  1869. }
  1870. #endif
  1871. return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
  1872. }
  1873. #endif
  1874. static int cfb_fb_is_in_dram(void)
  1875. {
  1876. bd_t *bd = gd->bd;
  1877. #if defined(CONFIG_ARM) || defined(CONFIG_AVR32) || defined(COFNIG_NDS32) || \
  1878. defined(CONFIG_SANDBOX) || defined(CONFIG_X86)
  1879. ulong start, end;
  1880. int i;
  1881. for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
  1882. start = bd->bi_dram[i].start;
  1883. end = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
  1884. if ((ulong)video_fb_address >= start &&
  1885. (ulong)video_fb_address < end)
  1886. return 1;
  1887. }
  1888. #else
  1889. if ((ulong)video_fb_address >= bd->bi_memstart &&
  1890. (ulong)video_fb_address < bd->bi_memstart + bd->bi_memsize)
  1891. return 1;
  1892. #endif
  1893. return 0;
  1894. }
  1895. static int video_init(void)
  1896. {
  1897. unsigned char color8;
  1898. pGD = video_hw_init();
  1899. if (pGD == NULL)
  1900. return -1;
  1901. video_fb_address = (void *) VIDEO_FB_ADRS;
  1902. #ifdef CONFIG_VIDEO_HW_CURSOR
  1903. video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
  1904. #endif
  1905. cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
  1906. /* Init drawing pats */
  1907. switch (VIDEO_DATA_FORMAT) {
  1908. case GDF__8BIT_INDEX:
  1909. video_set_lut(0x01, CONSOLE_FG_COL, CONSOLE_FG_COL,
  1910. CONSOLE_FG_COL);
  1911. video_set_lut(0x00, CONSOLE_BG_COL, CONSOLE_BG_COL,
  1912. CONSOLE_BG_COL);
  1913. fgx = 0x01010101;
  1914. bgx = 0x00000000;
  1915. break;
  1916. case GDF__8BIT_332RGB:
  1917. color8 = ((CONSOLE_FG_COL & 0xe0) |
  1918. ((CONSOLE_FG_COL >> 3) & 0x1c) |
  1919. CONSOLE_FG_COL >> 6);
  1920. fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
  1921. color8;
  1922. color8 = ((CONSOLE_BG_COL & 0xe0) |
  1923. ((CONSOLE_BG_COL >> 3) & 0x1c) |
  1924. CONSOLE_BG_COL >> 6);
  1925. bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
  1926. color8;
  1927. break;
  1928. case GDF_15BIT_555RGB:
  1929. fgx = (((CONSOLE_FG_COL >> 3) << 26) |
  1930. ((CONSOLE_FG_COL >> 3) << 21) |
  1931. ((CONSOLE_FG_COL >> 3) << 16) |
  1932. ((CONSOLE_FG_COL >> 3) << 10) |
  1933. ((CONSOLE_FG_COL >> 3) << 5) |
  1934. (CONSOLE_FG_COL >> 3));
  1935. bgx = (((CONSOLE_BG_COL >> 3) << 26) |
  1936. ((CONSOLE_BG_COL >> 3) << 21) |
  1937. ((CONSOLE_BG_COL >> 3) << 16) |
  1938. ((CONSOLE_BG_COL >> 3) << 10) |
  1939. ((CONSOLE_BG_COL >> 3) << 5) |
  1940. (CONSOLE_BG_COL >> 3));
  1941. break;
  1942. case GDF_16BIT_565RGB:
  1943. fgx = (((CONSOLE_FG_COL >> 3) << 27) |
  1944. ((CONSOLE_FG_COL >> 2) << 21) |
  1945. ((CONSOLE_FG_COL >> 3) << 16) |
  1946. ((CONSOLE_FG_COL >> 3) << 11) |
  1947. ((CONSOLE_FG_COL >> 2) << 5) |
  1948. (CONSOLE_FG_COL >> 3));
  1949. bgx = (((CONSOLE_BG_COL >> 3) << 27) |
  1950. ((CONSOLE_BG_COL >> 2) << 21) |
  1951. ((CONSOLE_BG_COL >> 3) << 16) |
  1952. ((CONSOLE_BG_COL >> 3) << 11) |
  1953. ((CONSOLE_BG_COL >> 2) << 5) |
  1954. (CONSOLE_BG_COL >> 3));
  1955. break;
  1956. case GDF_32BIT_X888RGB:
  1957. fgx = (CONSOLE_FG_COL << 16) |
  1958. (CONSOLE_FG_COL << 8) |
  1959. CONSOLE_FG_COL;
  1960. bgx = (CONSOLE_BG_COL << 16) |
  1961. (CONSOLE_BG_COL << 8) |
  1962. CONSOLE_BG_COL;
  1963. break;
  1964. case GDF_24BIT_888RGB:
  1965. fgx = (CONSOLE_FG_COL << 24) |
  1966. (CONSOLE_FG_COL << 16) |
  1967. (CONSOLE_FG_COL << 8) |
  1968. CONSOLE_FG_COL;
  1969. bgx = (CONSOLE_BG_COL << 24) |
  1970. (CONSOLE_BG_COL << 16) |
  1971. (CONSOLE_BG_COL << 8) |
  1972. CONSOLE_BG_COL;
  1973. break;
  1974. }
  1975. eorx = fgx ^ bgx;
  1976. #ifdef CONFIG_VIDEO_LOGO
  1977. /* Plot the logo and get start point of console */
  1978. debug("Video: Drawing the logo ...\n");
  1979. video_console_address = video_logo();
  1980. #else
  1981. video_console_address = video_fb_address;
  1982. #endif
  1983. /* Initialize the console */
  1984. console_col = 0;
  1985. console_row = 0;
  1986. return 0;
  1987. }
  1988. /*
  1989. * Implement a weak default function for boards that optionally
  1990. * need to skip the video initialization.
  1991. */
  1992. int __board_video_skip(void)
  1993. {
  1994. /* As default, don't skip test */
  1995. return 0;
  1996. }
  1997. int board_video_skip(void)
  1998. __attribute__ ((weak, alias("__board_video_skip")));
  1999. int drv_video_init(void)
  2000. {
  2001. int skip_dev_init;
  2002. struct stdio_dev console_dev;
  2003. /* Check if video initialization should be skipped */
  2004. if (board_video_skip())
  2005. return 0;
  2006. /* Init video chip - returns with framebuffer cleared */
  2007. skip_dev_init = (video_init() == -1);
  2008. #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
  2009. debug("KBD: Keyboard init ...\n");
  2010. skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);
  2011. #endif
  2012. if (skip_dev_init)
  2013. return 0;
  2014. /* Init vga device */
  2015. memset(&console_dev, 0, sizeof(console_dev));
  2016. strcpy(console_dev.name, "vga");
  2017. console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
  2018. console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
  2019. console_dev.putc = video_putc; /* 'putc' function */
  2020. console_dev.puts = video_puts; /* 'puts' function */
  2021. console_dev.tstc = NULL; /* 'tstc' function */
  2022. console_dev.getc = NULL; /* 'getc' function */
  2023. #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
  2024. /* Also init console device */
  2025. console_dev.flags |= DEV_FLAGS_INPUT;
  2026. console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
  2027. console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
  2028. #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
  2029. if (stdio_register(&console_dev) != 0)
  2030. return 0;
  2031. /* Return success */
  2032. return 1;
  2033. }