cfb_console.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298
  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. #ifdef CONFIG_VIDEO_MXS
  143. #define VIDEO_FB_16BPP_WORD_SWAP
  144. #endif
  145. /*
  146. * Defines for the MB862xx driver
  147. */
  148. #ifdef CONFIG_VIDEO_MB862xx
  149. #ifdef CONFIG_VIDEO_CORALP
  150. #define VIDEO_FB_LITTLE_ENDIAN
  151. #endif
  152. #ifdef CONFIG_VIDEO_MB862xx_ACCEL
  153. #define VIDEO_HW_RECTFILL
  154. #define VIDEO_HW_BITBLT
  155. #endif
  156. #endif
  157. /*
  158. * Defines for the i.MX31 driver (mx3fb.c)
  159. */
  160. #if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
  161. #define VIDEO_FB_16BPP_WORD_SWAP
  162. #endif
  163. /*
  164. * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
  165. */
  166. #include <video_fb.h>
  167. #include <splash.h>
  168. /*
  169. * some Macros
  170. */
  171. #define VIDEO_VISIBLE_COLS (pGD->winSizeX)
  172. #define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
  173. #define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
  174. #define VIDEO_DATA_FORMAT (pGD->gdfIndex)
  175. #define VIDEO_FB_ADRS (pGD->frameAdrs)
  176. /*
  177. * Console device defines with i8042 keyboard controller
  178. * Any other keyboard controller must change this section
  179. */
  180. #ifdef CONFIG_I8042_KBD
  181. #include <i8042.h>
  182. #define VIDEO_KBD_INIT_FCT i8042_kbd_init()
  183. #define VIDEO_TSTC_FCT i8042_tstc
  184. #define VIDEO_GETC_FCT i8042_getc
  185. #endif
  186. /*
  187. * Console device
  188. */
  189. #include <version.h>
  190. #include <linux/types.h>
  191. #include <stdio_dev.h>
  192. #include <video_font.h>
  193. #include <video_font_data.h>
  194. #if defined(CONFIG_CMD_DATE)
  195. #include <rtc.h>
  196. #endif
  197. #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
  198. #include <watchdog.h>
  199. #include <bmp_layout.h>
  200. #include <splash.h>
  201. #endif
  202. /*
  203. * Cursor definition:
  204. * CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/input/i8042.c)
  205. * to let the cursor blink. Uses the macros
  206. * CURSOR_OFF and CURSOR_ON.
  207. * CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No
  208. * blinking is provided. Uses the macros CURSOR_SET
  209. * and CURSOR_OFF.
  210. * CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the
  211. * graphic chip. Uses the macro CURSOR_SET.
  212. * ATTENTION: If booting an OS, the display driver
  213. * must disable the hardware register of the graphic
  214. * chip. Otherwise a blinking field is displayed
  215. */
  216. #if !defined(CONFIG_CONSOLE_CURSOR) && \
  217. !defined(CONFIG_VIDEO_SW_CURSOR) && \
  218. !defined(CONFIG_VIDEO_HW_CURSOR)
  219. /* no Cursor defined */
  220. #define CURSOR_ON
  221. #define CURSOR_OFF
  222. #define CURSOR_SET
  223. #endif
  224. #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
  225. #if defined(CURSOR_ON) || \
  226. (defined(CONFIG_CONSOLE_CURSOR) && defined(CONFIG_VIDEO_SW_CURSOR))
  227. #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
  228. or CONFIG_VIDEO_HW_CURSOR can be defined
  229. #endif
  230. void console_cursor(int state);
  231. #define CURSOR_ON console_cursor(1)
  232. #define CURSOR_OFF console_cursor(0)
  233. #define CURSOR_SET video_set_cursor()
  234. #endif /* CONFIG_CONSOLE_CURSOR || CONFIG_VIDEO_SW_CURSOR */
  235. #ifdef CONFIG_CONSOLE_CURSOR
  236. #ifndef CONFIG_CONSOLE_TIME
  237. #error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
  238. #endif
  239. #ifndef CONFIG_I8042_KBD
  240. #warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
  241. #endif
  242. #endif /* CONFIG_CONSOLE_CURSOR */
  243. #ifdef CONFIG_VIDEO_HW_CURSOR
  244. #ifdef CURSOR_ON
  245. #error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
  246. or CONFIG_VIDEO_HW_CURSOR can be defined
  247. #endif
  248. #define CURSOR_ON
  249. #define CURSOR_OFF
  250. #define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
  251. (console_row * VIDEO_FONT_HEIGHT) + video_logo_height)
  252. #endif /* CONFIG_VIDEO_HW_CURSOR */
  253. #ifdef CONFIG_VIDEO_LOGO
  254. #ifdef CONFIG_VIDEO_BMP_LOGO
  255. #include <bmp_logo.h>
  256. #include <bmp_logo_data.h>
  257. #define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH
  258. #define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT
  259. #define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET
  260. #define VIDEO_LOGO_COLORS BMP_LOGO_COLORS
  261. #else /* CONFIG_VIDEO_BMP_LOGO */
  262. #define LINUX_LOGO_WIDTH 80
  263. #define LINUX_LOGO_HEIGHT 80
  264. #define LINUX_LOGO_COLORS 214
  265. #define LINUX_LOGO_LUT_OFFSET 0x20
  266. #define __initdata
  267. #include <linux_logo.h>
  268. #define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
  269. #define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
  270. #define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
  271. #define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
  272. #endif /* CONFIG_VIDEO_BMP_LOGO */
  273. #define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
  274. #define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
  275. #else /* CONFIG_VIDEO_LOGO */
  276. #define VIDEO_LOGO_WIDTH 0
  277. #define VIDEO_LOGO_HEIGHT 0
  278. #endif /* CONFIG_VIDEO_LOGO */
  279. #define VIDEO_COLS VIDEO_VISIBLE_COLS
  280. #define VIDEO_ROWS VIDEO_VISIBLE_ROWS
  281. #define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
  282. #define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2)
  283. #define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE)
  284. #define VIDEO_BURST_LEN (VIDEO_COLS/8)
  285. #ifdef CONFIG_VIDEO_LOGO
  286. #define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
  287. #else
  288. #define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
  289. #endif
  290. #define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
  291. #define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
  292. #define CONSOLE_ROW_FIRST (video_console_address)
  293. #define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
  294. #define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
  295. #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
  296. #define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
  297. /* Macros */
  298. #ifdef VIDEO_FB_LITTLE_ENDIAN
  299. #define SWAP16(x) ((((x) & 0x00ff) << 8) | \
  300. ((x) >> 8) \
  301. )
  302. #define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
  303. (((x) & 0x0000ff00) << 8) | \
  304. (((x) & 0x00ff0000) >> 8) | \
  305. (((x) & 0xff000000) >> 24) \
  306. )
  307. #define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
  308. (((x) & 0x0000ff00) >> 8) | \
  309. (((x) & 0x00ff0000) << 8) | \
  310. (((x) & 0xff000000) >> 8) \
  311. )
  312. #else
  313. #define SWAP16(x) (x)
  314. #define SWAP32(x) (x)
  315. #if defined(VIDEO_FB_16BPP_WORD_SWAP)
  316. #define SHORTSWAP32(x) (((x) >> 16) | ((x) << 16))
  317. #else
  318. #define SHORTSWAP32(x) (x)
  319. #endif
  320. #endif
  321. #ifdef CONFIG_CONSOLE_EXTRA_INFO
  322. /*
  323. * setup a board string: type, speed, etc.
  324. *
  325. * line_number: location to place info string beside logo
  326. * info: buffer for info string
  327. */
  328. extern void video_get_info_str(int line_number, char *info);
  329. #endif
  330. DECLARE_GLOBAL_DATA_PTR;
  331. /* Locals */
  332. static GraphicDevice *pGD; /* Pointer to Graphic array */
  333. static void *video_fb_address; /* frame buffer address */
  334. static void *video_console_address; /* console buffer start address */
  335. static int video_logo_height = VIDEO_LOGO_HEIGHT;
  336. static int __maybe_unused cursor_state;
  337. static int __maybe_unused old_col;
  338. static int __maybe_unused old_row;
  339. static int console_col; /* cursor col */
  340. static int console_row; /* cursor row */
  341. static u32 eorx, fgx, bgx; /* color pats */
  342. static int cfb_do_flush_cache;
  343. #ifdef CONFIG_CFB_CONSOLE_ANSI
  344. static char ansi_buf[10];
  345. static int ansi_buf_size;
  346. static int ansi_colors_need_revert;
  347. static int ansi_cursor_hidden;
  348. #endif
  349. static const int video_font_draw_table8[] = {
  350. 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
  351. 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
  352. 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
  353. 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
  354. };
  355. static const int video_font_draw_table15[] = {
  356. 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
  357. };
  358. static const int video_font_draw_table16[] = {
  359. 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
  360. };
  361. static const int video_font_draw_table24[16][3] = {
  362. {0x00000000, 0x00000000, 0x00000000},
  363. {0x00000000, 0x00000000, 0x00ffffff},
  364. {0x00000000, 0x0000ffff, 0xff000000},
  365. {0x00000000, 0x0000ffff, 0xffffffff},
  366. {0x000000ff, 0xffff0000, 0x00000000},
  367. {0x000000ff, 0xffff0000, 0x00ffffff},
  368. {0x000000ff, 0xffffffff, 0xff000000},
  369. {0x000000ff, 0xffffffff, 0xffffffff},
  370. {0xffffff00, 0x00000000, 0x00000000},
  371. {0xffffff00, 0x00000000, 0x00ffffff},
  372. {0xffffff00, 0x0000ffff, 0xff000000},
  373. {0xffffff00, 0x0000ffff, 0xffffffff},
  374. {0xffffffff, 0xffff0000, 0x00000000},
  375. {0xffffffff, 0xffff0000, 0x00ffffff},
  376. {0xffffffff, 0xffffffff, 0xff000000},
  377. {0xffffffff, 0xffffffff, 0xffffffff}
  378. };
  379. static const int video_font_draw_table32[16][4] = {
  380. {0x00000000, 0x00000000, 0x00000000, 0x00000000},
  381. {0x00000000, 0x00000000, 0x00000000, 0x00ffffff},
  382. {0x00000000, 0x00000000, 0x00ffffff, 0x00000000},
  383. {0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff},
  384. {0x00000000, 0x00ffffff, 0x00000000, 0x00000000},
  385. {0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff},
  386. {0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000},
  387. {0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff},
  388. {0x00ffffff, 0x00000000, 0x00000000, 0x00000000},
  389. {0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff},
  390. {0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000},
  391. {0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff},
  392. {0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000},
  393. {0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff},
  394. {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000},
  395. {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
  396. };
  397. static void video_drawchars(int xx, int yy, unsigned char *s, int count)
  398. {
  399. u8 *cdat, *dest, *dest0;
  400. int rows, offset, c;
  401. offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
  402. dest0 = video_fb_address + offset;
  403. switch (VIDEO_DATA_FORMAT) {
  404. case GDF__8BIT_INDEX:
  405. case GDF__8BIT_332RGB:
  406. while (count--) {
  407. c = *s;
  408. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  409. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  410. rows--; dest += VIDEO_LINE_LEN) {
  411. u8 bits = *cdat++;
  412. ((u32 *) dest)[0] =
  413. (video_font_draw_table8[bits >> 4] &
  414. eorx) ^ bgx;
  415. ((u32 *) dest)[1] =
  416. (video_font_draw_table8[bits & 15] &
  417. eorx) ^ bgx;
  418. }
  419. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  420. s++;
  421. }
  422. break;
  423. case GDF_15BIT_555RGB:
  424. while (count--) {
  425. c = *s;
  426. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  427. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  428. rows--; dest += VIDEO_LINE_LEN) {
  429. u8 bits = *cdat++;
  430. ((u32 *) dest)[0] =
  431. SHORTSWAP32((video_font_draw_table15
  432. [bits >> 6] & eorx) ^
  433. bgx);
  434. ((u32 *) dest)[1] =
  435. SHORTSWAP32((video_font_draw_table15
  436. [bits >> 4 & 3] & eorx) ^
  437. bgx);
  438. ((u32 *) dest)[2] =
  439. SHORTSWAP32((video_font_draw_table15
  440. [bits >> 2 & 3] & eorx) ^
  441. bgx);
  442. ((u32 *) dest)[3] =
  443. SHORTSWAP32((video_font_draw_table15
  444. [bits & 3] & eorx) ^
  445. bgx);
  446. }
  447. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  448. s++;
  449. }
  450. break;
  451. case GDF_16BIT_565RGB:
  452. while (count--) {
  453. c = *s;
  454. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  455. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  456. rows--; dest += VIDEO_LINE_LEN) {
  457. u8 bits = *cdat++;
  458. ((u32 *) dest)[0] =
  459. SHORTSWAP32((video_font_draw_table16
  460. [bits >> 6] & eorx) ^
  461. bgx);
  462. ((u32 *) dest)[1] =
  463. SHORTSWAP32((video_font_draw_table16
  464. [bits >> 4 & 3] & eorx) ^
  465. bgx);
  466. ((u32 *) dest)[2] =
  467. SHORTSWAP32((video_font_draw_table16
  468. [bits >> 2 & 3] & eorx) ^
  469. bgx);
  470. ((u32 *) dest)[3] =
  471. SHORTSWAP32((video_font_draw_table16
  472. [bits & 3] & eorx) ^
  473. bgx);
  474. }
  475. dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
  476. s++;
  477. }
  478. break;
  479. case GDF_32BIT_X888RGB:
  480. while (count--) {
  481. c = *s;
  482. cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
  483. for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
  484. rows--; dest += VIDEO_LINE_LEN) {
  485. u8 bits = *cdat++;
  486. ((u32 *) dest)[0] =
  487. SWAP32((video_font_draw_table32
  488. [bits >> 4][0] & eorx) ^ bgx);
  489. ((u32 *) dest)[1] =
  490. SWAP32((video_font_draw_table32
  491. [bits >> 4][1] & eorx) ^ bgx);
  492. ((u32 *) dest)[2] =
  493. SWAP32((video_font_draw_table32
  494. [bits >> 4][2] & eorx) ^ bgx);
  495. ((u32 *) dest)[3] =
  496. SWAP32((video_font_draw_table32
  497. [bits >> 4][3] & eorx) ^ bgx);
  498. ((u32 *) dest)[4] =
  499. SWAP32((video_font_draw_table32
  500. [bits & 15][0] & eorx) ^ bgx);
  501. ((u32 *) dest)[5] =
  502. SWAP32((video_font_draw_table32
  503. [bits & 15][1] & eorx) ^ bgx);
  504. ((u32 *) dest)[6] =
  505. SWAP32((video_font_draw_table32
  506. [bits & 15][2] & eorx) ^ bgx);
  507. ((u32 *) dest)[7] =
  508. SWAP32((video_font_draw_table32
  509. [bits & 15][3] & eorx) ^ bgx);
  510. }
  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. }
  574. }
  575. }
  576. void console_cursor(int state)
  577. {
  578. #ifdef CONFIG_CONSOLE_TIME
  579. struct rtc_time tm;
  580. char info[16];
  581. /* time update only if cursor is on (faster scroll) */
  582. if (state) {
  583. rtc_get(&tm);
  584. sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
  585. tm.tm_sec);
  586. video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
  587. VIDEO_INFO_Y, (uchar *) info);
  588. sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
  589. tm.tm_year);
  590. video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
  591. VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT,
  592. (uchar *) info);
  593. }
  594. #endif
  595. if (cursor_state != state) {
  596. if (cursor_state) {
  597. /* turn off the cursor */
  598. video_invertchar(old_col * VIDEO_FONT_WIDTH,
  599. old_row * VIDEO_FONT_HEIGHT +
  600. video_logo_height);
  601. } else {
  602. /* turn off the cursor and record where it is */
  603. video_invertchar(console_col * VIDEO_FONT_WIDTH,
  604. console_row * VIDEO_FONT_HEIGHT +
  605. video_logo_height);
  606. old_col = console_col;
  607. old_row = console_row;
  608. }
  609. cursor_state = state;
  610. }
  611. if (cfb_do_flush_cache)
  612. flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
  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. }
  662. static void console_scrollup(void)
  663. {
  664. /* copy up rows ignoring the first one */
  665. #ifdef VIDEO_HW_BITBLT
  666. video_hw_bitblt(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  667. 0, /* source pos x */
  668. video_logo_height +
  669. VIDEO_FONT_HEIGHT, /* source pos y */
  670. 0, /* dest pos x */
  671. video_logo_height, /* dest pos y */
  672. VIDEO_VISIBLE_COLS, /* frame width */
  673. VIDEO_VISIBLE_ROWS
  674. - video_logo_height
  675. - VIDEO_FONT_HEIGHT /* frame height */
  676. );
  677. #else
  678. memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
  679. CONSOLE_SCROLL_SIZE >> 2);
  680. #endif
  681. /* clear the last one */
  682. console_clear_line(CONSOLE_ROWS - 1, 0, CONSOLE_COLS - 1);
  683. }
  684. static void console_back(void)
  685. {
  686. console_col--;
  687. if (console_col < 0) {
  688. console_col = CONSOLE_COLS - 1;
  689. console_row--;
  690. if (console_row < 0)
  691. console_row = 0;
  692. }
  693. }
  694. #ifdef CONFIG_CFB_CONSOLE_ANSI
  695. static void console_clear(void)
  696. {
  697. #ifdef VIDEO_HW_RECTFILL
  698. video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  699. 0, /* dest pos x */
  700. video_logo_height, /* dest pos y */
  701. VIDEO_VISIBLE_COLS, /* frame width */
  702. VIDEO_VISIBLE_ROWS, /* frame height */
  703. bgx /* fill color */
  704. );
  705. #else
  706. memsetl(CONSOLE_ROW_FIRST, CONSOLE_SIZE, bgx);
  707. #endif
  708. }
  709. static void console_cursor_fix(void)
  710. {
  711. if (console_row < 0)
  712. console_row = 0;
  713. if (console_row >= CONSOLE_ROWS)
  714. console_row = CONSOLE_ROWS - 1;
  715. if (console_col < 0)
  716. console_col = 0;
  717. if (console_col >= CONSOLE_COLS)
  718. console_col = CONSOLE_COLS - 1;
  719. }
  720. static void console_cursor_up(int n)
  721. {
  722. console_row -= n;
  723. console_cursor_fix();
  724. }
  725. static void console_cursor_down(int n)
  726. {
  727. console_row += n;
  728. console_cursor_fix();
  729. }
  730. static void console_cursor_left(int n)
  731. {
  732. console_col -= n;
  733. console_cursor_fix();
  734. }
  735. static void console_cursor_right(int n)
  736. {
  737. console_col += n;
  738. console_cursor_fix();
  739. }
  740. static void console_cursor_set_position(int row, int col)
  741. {
  742. if (console_row != -1)
  743. console_row = row;
  744. if (console_col != -1)
  745. console_col = col;
  746. console_cursor_fix();
  747. }
  748. static void console_previousline(int n)
  749. {
  750. /* FIXME: also scroll terminal ? */
  751. console_row -= n;
  752. console_cursor_fix();
  753. }
  754. static void console_swap_colors(void)
  755. {
  756. eorx = fgx;
  757. fgx = bgx;
  758. bgx = eorx;
  759. eorx = fgx ^ bgx;
  760. }
  761. static inline int console_cursor_is_visible(void)
  762. {
  763. return !ansi_cursor_hidden;
  764. }
  765. #else
  766. static inline int console_cursor_is_visible(void)
  767. {
  768. return 1;
  769. }
  770. #endif
  771. static void console_newline(int n)
  772. {
  773. console_row += n;
  774. console_col = 0;
  775. /* Check if we need to scroll the terminal */
  776. if (console_row >= CONSOLE_ROWS) {
  777. /* Scroll everything up */
  778. console_scrollup();
  779. /* Decrement row number */
  780. console_row = CONSOLE_ROWS - 1;
  781. }
  782. }
  783. static void console_cr(void)
  784. {
  785. console_col = 0;
  786. }
  787. static void parse_putc(const char c)
  788. {
  789. static int nl = 1;
  790. if (console_cursor_is_visible())
  791. CURSOR_OFF;
  792. switch (c) {
  793. case 13: /* back to first column */
  794. console_cr();
  795. break;
  796. case '\n': /* next line */
  797. if (console_col || (!console_col && nl))
  798. console_newline(1);
  799. nl = 1;
  800. break;
  801. case 9: /* tab 8 */
  802. console_col |= 0x0008;
  803. console_col &= ~0x0007;
  804. if (console_col >= CONSOLE_COLS)
  805. console_newline(1);
  806. break;
  807. case 8: /* backspace */
  808. console_back();
  809. break;
  810. case 7: /* bell */
  811. break; /* ignored */
  812. default: /* draw the char */
  813. video_putchar(console_col * VIDEO_FONT_WIDTH,
  814. console_row * VIDEO_FONT_HEIGHT, c);
  815. console_col++;
  816. /* check for newline */
  817. if (console_col >= CONSOLE_COLS) {
  818. console_newline(1);
  819. nl = 0;
  820. }
  821. }
  822. if (console_cursor_is_visible())
  823. CURSOR_SET;
  824. }
  825. void video_putc(const char c)
  826. {
  827. #ifdef CONFIG_CFB_CONSOLE_ANSI
  828. int i;
  829. if (c == 27) {
  830. for (i = 0; i < ansi_buf_size; ++i)
  831. parse_putc(ansi_buf[i]);
  832. ansi_buf[0] = 27;
  833. ansi_buf_size = 1;
  834. return;
  835. }
  836. if (ansi_buf_size > 0) {
  837. /*
  838. * 0 - ESC
  839. * 1 - [
  840. * 2 - num1
  841. * 3 - ..
  842. * 4 - ;
  843. * 5 - num2
  844. * 6 - ..
  845. * - cchar
  846. */
  847. int next = 0;
  848. int flush = 0;
  849. int fail = 0;
  850. int num1 = 0;
  851. int num2 = 0;
  852. int cchar = 0;
  853. ansi_buf[ansi_buf_size++] = c;
  854. if (ansi_buf_size >= sizeof(ansi_buf))
  855. fail = 1;
  856. for (i = 0; i < ansi_buf_size; ++i) {
  857. if (fail)
  858. break;
  859. switch (next) {
  860. case 0:
  861. if (ansi_buf[i] == 27)
  862. next = 1;
  863. else
  864. fail = 1;
  865. break;
  866. case 1:
  867. if (ansi_buf[i] == '[')
  868. next = 2;
  869. else
  870. fail = 1;
  871. break;
  872. case 2:
  873. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  874. num1 = ansi_buf[i]-'0';
  875. next = 3;
  876. } else if (ansi_buf[i] != '?') {
  877. --i;
  878. num1 = 1;
  879. next = 4;
  880. }
  881. break;
  882. case 3:
  883. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  884. num1 *= 10;
  885. num1 += ansi_buf[i]-'0';
  886. } else {
  887. --i;
  888. next = 4;
  889. }
  890. break;
  891. case 4:
  892. if (ansi_buf[i] != ';') {
  893. --i;
  894. next = 7;
  895. } else
  896. next = 5;
  897. break;
  898. case 5:
  899. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  900. num2 = ansi_buf[i]-'0';
  901. next = 6;
  902. } else
  903. fail = 1;
  904. break;
  905. case 6:
  906. if (ansi_buf[i] >= '0' && ansi_buf[i] <= '9') {
  907. num2 *= 10;
  908. num2 += ansi_buf[i]-'0';
  909. } else {
  910. --i;
  911. next = 7;
  912. }
  913. break;
  914. case 7:
  915. if ((ansi_buf[i] >= 'A' && ansi_buf[i] <= 'H')
  916. || ansi_buf[i] == 'J'
  917. || ansi_buf[i] == 'K'
  918. || ansi_buf[i] == 'h'
  919. || ansi_buf[i] == 'l'
  920. || ansi_buf[i] == 'm') {
  921. cchar = ansi_buf[i];
  922. flush = 1;
  923. } else
  924. fail = 1;
  925. break;
  926. }
  927. }
  928. if (fail) {
  929. for (i = 0; i < ansi_buf_size; ++i)
  930. parse_putc(ansi_buf[i]);
  931. ansi_buf_size = 0;
  932. return;
  933. }
  934. if (flush) {
  935. if (!ansi_cursor_hidden)
  936. CURSOR_OFF;
  937. ansi_buf_size = 0;
  938. switch (cchar) {
  939. case 'A':
  940. /* move cursor num1 rows up */
  941. console_cursor_up(num1);
  942. break;
  943. case 'B':
  944. /* move cursor num1 rows down */
  945. console_cursor_down(num1);
  946. break;
  947. case 'C':
  948. /* move cursor num1 columns forward */
  949. console_cursor_right(num1);
  950. break;
  951. case 'D':
  952. /* move cursor num1 columns back */
  953. console_cursor_left(num1);
  954. break;
  955. case 'E':
  956. /* move cursor num1 rows up at begin of row */
  957. console_previousline(num1);
  958. break;
  959. case 'F':
  960. /* move cursor num1 rows down at begin of row */
  961. console_newline(num1);
  962. break;
  963. case 'G':
  964. /* move cursor to column num1 */
  965. console_cursor_set_position(-1, num1-1);
  966. break;
  967. case 'H':
  968. /* move cursor to row num1, column num2 */
  969. console_cursor_set_position(num1-1, num2-1);
  970. break;
  971. case 'J':
  972. /* clear console and move cursor to 0, 0 */
  973. console_clear();
  974. console_cursor_set_position(0, 0);
  975. break;
  976. case 'K':
  977. /* clear line */
  978. if (num1 == 0)
  979. console_clear_line(console_row,
  980. console_col,
  981. CONSOLE_COLS-1);
  982. else if (num1 == 1)
  983. console_clear_line(console_row,
  984. 0, console_col);
  985. else
  986. console_clear_line(console_row,
  987. 0, CONSOLE_COLS-1);
  988. break;
  989. case 'h':
  990. ansi_cursor_hidden = 0;
  991. break;
  992. case 'l':
  993. ansi_cursor_hidden = 1;
  994. break;
  995. case 'm':
  996. if (num1 == 0) { /* reset swapped colors */
  997. if (ansi_colors_need_revert) {
  998. console_swap_colors();
  999. ansi_colors_need_revert = 0;
  1000. }
  1001. } else if (num1 == 7) { /* once swap colors */
  1002. if (!ansi_colors_need_revert) {
  1003. console_swap_colors();
  1004. ansi_colors_need_revert = 1;
  1005. }
  1006. }
  1007. break;
  1008. }
  1009. if (!ansi_cursor_hidden)
  1010. CURSOR_SET;
  1011. }
  1012. } else {
  1013. parse_putc(c);
  1014. }
  1015. #else
  1016. parse_putc(c);
  1017. #endif
  1018. if (cfb_do_flush_cache)
  1019. flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
  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. /*
  1369. * Just ignore elements which are completely beyond screen
  1370. * dimensions.
  1371. */
  1372. if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
  1373. return 0;
  1374. if ((x + width) > VIDEO_VISIBLE_COLS)
  1375. width = VIDEO_VISIBLE_COLS - x;
  1376. if ((y + height) > VIDEO_VISIBLE_ROWS)
  1377. height = VIDEO_VISIBLE_ROWS - y;
  1378. bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
  1379. fb = (uchar *) (video_fb_address +
  1380. ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
  1381. x * VIDEO_PIXEL_SIZE);
  1382. #ifdef CONFIG_VIDEO_BMP_RLE8
  1383. if (compression == BMP_BI_RLE8) {
  1384. return display_rle8_bitmap(bmp, x, y, width, height);
  1385. }
  1386. #endif
  1387. /* We handle only 4, 8, or 24 bpp bitmaps */
  1388. switch (le16_to_cpu(bmp->header.bit_count)) {
  1389. case 4:
  1390. padded_line -= width / 2;
  1391. ycount = height;
  1392. switch (VIDEO_DATA_FORMAT) {
  1393. case GDF_32BIT_X888RGB:
  1394. while (ycount--) {
  1395. WATCHDOG_RESET();
  1396. /*
  1397. * Don't assume that 'width' is an
  1398. * even number
  1399. */
  1400. for (xcount = 0; xcount < width; xcount++) {
  1401. uchar idx;
  1402. if (xcount & 1) {
  1403. idx = *bmap & 0xF;
  1404. bmap++;
  1405. } else
  1406. idx = *bmap >> 4;
  1407. cte = bmp->color_table[idx];
  1408. FILL_32BIT_X888RGB(cte.red, cte.green,
  1409. cte.blue);
  1410. }
  1411. bmap += padded_line;
  1412. fb -= (VIDEO_VISIBLE_COLS + width) *
  1413. VIDEO_PIXEL_SIZE;
  1414. }
  1415. break;
  1416. default:
  1417. puts("4bpp bitmap unsupported with current "
  1418. "video mode\n");
  1419. break;
  1420. }
  1421. break;
  1422. case 8:
  1423. padded_line -= width;
  1424. if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
  1425. /* Copy colormap */
  1426. for (xcount = 0; xcount < colors; ++xcount) {
  1427. cte = bmp->color_table[xcount];
  1428. video_set_lut(xcount, cte.red, cte.green,
  1429. cte.blue);
  1430. }
  1431. }
  1432. ycount = height;
  1433. switch (VIDEO_DATA_FORMAT) {
  1434. case GDF__8BIT_INDEX:
  1435. while (ycount--) {
  1436. WATCHDOG_RESET();
  1437. xcount = width;
  1438. while (xcount--) {
  1439. *fb++ = *bmap++;
  1440. }
  1441. bmap += padded_line;
  1442. fb -= (VIDEO_VISIBLE_COLS + width) *
  1443. VIDEO_PIXEL_SIZE;
  1444. }
  1445. break;
  1446. case GDF__8BIT_332RGB:
  1447. while (ycount--) {
  1448. WATCHDOG_RESET();
  1449. xcount = width;
  1450. while (xcount--) {
  1451. cte = bmp->color_table[*bmap++];
  1452. FILL_8BIT_332RGB(cte.red, cte.green,
  1453. cte.blue);
  1454. }
  1455. bmap += padded_line;
  1456. fb -= (VIDEO_VISIBLE_COLS + width) *
  1457. VIDEO_PIXEL_SIZE;
  1458. }
  1459. break;
  1460. case GDF_15BIT_555RGB:
  1461. while (ycount--) {
  1462. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1463. int xpos = x;
  1464. #endif
  1465. WATCHDOG_RESET();
  1466. xcount = width;
  1467. while (xcount--) {
  1468. cte = bmp->color_table[*bmap++];
  1469. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1470. fill_555rgb_pswap(fb, xpos++, cte.red,
  1471. cte.green,
  1472. cte.blue);
  1473. fb += 2;
  1474. #else
  1475. FILL_15BIT_555RGB(cte.red, cte.green,
  1476. cte.blue);
  1477. #endif
  1478. }
  1479. bmap += padded_line;
  1480. fb -= (VIDEO_VISIBLE_COLS + width) *
  1481. VIDEO_PIXEL_SIZE;
  1482. }
  1483. break;
  1484. case GDF_16BIT_565RGB:
  1485. while (ycount--) {
  1486. WATCHDOG_RESET();
  1487. xcount = width;
  1488. while (xcount--) {
  1489. cte = bmp->color_table[*bmap++];
  1490. FILL_16BIT_565RGB(cte.red, cte.green,
  1491. cte.blue);
  1492. }
  1493. bmap += padded_line;
  1494. fb -= (VIDEO_VISIBLE_COLS + width) *
  1495. VIDEO_PIXEL_SIZE;
  1496. }
  1497. break;
  1498. case GDF_32BIT_X888RGB:
  1499. while (ycount--) {
  1500. WATCHDOG_RESET();
  1501. xcount = width;
  1502. while (xcount--) {
  1503. cte = bmp->color_table[*bmap++];
  1504. FILL_32BIT_X888RGB(cte.red, cte.green,
  1505. cte.blue);
  1506. }
  1507. bmap += padded_line;
  1508. fb -= (VIDEO_VISIBLE_COLS + width) *
  1509. VIDEO_PIXEL_SIZE;
  1510. }
  1511. break;
  1512. case GDF_24BIT_888RGB:
  1513. while (ycount--) {
  1514. WATCHDOG_RESET();
  1515. xcount = width;
  1516. while (xcount--) {
  1517. cte = bmp->color_table[*bmap++];
  1518. FILL_24BIT_888RGB(cte.red, cte.green,
  1519. cte.blue);
  1520. }
  1521. bmap += padded_line;
  1522. fb -= (VIDEO_VISIBLE_COLS + width) *
  1523. VIDEO_PIXEL_SIZE;
  1524. }
  1525. break;
  1526. }
  1527. break;
  1528. case 24:
  1529. padded_line -= 3 * width;
  1530. ycount = height;
  1531. switch (VIDEO_DATA_FORMAT) {
  1532. case GDF__8BIT_332RGB:
  1533. while (ycount--) {
  1534. WATCHDOG_RESET();
  1535. xcount = width;
  1536. while (xcount--) {
  1537. FILL_8BIT_332RGB(bmap[2], bmap[1],
  1538. bmap[0]);
  1539. bmap += 3;
  1540. }
  1541. bmap += padded_line;
  1542. fb -= (VIDEO_VISIBLE_COLS + width) *
  1543. VIDEO_PIXEL_SIZE;
  1544. }
  1545. break;
  1546. case GDF_15BIT_555RGB:
  1547. while (ycount--) {
  1548. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1549. int xpos = x;
  1550. #endif
  1551. WATCHDOG_RESET();
  1552. xcount = width;
  1553. while (xcount--) {
  1554. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1555. fill_555rgb_pswap(fb, xpos++, bmap[2],
  1556. bmap[1], bmap[0]);
  1557. fb += 2;
  1558. #else
  1559. FILL_15BIT_555RGB(bmap[2], bmap[1],
  1560. bmap[0]);
  1561. #endif
  1562. bmap += 3;
  1563. }
  1564. bmap += padded_line;
  1565. fb -= (VIDEO_VISIBLE_COLS + width) *
  1566. VIDEO_PIXEL_SIZE;
  1567. }
  1568. break;
  1569. case GDF_16BIT_565RGB:
  1570. while (ycount--) {
  1571. WATCHDOG_RESET();
  1572. xcount = width;
  1573. while (xcount--) {
  1574. FILL_16BIT_565RGB(bmap[2], bmap[1],
  1575. bmap[0]);
  1576. bmap += 3;
  1577. }
  1578. bmap += padded_line;
  1579. fb -= (VIDEO_VISIBLE_COLS + width) *
  1580. VIDEO_PIXEL_SIZE;
  1581. }
  1582. break;
  1583. case GDF_32BIT_X888RGB:
  1584. while (ycount--) {
  1585. WATCHDOG_RESET();
  1586. xcount = width;
  1587. while (xcount--) {
  1588. FILL_32BIT_X888RGB(bmap[2], bmap[1],
  1589. bmap[0]);
  1590. bmap += 3;
  1591. }
  1592. bmap += padded_line;
  1593. fb -= (VIDEO_VISIBLE_COLS + width) *
  1594. VIDEO_PIXEL_SIZE;
  1595. }
  1596. break;
  1597. case GDF_24BIT_888RGB:
  1598. while (ycount--) {
  1599. WATCHDOG_RESET();
  1600. xcount = width;
  1601. while (xcount--) {
  1602. FILL_24BIT_888RGB(bmap[2], bmap[1],
  1603. bmap[0]);
  1604. bmap += 3;
  1605. }
  1606. bmap += padded_line;
  1607. fb -= (VIDEO_VISIBLE_COLS + width) *
  1608. VIDEO_PIXEL_SIZE;
  1609. }
  1610. break;
  1611. default:
  1612. printf("Error: 24 bits/pixel bitmap incompatible "
  1613. "with current video mode\n");
  1614. break;
  1615. }
  1616. break;
  1617. default:
  1618. printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
  1619. le16_to_cpu(bmp->header.bit_count));
  1620. break;
  1621. }
  1622. #ifdef CONFIG_VIDEO_BMP_GZIP
  1623. if (dst) {
  1624. free(dst);
  1625. }
  1626. #endif
  1627. if (cfb_do_flush_cache)
  1628. flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
  1629. return (0);
  1630. }
  1631. #endif
  1632. #ifdef CONFIG_VIDEO_LOGO
  1633. static int video_logo_xpos;
  1634. static int video_logo_ypos;
  1635. static void plot_logo_or_black(void *screen, int width, int x, int y, \
  1636. int black);
  1637. static void logo_plot(void *screen, int width, int x, int y)
  1638. {
  1639. plot_logo_or_black(screen, width, x, y, 0);
  1640. }
  1641. static void logo_black(void)
  1642. {
  1643. plot_logo_or_black(video_fb_address, \
  1644. VIDEO_COLS, \
  1645. video_logo_xpos, \
  1646. video_logo_ypos, \
  1647. 1);
  1648. }
  1649. static int do_clrlogo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  1650. {
  1651. if (argc != 1)
  1652. return cmd_usage(cmdtp);
  1653. logo_black();
  1654. return 0;
  1655. }
  1656. U_BOOT_CMD(
  1657. clrlogo, 1, 0, do_clrlogo,
  1658. "fill the boot logo area with black",
  1659. " "
  1660. );
  1661. static void plot_logo_or_black(void *screen, int width, int x, int y, int black)
  1662. {
  1663. int xcount, i;
  1664. int skip = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
  1665. int ycount = video_logo_height;
  1666. unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
  1667. unsigned char *source;
  1668. unsigned char *dest;
  1669. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  1670. if (x == BMP_ALIGN_CENTER)
  1671. x = max(0, (VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH) / 2);
  1672. else if (x < 0)
  1673. x = max(0, VIDEO_VISIBLE_COLS - VIDEO_LOGO_WIDTH + x + 1);
  1674. if (y == BMP_ALIGN_CENTER)
  1675. y = max(0, (VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT) / 2);
  1676. else if (y < 0)
  1677. y = max(0, VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT + y + 1);
  1678. #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
  1679. dest = (unsigned char *)screen + (y * width + x) * VIDEO_PIXEL_SIZE;
  1680. #ifdef CONFIG_VIDEO_BMP_LOGO
  1681. source = bmp_logo_bitmap;
  1682. /* Allocate temporary space for computing colormap */
  1683. logo_red = malloc(BMP_LOGO_COLORS);
  1684. logo_green = malloc(BMP_LOGO_COLORS);
  1685. logo_blue = malloc(BMP_LOGO_COLORS);
  1686. /* Compute color map */
  1687. for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
  1688. logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
  1689. logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
  1690. logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
  1691. }
  1692. #else
  1693. source = linux_logo;
  1694. logo_red = linux_logo_red;
  1695. logo_green = linux_logo_green;
  1696. logo_blue = linux_logo_blue;
  1697. #endif
  1698. if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
  1699. for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
  1700. video_set_lut(i + VIDEO_LOGO_LUT_OFFSET,
  1701. logo_red[i], logo_green[i],
  1702. logo_blue[i]);
  1703. }
  1704. }
  1705. while (ycount--) {
  1706. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1707. int xpos = x;
  1708. #endif
  1709. xcount = VIDEO_LOGO_WIDTH;
  1710. while (xcount--) {
  1711. if (black) {
  1712. r = 0x00;
  1713. g = 0x00;
  1714. b = 0x00;
  1715. } else {
  1716. r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
  1717. g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
  1718. b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
  1719. }
  1720. switch (VIDEO_DATA_FORMAT) {
  1721. case GDF__8BIT_INDEX:
  1722. *dest = *source;
  1723. break;
  1724. case GDF__8BIT_332RGB:
  1725. *dest = ((r >> 5) << 5) |
  1726. ((g >> 5) << 2) |
  1727. (b >> 6);
  1728. break;
  1729. case GDF_15BIT_555RGB:
  1730. #if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
  1731. fill_555rgb_pswap(dest, xpos++, r, g, b);
  1732. #else
  1733. *(unsigned short *) dest =
  1734. SWAP16((unsigned short) (
  1735. ((r >> 3) << 10) |
  1736. ((g >> 3) << 5) |
  1737. (b >> 3)));
  1738. #endif
  1739. break;
  1740. case GDF_16BIT_565RGB:
  1741. *(unsigned short *) dest =
  1742. SWAP16((unsigned short) (
  1743. ((r >> 3) << 11) |
  1744. ((g >> 2) << 5) |
  1745. (b >> 3)));
  1746. break;
  1747. case GDF_32BIT_X888RGB:
  1748. *(unsigned long *) dest =
  1749. SWAP32((unsigned long) (
  1750. (r << 16) |
  1751. (g << 8) |
  1752. b));
  1753. break;
  1754. case GDF_24BIT_888RGB:
  1755. #ifdef VIDEO_FB_LITTLE_ENDIAN
  1756. dest[0] = b;
  1757. dest[1] = g;
  1758. dest[2] = r;
  1759. #else
  1760. dest[0] = r;
  1761. dest[1] = g;
  1762. dest[2] = b;
  1763. #endif
  1764. break;
  1765. }
  1766. source++;
  1767. dest += VIDEO_PIXEL_SIZE;
  1768. }
  1769. dest += skip;
  1770. }
  1771. #ifdef CONFIG_VIDEO_BMP_LOGO
  1772. free(logo_red);
  1773. free(logo_green);
  1774. free(logo_blue);
  1775. #endif
  1776. }
  1777. static void *video_logo(void)
  1778. {
  1779. char info[128];
  1780. int space, len;
  1781. __maybe_unused int y_off = 0;
  1782. __maybe_unused ulong addr;
  1783. __maybe_unused char *s;
  1784. splash_get_pos(&video_logo_xpos, &video_logo_ypos);
  1785. #ifdef CONFIG_SPLASH_SCREEN
  1786. s = getenv("splashimage");
  1787. if (s != NULL) {
  1788. splash_screen_prepare();
  1789. addr = simple_strtoul(s, NULL, 16);
  1790. if (video_display_bitmap(addr,
  1791. video_logo_xpos,
  1792. video_logo_ypos) == 0) {
  1793. video_logo_height = 0;
  1794. return ((void *) (video_fb_address));
  1795. }
  1796. }
  1797. #endif /* CONFIG_SPLASH_SCREEN */
  1798. logo_plot(video_fb_address, VIDEO_COLS,
  1799. video_logo_xpos, video_logo_ypos);
  1800. #ifdef CONFIG_SPLASH_SCREEN_ALIGN
  1801. /*
  1802. * when using splashpos for video_logo, skip any info
  1803. * output on video console if the logo is not at 0,0
  1804. */
  1805. if (video_logo_xpos || video_logo_ypos) {
  1806. /*
  1807. * video_logo_height is used in text and cursor offset
  1808. * calculations. Since the console is below the logo,
  1809. * we need to adjust the logo height
  1810. */
  1811. if (video_logo_ypos == BMP_ALIGN_CENTER)
  1812. video_logo_height += max(0, (VIDEO_VISIBLE_ROWS - \
  1813. VIDEO_LOGO_HEIGHT) / 2);
  1814. else if (video_logo_ypos > 0)
  1815. video_logo_height += video_logo_ypos;
  1816. return video_fb_address + video_logo_height * VIDEO_LINE_LEN;
  1817. }
  1818. #endif
  1819. sprintf(info, " %s", version_string);
  1820. space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
  1821. len = strlen(info);
  1822. if (len > space) {
  1823. video_drawchars(VIDEO_INFO_X, VIDEO_INFO_Y,
  1824. (uchar *) info, space);
  1825. video_drawchars(VIDEO_INFO_X + VIDEO_FONT_WIDTH,
  1826. VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
  1827. (uchar *) info + space, len - space);
  1828. y_off = 1;
  1829. } else
  1830. video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
  1831. #ifdef CONFIG_CONSOLE_EXTRA_INFO
  1832. {
  1833. int i, n =
  1834. ((video_logo_height -
  1835. VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
  1836. for (i = 1; i < n; i++) {
  1837. video_get_info_str(i, info);
  1838. if (!*info)
  1839. continue;
  1840. len = strlen(info);
  1841. if (len > space) {
  1842. video_drawchars(VIDEO_INFO_X,
  1843. VIDEO_INFO_Y +
  1844. (i + y_off) *
  1845. VIDEO_FONT_HEIGHT,
  1846. (uchar *) info, space);
  1847. y_off++;
  1848. video_drawchars(VIDEO_INFO_X +
  1849. VIDEO_FONT_WIDTH,
  1850. VIDEO_INFO_Y +
  1851. (i + y_off) *
  1852. VIDEO_FONT_HEIGHT,
  1853. (uchar *) info + space,
  1854. len - space);
  1855. } else {
  1856. video_drawstring(VIDEO_INFO_X,
  1857. VIDEO_INFO_Y +
  1858. (i + y_off) *
  1859. VIDEO_FONT_HEIGHT,
  1860. (uchar *) info);
  1861. }
  1862. }
  1863. }
  1864. #endif
  1865. return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
  1866. }
  1867. #endif
  1868. static int cfb_fb_is_in_dram(void)
  1869. {
  1870. bd_t *bd = gd->bd;
  1871. #if defined(CONFIG_ARM) || defined(CONFIG_AVR32) || defined(COFNIG_NDS32) || \
  1872. defined(CONFIG_SANDBOX) || defined(CONFIG_X86)
  1873. ulong start, end;
  1874. int i;
  1875. for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
  1876. start = bd->bi_dram[i].start;
  1877. end = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
  1878. if ((ulong)video_fb_address >= start &&
  1879. (ulong)video_fb_address < end)
  1880. return 1;
  1881. }
  1882. #else
  1883. if ((ulong)video_fb_address >= bd->bi_memstart &&
  1884. (ulong)video_fb_address < bd->bi_memstart + bd->bi_memsize)
  1885. return 1;
  1886. #endif
  1887. return 0;
  1888. }
  1889. static int video_init(void)
  1890. {
  1891. unsigned char color8;
  1892. pGD = video_hw_init();
  1893. if (pGD == NULL)
  1894. return -1;
  1895. video_fb_address = (void *) VIDEO_FB_ADRS;
  1896. #ifdef CONFIG_VIDEO_HW_CURSOR
  1897. video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
  1898. #endif
  1899. cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status();
  1900. /* Init drawing pats */
  1901. switch (VIDEO_DATA_FORMAT) {
  1902. case GDF__8BIT_INDEX:
  1903. video_set_lut(0x01, CONSOLE_FG_COL, CONSOLE_FG_COL,
  1904. CONSOLE_FG_COL);
  1905. video_set_lut(0x00, CONSOLE_BG_COL, CONSOLE_BG_COL,
  1906. CONSOLE_BG_COL);
  1907. fgx = 0x01010101;
  1908. bgx = 0x00000000;
  1909. break;
  1910. case GDF__8BIT_332RGB:
  1911. color8 = ((CONSOLE_FG_COL & 0xe0) |
  1912. ((CONSOLE_FG_COL >> 3) & 0x1c) |
  1913. CONSOLE_FG_COL >> 6);
  1914. fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
  1915. color8;
  1916. color8 = ((CONSOLE_BG_COL & 0xe0) |
  1917. ((CONSOLE_BG_COL >> 3) & 0x1c) |
  1918. CONSOLE_BG_COL >> 6);
  1919. bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
  1920. color8;
  1921. break;
  1922. case GDF_15BIT_555RGB:
  1923. fgx = (((CONSOLE_FG_COL >> 3) << 26) |
  1924. ((CONSOLE_FG_COL >> 3) << 21) |
  1925. ((CONSOLE_FG_COL >> 3) << 16) |
  1926. ((CONSOLE_FG_COL >> 3) << 10) |
  1927. ((CONSOLE_FG_COL >> 3) << 5) |
  1928. (CONSOLE_FG_COL >> 3));
  1929. bgx = (((CONSOLE_BG_COL >> 3) << 26) |
  1930. ((CONSOLE_BG_COL >> 3) << 21) |
  1931. ((CONSOLE_BG_COL >> 3) << 16) |
  1932. ((CONSOLE_BG_COL >> 3) << 10) |
  1933. ((CONSOLE_BG_COL >> 3) << 5) |
  1934. (CONSOLE_BG_COL >> 3));
  1935. break;
  1936. case GDF_16BIT_565RGB:
  1937. fgx = (((CONSOLE_FG_COL >> 3) << 27) |
  1938. ((CONSOLE_FG_COL >> 2) << 21) |
  1939. ((CONSOLE_FG_COL >> 3) << 16) |
  1940. ((CONSOLE_FG_COL >> 3) << 11) |
  1941. ((CONSOLE_FG_COL >> 2) << 5) |
  1942. (CONSOLE_FG_COL >> 3));
  1943. bgx = (((CONSOLE_BG_COL >> 3) << 27) |
  1944. ((CONSOLE_BG_COL >> 2) << 21) |
  1945. ((CONSOLE_BG_COL >> 3) << 16) |
  1946. ((CONSOLE_BG_COL >> 3) << 11) |
  1947. ((CONSOLE_BG_COL >> 2) << 5) |
  1948. (CONSOLE_BG_COL >> 3));
  1949. break;
  1950. case GDF_32BIT_X888RGB:
  1951. fgx = (CONSOLE_FG_COL << 16) |
  1952. (CONSOLE_FG_COL << 8) |
  1953. CONSOLE_FG_COL;
  1954. bgx = (CONSOLE_BG_COL << 16) |
  1955. (CONSOLE_BG_COL << 8) |
  1956. CONSOLE_BG_COL;
  1957. break;
  1958. case GDF_24BIT_888RGB:
  1959. fgx = (CONSOLE_FG_COL << 24) |
  1960. (CONSOLE_FG_COL << 16) |
  1961. (CONSOLE_FG_COL << 8) |
  1962. CONSOLE_FG_COL;
  1963. bgx = (CONSOLE_BG_COL << 24) |
  1964. (CONSOLE_BG_COL << 16) |
  1965. (CONSOLE_BG_COL << 8) |
  1966. CONSOLE_BG_COL;
  1967. break;
  1968. }
  1969. eorx = fgx ^ bgx;
  1970. #ifdef CONFIG_VIDEO_LOGO
  1971. /* Plot the logo and get start point of console */
  1972. debug("Video: Drawing the logo ...\n");
  1973. video_console_address = video_logo();
  1974. #else
  1975. video_console_address = video_fb_address;
  1976. #endif
  1977. /* Initialize the console */
  1978. console_col = 0;
  1979. console_row = 0;
  1980. if (cfb_do_flush_cache)
  1981. flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
  1982. return 0;
  1983. }
  1984. /*
  1985. * Implement a weak default function for boards that optionally
  1986. * need to skip the video initialization.
  1987. */
  1988. int __board_video_skip(void)
  1989. {
  1990. /* As default, don't skip test */
  1991. return 0;
  1992. }
  1993. int board_video_skip(void)
  1994. __attribute__ ((weak, alias("__board_video_skip")));
  1995. int drv_video_init(void)
  1996. {
  1997. int skip_dev_init;
  1998. struct stdio_dev console_dev;
  1999. /* Check if video initialization should be skipped */
  2000. if (board_video_skip())
  2001. return 0;
  2002. /* Init video chip - returns with framebuffer cleared */
  2003. skip_dev_init = (video_init() == -1);
  2004. #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
  2005. debug("KBD: Keyboard init ...\n");
  2006. skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);
  2007. #endif
  2008. if (skip_dev_init)
  2009. return 0;
  2010. /* Init vga device */
  2011. memset(&console_dev, 0, sizeof(console_dev));
  2012. strcpy(console_dev.name, "vga");
  2013. console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
  2014. console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
  2015. console_dev.putc = video_putc; /* 'putc' function */
  2016. console_dev.puts = video_puts; /* 'puts' function */
  2017. console_dev.tstc = NULL; /* 'tstc' function */
  2018. console_dev.getc = NULL; /* 'getc' function */
  2019. #if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
  2020. /* Also init console device */
  2021. console_dev.flags |= DEV_FLAGS_INPUT;
  2022. console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
  2023. console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
  2024. #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
  2025. if (stdio_register(&console_dev) != 0)
  2026. return 0;
  2027. /* Return success */
  2028. return 1;
  2029. }
  2030. void video_position_cursor(unsigned col, unsigned row)
  2031. {
  2032. console_col = min(col, CONSOLE_COLS - 1);
  2033. console_row = min(row, CONSOLE_ROWS - 1);
  2034. }
  2035. int video_get_pixel_width(void)
  2036. {
  2037. return VIDEO_VISIBLE_COLS;
  2038. }
  2039. int video_get_pixel_height(void)
  2040. {
  2041. return VIDEO_VISIBLE_ROWS;
  2042. }
  2043. int video_get_screen_rows(void)
  2044. {
  2045. return CONSOLE_ROWS;
  2046. }
  2047. int video_get_screen_columns(void)
  2048. {
  2049. return CONSOLE_COLS;
  2050. }
  2051. void video_clear(void)
  2052. {
  2053. if (!video_fb_address)
  2054. return;
  2055. #ifdef VIDEO_HW_RECTFILL
  2056. video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
  2057. 0, /* dest pos x */
  2058. 0, /* dest pos y */
  2059. VIDEO_VISIBLE_COLS, /* frame width */
  2060. VIDEO_VISIBLE_ROWS, /* frame height */
  2061. bgx /* fill color */
  2062. );
  2063. #else
  2064. memsetl(video_fb_address,
  2065. (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), bgx);
  2066. #endif
  2067. }