blob: abe1c799f1d0afca914f667e8e357e458f1cab42 [file] [log] [blame]
Dima Zavind5b0b6a2009-01-15 18:09:25 -08001/*
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 <debug.h>
30#include <err.h>
31#include <stdlib.h>
32#include <dev/fbcon.h>
33
34#include "font5x12.h"
35
36struct pos {
37 int x;
38 int y;
39};
40
41static struct fbcon_config *config = NULL;
42
43#define RGB565_BLUE 0x001f
44#define RGB565_WHITE 0xffff
45
46#define FONT_WIDTH 5
47#define FONT_HEIGHT 12
48
49static uint16_t BGCOLOR;
50static uint16_t FGCOLOR;
51
52static struct pos cur_pos;
53static struct pos max_pos;
54
55static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
56 unsigned *glyph)
57{
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
Dima Zavin25ed9942009-01-28 17:04:19 -080084static void fbcon_flush(void)
85{
86 if (config->update_start)
87 config->update_start();
88 if (config->update_done)
89 while (!config->update_done());
90}
91
Dima Zavind5b0b6a2009-01-15 18:09:25 -080092/* TODO: Take stride into account */
93static void fbcon_scroll_up(void)
94{
95 unsigned short *dst = config->base;
96 unsigned short *src = dst + (config->width * FONT_HEIGHT);
97 unsigned count = config->width * (config->height - FONT_HEIGHT);
98
99 while(count--) {
100 *dst++ = *src++;
101 }
102
103 count = config->width * FONT_HEIGHT;
104 while(count--) {
105 *dst++ = BGCOLOR;
106 }
Dima Zavin25ed9942009-01-28 17:04:19 -0800107
108 fbcon_flush();
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800109}
110
111/* TODO: take stride into account */
112static void fbcon_clear(void)
113{
114 uint16_t *dst = config->base;
115 unsigned count = config->width * config->height;
116
117 cur_pos.x = 0;
118 cur_pos.y = 0;
119
120 while (count--)
121 *dst++ = BGCOLOR;
122}
123
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800124
125static void fbcon_set_colors(unsigned bg, unsigned fg)
126{
127 BGCOLOR = bg;
128 FGCOLOR = fg;
129}
130
131void fbcon_putc(char c)
132{
133 uint16_t *pixels;
134
135 /* ignore anything that happens before fbcon is initialized */
136 if (!config)
137 return;
138
139 if((unsigned char)c > 127)
140 return;
141 if((unsigned char)c < 32) {
142 if(c == '\n')
143 goto newline;
144 else if (c == '\r')
145 cur_pos.x = 0;
146 return;
147 }
148
149 pixels = config->base;
150 pixels += cur_pos.y * FONT_HEIGHT * config->width;
151 pixels += cur_pos.x * (FONT_WIDTH + 1);
152 fbcon_drawglyph(pixels, FGCOLOR, config->stride,
153 font5x12 + (c - 32) * 2);
154
155 cur_pos.x++;
156 if (cur_pos.x < max_pos.x)
157 return;
158
159newline:
160 cur_pos.y++;
161 cur_pos.x = 0;
162 if(cur_pos.y >= max_pos.y) {
163 cur_pos.y = max_pos.y - 1;
164 fbcon_scroll_up();
Dima Zavin25ed9942009-01-28 17:04:19 -0800165 } else
166 fbcon_flush();
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800167}
168
169void fbcon_setup(struct fbcon_config *_config)
170{
171 uint32_t bg;
172 uint32_t fg;
173
174 ASSERT(_config);
175
176 config = _config;
177
178 switch (config->format) {
179 case FB_FORMAT_RGB565:
180 bg = RGB565_BLUE;
181 fg = RGB565_WHITE;
182 break;
183
184 default:
185 dprintf(CRITICAL, "unknown framebuffer pixel format\n");
186 ASSERT(0);
187 break;
188 }
189
190 fbcon_set_colors(bg, fg);
191
192 fbcon_clear();
193 fbcon_flush();
194
195 cur_pos.x = 0;
196 cur_pos.y = 0;
197 max_pos.x = config->width / (FONT_WIDTH+1);
198 max_pos.y = (config->height - 1) / FONT_HEIGHT;
199}