cfb_console.c 46 KB

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