First version
[3rdparty/ote_partner/tlk.git] / dev / fbcon / fbcon.c
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 <debug.h>
30 #include <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
56 static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
57                             unsigned *glyph)
58 {
59         unsigned x, y, data;
60         stride -= FONT_WIDTH;
61
62         data = glyph[0];
63         for (y = 0; y < (FONT_HEIGHT / 2); ++y) {
64                 for (x = 0; x < FONT_WIDTH; ++x) {
65                         if (data & 1)
66                                 *pixels = paint;
67                         data >>= 1;
68                         pixels++;
69                 }
70                 pixels += stride;
71         }
72
73         data = glyph[1];
74         for (y = 0; y < (FONT_HEIGHT / 2); y++) {
75                 for (x = 0; x < FONT_WIDTH; x++) {
76                         if (data & 1)
77                                 *pixels = paint;
78                         data >>= 1;
79                         pixels++;
80                 }
81                 pixels += stride;
82         }
83 }
84
85 static void fbcon_flush(void)
86 {
87         if (config->update_start)
88                 config->update_start();
89         if (config->update_done)
90                 while (!config->update_done());
91 }
92
93 /* TODO: Take stride into account */
94 static void fbcon_scroll_up(void)
95 {
96         unsigned short *dst = config->base;
97         unsigned short *src = dst + (config->width * FONT_HEIGHT);
98         unsigned count = config->width * (config->height - FONT_HEIGHT);
99
100         while(count--) {
101                 *dst++ = *src++;
102         }
103
104         count = config->width * FONT_HEIGHT;
105         while(count--) {
106                 *dst++ = BGCOLOR;
107         }
108
109         fbcon_flush();
110 }
111
112 /* TODO: take stride into account */
113 static void fbcon_clear(void)
114 {
115         uint16_t *dst = config->base;
116         unsigned count = config->width * config->height;
117
118         cur_pos.x = 0;
119         cur_pos.y = 0;
120
121         while (count--)
122                 *dst++ = BGCOLOR;
123 }
124
125
126 static void fbcon_set_colors(unsigned bg, unsigned fg)
127 {
128         BGCOLOR = bg;
129         FGCOLOR = fg;
130 }
131
132 void fbcon_putc(char c)
133 {
134         uint16_t *pixels;
135
136         /* ignore anything that happens before fbcon is initialized */
137         if (!config)
138                 return;
139
140         if((unsigned char)c > 127)
141                 return;
142         if((unsigned char)c < 32) {
143                 if(c == '\n')
144                         goto newline;
145                 else if (c == '\r')
146                         cur_pos.x = 0;
147                 return;
148         }
149
150         pixels = config->base;
151         pixels += cur_pos.y * FONT_HEIGHT * config->width;
152         pixels += cur_pos.x * (FONT_WIDTH + 1);
153         fbcon_drawglyph(pixels, FGCOLOR, config->stride,
154                         font5x12 + (c - 32) * 2);
155
156         cur_pos.x++;
157         if (cur_pos.x < max_pos.x)
158                 return;
159
160 newline:
161         cur_pos.y++;
162         cur_pos.x = 0;
163         if(cur_pos.y >= max_pos.y) {
164                 cur_pos.y = max_pos.y - 1;
165                 fbcon_scroll_up();
166         } else
167                 fbcon_flush();
168 }
169
170 void fbcon_setup(struct fbcon_config *_config)
171 {
172         uint32_t bg;
173         uint32_t fg;
174
175         ASSERT(_config);
176
177         config = _config;
178
179         switch (config->format) {
180         case FB_FORMAT_RGB565:
181                 bg = RGB565_BLUE;
182                 fg = RGB565_WHITE;
183                 break;
184
185         default:
186                 dprintf(CRITICAL, "unknown framebuffer pixel format\n");
187                 ASSERT(0);
188                 break;
189         }
190
191         fbcon_set_colors(bg, fg);
192
193         fbcon_clear();
194         fbcon_flush();
195
196         cur_pos.x = 0;
197         cur_pos.y = 0;
198         max_pos.x = config->width / (FONT_WIDTH+1);
199         max_pos.y = (config->height - 1) / FONT_HEIGHT;
200 }