tizen 2.3.1 release
[platform/kernel/u-boot.git] / drivers / video / fbutils.c
1 /*
2  * Font module for Framebuffer.
3  *
4  * Copyright(C) 2009 Samsung Electronics
5  * InKi Dae <inki.dae@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <config.h>
24 #include <common.h>
25 #include <version.h>
26 #include <stdarg.h>
27 #include <malloc.h>
28 #include <linux/types.h>
29 #include <asm/io.h>
30 #include <lcd.h>
31 #include <asm/global_data.h>
32
33 #include <fbutils.h>
34
35 #define XORMODE                 0x80000000
36 #define CARRIAGE_RETURN         10
37 #define HORIZONTAL_TAP          9
38
39 extern struct fbcon_font_desc font_vga_8x16;
40 extern vidinfo_t panel_info;
41
42 union multiptr {
43         unsigned char *p8;
44         unsigned short *p16;
45         unsigned long *p32;
46 };
47
48 static int bytes_per_pixel;
49 static unsigned char **line_addr;
50
51 static unsigned int g_default_x, g_default_y;
52 static unsigned int color_index;
53
54 static unsigned colormap [256];
55 extern vidinfo_t panel_info;
56
57 static char red_length = 8, red_offset = 16;
58 static char green_length = 8, green_offset = 8;
59 static char blue_length = 8, blue_offset = 0;
60
61 static unsigned int color_table_8[MAX_INDEX_TABLE] ={
62         0x000000,       /* BLACK */
63         0xff0000,       /* RED */
64         0x00ff00,       /* GREEN */
65         0x0000ff,       /* BLUE */
66         0xffff00,       /* YELLOW */
67         0xff00ff,       /* MAGENTA */
68         0x00ffff,       /* AQUA */
69         0xffffff,       /* WHITE */
70         0x80000000      /* XORMODE */
71 };
72
73 static unsigned int g_x, g_y;
74
75 void set_font_color(unsigned char index)
76 {
77         if (index < 0 || index > 8) {
78                 printf("index is invalid.\n");
79                 return;
80         }
81
82         color_index = index;
83 }
84
85 static void set_color_table(unsigned colidx, unsigned value)
86 {
87         unsigned res;
88         unsigned short red, green, blue;
89
90         switch (bytes_per_pixel) {
91         case 2:
92         case 4:
93                 red = (value >> 16) & 0xff;
94                 green = (value >> 8) & 0xff;
95                 blue = value & 0xff;
96                 res = ((red >> (8 - red_length)) << red_offset) |
97                       ((green >> (8 - green_length)) << green_offset) |
98                       ((blue >> (8 - blue_length)) << blue_offset);
99                 break;
100         default:
101                 printf("bpp %d is invalid.\n", bytes_per_pixel);
102                 break;
103         }
104
105         colormap [colidx] = res;
106 }
107
108 static void make_color_table(void)
109 {
110         int i;
111
112         for(i = 0; i < MAX_INDEX_TABLE; i++)
113                 set_color_table(i, color_table_8[i]);
114 }
115
116 void set_font_xy(unsigned int x, unsigned int y)
117 {
118         g_default_x = x;
119         g_default_y = y;
120
121         /* it needs handling for exception */
122
123         g_x = x;
124         g_y = y;
125 }
126
127 void get_font_xy(unsigned int *x, unsigned int *y)
128 {
129         *x = g_x;
130         *y = g_y;
131 }
132
133 static inline void __setpixel (union multiptr loc, unsigned xormode, unsigned color)
134 {
135         switch(bytes_per_pixel) {
136         case 1:
137         default:
138                 if (xormode)
139                         *loc.p8 ^= color;
140                 else
141                         *loc.p8 = color;
142                 break;
143         case 2:
144                 if (xormode)
145                         *loc.p16 ^= color;
146                 else
147                         *loc.p16 = color;
148                 break;
149         case 4:
150                 if (xormode)
151                         *loc.p32 ^= color;
152                 else
153                         *loc.p32 = color;
154                 break;
155         }
156 }
157
158 static void pixel(int x, int y)
159 {
160         unsigned int xormode;
161         union multiptr loc;
162
163         if ((x < 0) || ((__u32)x >= panel_info.vl_width) ||
164             (y < 0) || ((__u32)y >= panel_info.vl_height))
165                 return;
166
167         xormode = (unsigned int)(color_index & XORMODE);
168         color_index &= (unsigned int)~XORMODE;
169
170         loc.p8 = line_addr [y] + x * bytes_per_pixel;
171         __setpixel (loc, xormode, colormap[color_index]);
172 }
173
174 static void put_char(int c)
175 {
176         int i,j,bits;
177
178         if (c == CARRIAGE_RETURN) {
179                 g_y += font_vga_8x16.height;
180                 g_x = g_default_x - font_vga_8x16.width;
181                 return;
182         }
183
184         if (c == HORIZONTAL_TAP) {
185                 g_x += 20;
186                 return;
187         }
188
189         /* check x-axis limitation. */
190         if (g_x > panel_info.vl_width - font_vga_8x16.width) {
191                 g_x = g_default_x;
192                 g_y += font_vga_8x16.height;
193         }
194
195         for (i = 0; i < font_vga_8x16.height; i++) {
196                 bits = font_vga_8x16.data [font_vga_8x16.height * c + i];
197                 for (j = 0; j < font_vga_8x16.width; j++, bits <<= 1) {
198                                 if (bits & 0x80)
199                                         pixel (g_x + j, g_y + i);
200                 }
201         }
202 }
203
204 static void put_char_rotate(int c)
205 {
206         int i,j,bits;
207
208         if (c == CARRIAGE_RETURN) {
209                 g_y += font_vga_8x16.height;
210                 g_x = g_default_x - font_vga_8x16.width;
211                 return;
212         }
213
214         if (c == HORIZONTAL_TAP) {
215                 g_y += 20;
216                 return;
217         }
218
219         /* check y-axis limitation. */
220         if (g_x > panel_info.vl_height) {
221                 g_x = g_default_x;
222                 g_y += font_vga_8x16.height;
223         }
224
225         for (i = 0; i < font_vga_8x16.height; i++) {
226                 bits = font_vga_8x16.data [font_vga_8x16.height * c + i];
227                 for (j = 0; j < font_vga_8x16.width; j++, bits <<= 1) {
228                                 if (bits & 0x80)
229                                         pixel (panel_info.vl_width - (g_y + i), g_x + j);
230                 }
231         }
232 }
233
234 void fb_printf(char *s)
235 {
236         int i;
237
238         for (i = 0; *s; i++, g_x += font_vga_8x16.width, s++) {
239                 if (panel_info.lcd_rotate == SCREEN_NORMAL)
240                         put_char (*s);
241                 else
242                         put_char_rotate(*s);
243         }
244 }
245
246 #if 0
247 static void draw_ve_wheel(int x, int y, unsigned char color)
248 {
249         set_font_xy(x, y);
250         set_font_color(FONT_XOR);
251         fb_printf(" | ");
252         set_font_xy(x, y + 6);
253         fb_printf(" | ");
254
255         set_font_color(color);
256         set_font_xy(x, y + 2);
257         fb_printf("---");
258 }
259
260 static void draw_ho_wheel(int x, int y, unsigned char color)
261 {
262         set_font_xy(x, y + 2);
263         set_font_color(FONT_XOR);
264         fb_printf("---");
265
266         set_font_color(color);
267         set_font_xy(x, y);
268         fb_printf(" | ");
269         set_font_xy(x, y + 6);
270         fb_printf(" | ");
271 }
272
273 void draw_wheel(int x, int y, unsigned char color)
274 {
275         static int sw = 1;
276
277         if (sw)
278                 draw_ve_wheel(x, y, color);
279         else
280                 draw_ho_wheel(x, y, color);
281
282         if (sw)
283                 sw = 0;
284         else
285                 sw = 1;
286 }
287 #endif
288
289 void draw_progress(int y, int per, unsigned char color)
290 {
291         int i;
292         int num;
293         int chars;
294         static char buf[128] ={0,};
295         char per_buf[8];
296
297         set_font_xy(0, y);
298         set_font_color(FONT_XOR);
299         fb_printf(buf);
300         memset(buf, 0x0, 64);
301
302         if (panel_info.lcd_rotate == SCREEN_NORMAL)
303                 chars = panel_info.vl_width / font_vga_8x16.width - 7;
304         else
305                 chars = panel_info.vl_height / font_vga_8x16.width - 7;
306
307         num = (per * 100) / (10000 / chars);
308
309         sprintf(buf, "[");
310
311         for (i = 0; i < num; i++)
312                 strcat(buf, "=");
313
314         sprintf(per_buf, ">%3d%%", per);
315         strcat(buf, per_buf);
316
317         num = chars - num;
318
319         for (i = 0; i < num; i++)
320                 strcat(buf, " ");
321
322         strcat(buf, "]");
323
324         set_font_color(color);
325         set_font_xy(0, y);
326         fb_printf(buf);
327 }
328
329 DECLARE_GLOBAL_DATA_PTR;
330
331 void init_font(void)
332 {
333         int addr = 0, y;
334         int line_length;
335
336         line_length = panel_info.vl_width * 4;
337         bytes_per_pixel = panel_info.vl_bpix / 8;
338
339         line_addr = (unsigned char **)malloc(sizeof(__u32) * panel_info.vl_height);
340
341         for (y = 0; y < panel_info.vl_height; y++, addr += line_length) {
342                 line_addr[y] = (unsigned char *)(gd->fb_base + addr);
343         }
344
345         make_color_table();
346 }
347
348 void exit_font(void)
349 {
350         if (line_addr)
351                 free(line_addr);
352
353         g_default_x = g_default_y = 0;
354         g_x = g_y = 0;
355 }
356
357 void fb_clear(int range)
358 {
359         int y;
360         int line_length = panel_info.vl_width * 4;
361
362         if (!range)
363                 range = panel_info.vl_height;
364
365         for (y = 0; y < range; y++)
366                 memset(line_addr[y], 0x0, line_length);
367 }
368
369 unsigned int get_chars(void)
370 {
371         int chars;
372         int lines;
373
374         chars = panel_info.vl_width / font_vga_8x16.width - 3;
375         lines = panel_info.vl_height  / font_vga_8x16.height;
376
377         return chars * lines;
378 }