cfb_console.c 54 KB

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