1 /*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <lk/debug.h>
30 #include <lk/err.h>
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <dev/fbcon.h>
34
35 #include "font5x12.h"
36
37 struct pos {
38 int x;
39 int y;
40 };
41
42 static struct fbcon_config *config = NULL;
43
44 #define RGB565_BLUE 0x001f
45 #define RGB565_WHITE 0xffff
46
47 #define FONT_WIDTH 5
48 #define FONT_HEIGHT 12
49
50 static uint16_t BGCOLOR;
51 static uint16_t FGCOLOR;
52
53 static struct pos cur_pos;
54 static struct pos max_pos;
55
fbcon_drawglyph(uint16_t * pixels,uint16_t paint,unsigned stride,unsigned * glyph)56 static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
57 unsigned *glyph) {
58 unsigned x, y, data;
59 stride -= FONT_WIDTH;
60
61 data = glyph[0];
62 for (y = 0; y < (FONT_HEIGHT / 2); ++y) {
63 for (x = 0; x < FONT_WIDTH; ++x) {
64 if (data & 1)
65 *pixels = paint;
66 data >>= 1;
67 pixels++;
68 }
69 pixels += stride;
70 }
71
72 data = glyph[1];
73 for (y = 0; y < (FONT_HEIGHT / 2); y++) {
74 for (x = 0; x < FONT_WIDTH; x++) {
75 if (data & 1)
76 *pixels = paint;
77 data >>= 1;
78 pixels++;
79 }
80 pixels += stride;
81 }
82 }
83
fbcon_flush(void)84 static void fbcon_flush(void) {
85 if (config->update_start)
86 config->update_start();
87 if (config->update_done)
88 while (!config->update_done());
89 }
90
91 /* TODO: Take stride into account */
fbcon_scroll_up(void)92 static void fbcon_scroll_up(void) {
93 unsigned short *dst = config->base;
94 unsigned short *src = dst + (config->width * FONT_HEIGHT);
95 unsigned count = config->width * (config->height - FONT_HEIGHT);
96
97 while (count--) {
98 *dst++ = *src++;
99 }
100
101 count = config->width * FONT_HEIGHT;
102 while (count--) {
103 *dst++ = BGCOLOR;
104 }
105
106 fbcon_flush();
107 }
108
109 /* TODO: take stride into account */
fbcon_clear(void)110 static void fbcon_clear(void) {
111 uint16_t *dst = config->base;
112 unsigned count = config->width * config->height;
113
114 cur_pos.x = 0;
115 cur_pos.y = 0;
116
117 while (count--)
118 *dst++ = BGCOLOR;
119 }
120
121
fbcon_set_colors(unsigned bg,unsigned fg)122 static void fbcon_set_colors(unsigned bg, unsigned fg) {
123 BGCOLOR = bg;
124 FGCOLOR = fg;
125 }
126
fbcon_putc(char c)127 void fbcon_putc(char c) {
128 uint16_t *pixels;
129
130 /* ignore anything that happens before fbcon is initialized */
131 if (!config)
132 return;
133
134 if ((unsigned char)c > 127)
135 return;
136 if ((unsigned char)c < 32) {
137 if (c == '\n')
138 goto newline;
139 else if (c == '\r')
140 cur_pos.x = 0;
141 return;
142 }
143
144 pixels = config->base;
145 pixels += cur_pos.y * FONT_HEIGHT * config->width;
146 pixels += cur_pos.x * (FONT_WIDTH + 1);
147 fbcon_drawglyph(pixels, FGCOLOR, config->stride,
148 font5x12 + (c - 32) * 2);
149
150 cur_pos.x++;
151 if (cur_pos.x < max_pos.x)
152 return;
153
154 newline:
155 cur_pos.y++;
156 cur_pos.x = 0;
157 if (cur_pos.y >= max_pos.y) {
158 cur_pos.y = max_pos.y - 1;
159 fbcon_scroll_up();
160 } else
161 fbcon_flush();
162 }
163
fbcon_setup(struct fbcon_config * _config)164 void fbcon_setup(struct fbcon_config *_config) {
165 uint32_t bg;
166 uint32_t fg;
167
168 ASSERT(_config);
169
170 config = _config;
171
172 switch (config->format) {
173 case FB_FORMAT_RGB565:
174 bg = RGB565_BLUE;
175 fg = RGB565_WHITE;
176 break;
177
178 default:
179 dprintf(CRITICAL, "unknown framebuffer pixel format\n");
180 ASSERT(0);
181 break;
182 }
183
184 fbcon_set_colors(bg, fg);
185
186 fbcon_clear();
187 fbcon_flush();
188
189 cur_pos.x = 0;
190 cur_pos.y = 0;
191 max_pos.x = config->width / (FONT_WIDTH+1);
192 max_pos.y = (config->height - 1) / FONT_HEIGHT;
193 }
194