2
* Copyright (c) 2008 Martin Decky
3
* Copyright (c) 2006 Ondrej Palkovsky
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
10
* - Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* - Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* - The name of the author may not be used to endorse or promote products
16
* derived from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
/** @addtogroup genarch
36
#include <genarch/fb/font-8x16.h>
37
#include <genarch/fb/logo-196x66.h>
38
#include <genarch/fb/visuals.h>
39
#include <genarch/fb/fb.h>
40
#include <console/chardev.h>
41
#include <console/console.h>
42
#include <sysinfo/sysinfo.h>
52
#include <arch/types.h>
53
#include <byteorder.h>
55
SPINLOCK_INITIALIZE(fb_lock);
57
static uint8_t *fb_addr;
58
static uint16_t *backbuf;
59
static uint8_t *glyphs;
60
static uint8_t *bgscan;
62
static unsigned int xres;
63
static unsigned int yres;
65
static unsigned int ylogo;
66
static unsigned int ytrim;
67
static unsigned int rowtrim;
69
static unsigned int scanline;
70
static unsigned int glyphscanline;
72
static unsigned int pixelbytes;
73
static unsigned int glyphbytes;
74
static unsigned int bgscanbytes;
76
static unsigned int cols;
77
static unsigned int rows;
78
static unsigned int position = 0;
80
#define BG_COLOR 0x000080
81
#define FG_COLOR 0xffff00
82
#define INV_COLOR 0xaaaaaa
84
#define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
85
#define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
86
#define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
88
#define COL2X(col) ((col) * FONT_WIDTH)
89
#define ROW2Y(row) ((row) * FONT_SCANLINES)
91
#define X2COL(x) ((x) / FONT_WIDTH)
92
#define Y2ROW(y) ((y) / FONT_SCANLINES)
94
#define FB_POS(x, y) ((y) * scanline + (x) * pixelbytes)
95
#define BB_POS(col, row) ((row) * cols + (col))
96
#define GLYPH_POS(glyph, y) ((glyph) * glyphbytes + (y) * glyphscanline)
99
static void (*rgb_conv)(void *, uint32_t);
102
* RGB conversion functions.
104
* These functions write an RGB value to some memory in some predefined format.
105
* The naming convention corresponds to the format created by these functions.
106
* The functions use the so called network order (i.e. big endian) with respect
110
static void rgb_0888(void *dst, uint32_t rgb)
112
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
113
(RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8)));
116
static void bgr_0888(void *dst, uint32_t rgb)
118
*((uint32_t *) dst) = host2uint32_t_be((0 << 24) |
119
(BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8)));
122
static void rgb_8880(void *dst, uint32_t rgb)
124
*((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) |
125
(GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0);
128
static void bgr_8880(void *dst, uint32_t rgb)
130
*((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) |
131
(GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0);
134
static void rgb_888(void *dst, uint32_t rgb)
136
((uint8_t *) dst)[0] = RED(rgb, 8);
137
((uint8_t *) dst)[1] = GREEN(rgb, 8);
138
((uint8_t *) dst)[2] = BLUE(rgb, 8);
141
static void bgr_888(void *dst, uint32_t rgb)
143
((uint8_t *) dst)[0] = BLUE(rgb, 8);
144
((uint8_t *) dst)[1] = GREEN(rgb, 8);
145
((uint8_t *) dst)[2] = RED(rgb, 8);
148
static void rgb_555_be(void *dst, uint32_t rgb)
150
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 |
151
GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
154
static void rgb_555_le(void *dst, uint32_t rgb)
156
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 |
157
GREEN(rgb, 5) << 5 | BLUE(rgb, 5));
160
static void rgb_565_be(void *dst, uint32_t rgb)
162
*((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 |
163
GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
166
static void rgb_565_le(void *dst, uint32_t rgb)
168
*((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 |
169
GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
175
* Even though we try 3:2:3 color scheme here, an 8-bit framebuffer
176
* will most likely use a color palette. The color appearance
177
* will be pretty random and depend on the default installed
178
* palette. This could be fixed by supporting custom palette
179
* and setting it to simulate the 8-bit truecolor.
181
* Currently we set the palette on the ia32, amd64 and sparc64 port.
183
* Note that the byte is being inverted by this function. The reason is
184
* that we would like to use a color palette where the white color code
185
* is 0 and the black color code is 255, as some machines (Sun Blade 1500)
186
* use these codes for black and white and prevent to set codes
187
* 0 and 255 to other colors.
190
static void bgr_323(void *dst, uint32_t rgb)
193
= ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3));
197
/** Hide logo and refresh screen
200
static void logo_hide(bool silent)
210
/** Draw character at given position
213
static void glyph_draw(uint16_t glyph, unsigned int col, unsigned int row, bool silent, bool overlay)
215
unsigned int x = COL2X(col);
216
unsigned int y = ROW2Y(row);
223
backbuf[BB_POS(col, row)] = glyph;
226
for (yd = 0; yd < FONT_SCANLINES; yd++)
227
memcpy(&fb_addr[FB_POS(x, y + yd + ylogo)],
228
&glyphs[GLYPH_POS(glyph, yd)], glyphscanline);
233
/** Scroll screen down by one row
237
static void screen_scroll(bool silent)
247
for (row = 0; row < rows; row++) {
248
unsigned int y = ROW2Y(row);
251
for (yd = 0; yd < FONT_SCANLINES; yd++) {
255
for (col = 0, x = 0; col < cols; col++,
259
if (row < rows - 1) {
260
if (backbuf[BB_POS(col, row)] ==
261
backbuf[BB_POS(col, row + 1)])
264
glyph = backbuf[BB_POS(col, row + 1)];
268
memcpy(&fb_addr[FB_POS(x, y + yd)],
269
&glyphs[GLYPH_POS(glyph, yd)],
276
memmove(backbuf, &backbuf[BB_POS(0, 1)], cols * (rows - 1) * sizeof(uint16_t));
277
memsetw(&backbuf[BB_POS(0, rows - 1)], cols, 0);
281
static void cursor_put(bool silent)
283
unsigned int col = position % cols;
284
unsigned int row = position / cols;
286
glyph_draw(fb_font_glyph(U_CURSOR), col, row, silent, true);
290
static void cursor_remove(bool silent)
292
unsigned int col = position % cols;
293
unsigned int row = position / cols;
295
glyph_draw(backbuf[BB_POS(col, row)], col, row, silent, true);
299
/** Print character to screen
301
* Emulate basic terminal commands.
304
static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent)
306
spinlock_lock(&fb_lock);
310
cursor_remove(silent);
312
position -= position % cols;
315
cursor_remove(silent);
316
position -= position % cols;
319
cursor_remove(silent);
324
cursor_remove(silent);
326
glyph_draw(fb_font_glyph(' '), position % cols,
327
position / cols, silent, false);
329
} while ((position % 8) && (position < cols * rows));
332
glyph_draw(fb_font_glyph(ch), position % cols,
333
position / cols, silent, false);
337
if (position >= cols * rows) {
339
screen_scroll(silent);
344
spinlock_unlock(&fb_lock);
347
static outdev_t fb_console;
348
static outdev_operations_t fb_ops = {
355
* Convert glyphs from device independent font
356
* description to current visual representation.
359
static void glyphs_render(void)
361
/* Prerender glyphs */
364
for (glyph = 0; glyph < FONT_GLYPHS; glyph++) {
367
if (glyph == FONT_GLYPHS - 1)
368
fg_color = INV_COLOR;
374
for (y = 0; y < FONT_SCANLINES; y++) {
377
for (x = 0; x < FONT_WIDTH; x++) {
378
void *dst = &glyphs[GLYPH_POS(glyph, y) +
380
uint32_t rgb = (fb_font[glyph][y] &
381
(1 << (7 - x))) ? fg_color : BG_COLOR;
387
/* Prerender background scanline */
390
for (x = 0; x < xres; x++)
391
rgb_conv(&bgscan[x * pixelbytes], BG_COLOR);
395
/** Refresh the screen
403
for (y = 0; y < LOGO_HEIGHT; y++) {
406
for (x = 0; x < xres; x++)
407
rgb_conv(&fb_addr[FB_POS(x, y)],
409
fb_logo[y * LOGO_WIDTH + x] :
416
for (row = 0; row < rowtrim; row++) {
417
unsigned int y = ylogo + ROW2Y(row);
420
for (yd = 0; yd < FONT_SCANLINES; yd++) {
424
for (col = 0, x = 0; col < cols;
425
col++, x += FONT_WIDTH) {
426
uint16_t glyph = backbuf[BB_POS(col, row)];
427
void *dst = &fb_addr[FB_POS(x, y + yd)];
428
void *src = &glyphs[GLYPH_POS(glyph, yd)];
429
memcpy(dst, src, glyphscanline);
434
if (COL2X(cols) < xres) {
436
unsigned int size = (xres - COL2X(cols)) * pixelbytes;
438
for (y = ylogo; y < yres; y++)
439
memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size);
442
if (ROW2Y(rowtrim) + ylogo < yres) {
445
for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++)
446
memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes);
451
/** Initialize framebuffer as a output character device
453
* @param addr Physical address of the framebuffer
454
* @param x Screen width in pixels
455
* @param y Screen height in pixels
456
* @param scan Bytes per one scanline
457
* @param visual Color model
460
void fb_init(fb_properties_t *props)
462
switch (props->visual) {
463
case VISUAL_INDIRECT_8:
467
case VISUAL_RGB_5_5_5_LE:
468
rgb_conv = rgb_555_le;
471
case VISUAL_RGB_5_5_5_BE:
472
rgb_conv = rgb_555_be;
475
case VISUAL_RGB_5_6_5_LE:
476
rgb_conv = rgb_565_le;
479
case VISUAL_RGB_5_6_5_BE:
480
rgb_conv = rgb_565_be;
483
case VISUAL_RGB_8_8_8:
487
case VISUAL_BGR_8_8_8:
491
case VISUAL_RGB_8_8_8_0:
495
case VISUAL_RGB_0_8_8_8:
499
case VISUAL_BGR_0_8_8_8:
503
case VISUAL_BGR_8_8_8_0:
508
panic("Unsupported visual.");
513
scanline = props->scan;
520
rowtrim = rows - Y2ROW(ylogo);
521
if (ylogo % FONT_SCANLINES > 0)
523
ytrim = ROW2Y(rowtrim);
530
glyphscanline = FONT_WIDTH * pixelbytes;
531
glyphbytes = ROW2Y(glyphscanline);
532
bgscanbytes = xres * pixelbytes;
534
size_t fbsize = scanline * yres;
535
size_t bbsize = cols * rows * sizeof(uint16_t);
536
size_t glyphsize = FONT_GLYPHS * glyphbytes;
538
backbuf = (uint16_t *) malloc(bbsize, 0);
540
panic("Unable to allocate backbuffer.");
542
glyphs = (uint8_t *) malloc(glyphsize, 0);
544
panic("Unable to allocate glyphs.");
546
bgscan = malloc(bgscanbytes, 0);
548
panic("Unable to allocate background pixel.");
550
memsetw(backbuf, cols * rows, 0);
554
fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
556
sysinfo_set_item_val("fb", NULL, true);
557
sysinfo_set_item_val("fb.kind", NULL, 1);
558
sysinfo_set_item_val("fb.width", NULL, xres);
559
sysinfo_set_item_val("fb.height", NULL, yres);
560
sysinfo_set_item_val("fb.scanline", NULL, scanline);
561
sysinfo_set_item_val("fb.visual", NULL, props->visual);
562
sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
566
outdev_initialize("fb", &fb_console, &fb_ops);
567
stdout = &fb_console;