f87ba6663521acacf11212f7234ce94405615d93
[coreboot.git] / src / pc80 / vga / vga.c
1 /*
2  * Copyright (C)  2007-2009  Luc Verhaegen <libv@skynet.be>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 2 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 51
16  * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <pc80/vga.h>
20 #include <pc80/vga_io.h>
21
22 #include <string.h>
23
24 /*
25  * pci io enable should've happened before
26  */
27 void
28 vga_io_init(void)
29 {
30         vga_enable_mask(0x01, 0x01);
31
32         /* cr io is at 0x3D4/0x3D5 */
33         vga_misc_mask(0x01, 0x01);
34
35         /* clear cr0-7 protection */
36         vga_cr_mask(0x11, 0x00, 0x80);
37 }
38
39 /*
40  *
41  */
42 static void
43 vga_fb_init(void)
44 {
45         vga_sr_write(0x02, 0x03);
46         vga_sr_write(0x03, 0x00);
47         vga_sr_write(0x04, 0x02); /* access all 256kB */
48
49         vga_gr_write(0x00, 0x00);
50         vga_gr_write(0x01, 0x00);
51         vga_gr_write(0x02, 0x00);
52         vga_gr_write(0x03, 0x00);
53         vga_gr_write(0x04, 0x00);
54         vga_gr_write(0x05, 0x10);
55         vga_gr_write(0x06, 0x0E); /* map at 0xB8000 */
56         vga_gr_write(0x07, 0x00);
57         vga_gr_write(0x08, 0xFF);
58
59         /* o/e enable: ram enable */
60         vga_misc_mask(0x22, 0x22);
61 }
62
63 /*
64  *
65  */
66 static void
67 vga_fb_clear(void)
68 {
69         memset((void *)VGA_FB, 0x00, 0x8000);
70 }
71
72 #include "vga_palette.c"
73
74 /*
75  *
76  */
77 static void
78 vga_palette_init(void)
79 {
80         unsigned int i;
81
82         /* set up attribute registers */
83         for (i = 0; i < 0x10; i++)
84                 vga_ar_write(i, i);
85
86         vga_ar_write(0x10, 0x0c);
87         vga_ar_write(0x11, 0x00);
88         vga_ar_write(0x12, 0x0F);
89         vga_ar_write(0x13, 0x08);
90         vga_ar_write(0x14, 0x00);
91
92         vga_palette_disable();
93
94         /* load actual palette */
95         vga_dac_mask_write(0xFF);
96
97         for (i = 0; i < 0x100; i++) {
98                 vga_dac_write_address(i);
99                 vga_dac_data_write(default_vga_palette[i].red);
100                 vga_dac_data_write(default_vga_palette[i].green);
101                 vga_dac_data_write(default_vga_palette[i].blue);
102         }
103 }
104
105 /*
106  *
107  */
108 static void
109 vga_mode_set(int hdisplay, int hblankstart, int hsyncstart, int hsyncend,
110              int hblankend, int htotal, int vdisplay, int vblankstart,
111              int vsyncstart, int vsyncend, int vblankend, int vtotal,
112              int stride)
113 {
114         /* htotal: 2080 */
115         htotal /= 8;
116         htotal -= 5;
117         vga_cr_write(0x00, htotal);
118
119         /* hdisplay: 2048 */
120         hdisplay /= 8;
121         hdisplay -= 1;
122         vga_cr_write(0x01, hdisplay);
123
124         /* hblankstart: 2048 */
125         hblankstart /= 8;
126         hblankstart -= 1;
127         vga_cr_write(0x02, hblankstart);
128
129         /* hblankend: hblankstart + 512 */
130         hblankend /= 8;
131         hblankend -= 1;
132         vga_cr_mask(0x03, hblankend, 0x1F);
133         vga_cr_mask(0x05, hblankend << 2, 0x80);
134
135         /* hsyncstart: 255 * 8: 2040 */
136         vga_cr_write(0x04, hsyncstart / 8);
137
138         /* hsyncend: hsyncstart + 255 */
139         vga_cr_mask(0x05, hsyncend / 8, 0x1F);
140
141         /* vtotal: 1025 */
142         vtotal -= 2;
143         vga_cr_write(0x06, vtotal);
144         vga_cr_mask(0x07, vtotal >> 8, 0x01);
145         vga_cr_mask(0x07, vtotal >> 4, 0x20);
146
147         /* vdisplay: 1024 */
148         vdisplay -= 1;
149         vga_cr_write(0x12, vdisplay);
150         vga_cr_mask(0x07, vdisplay >> 7, 0x02);
151         vga_cr_mask(0x07, vdisplay >> 3, 0x40);
152
153         /* vblankstart: 1024 */
154         vblankstart -= 1;
155         vga_cr_write(0x15, vblankstart);
156         vga_cr_mask(0x07, vblankstart >> 5, 0x08);
157         vga_cr_mask(0x09, vblankstart >> 4, 0x20);
158
159         /* vblankend: vblankstart + 256 */
160         vblankend -= 1;
161         vga_cr_write(0x16, vblankend);
162
163         /* vsyncstart: 1023 */
164         vga_cr_write(0x10, vsyncstart);
165         vga_cr_mask(0x07, vsyncstart >> 6, 0x04);
166         vga_cr_mask(0x07, vsyncstart >> 2, 0x80);
167
168         /* vsyncend: vsyncstart + 16 */
169         vga_cr_mask(0x11, vsyncend, 0x0F);
170
171         /* stride */
172         vga_cr_write(0x13, stride / 8);
173
174         /* line compare */
175         vga_cr_write(0x18, 0xFF);
176         vga_cr_mask(0x07, 0x10, 0x10);
177         vga_cr_mask(0x09, 0x40, 0x40);
178
179         vga_misc_mask(0x44, 0xCC); /* set up clock: 27mhz and h/vsync */
180
181         vga_cr_mask(0x09, 0x00, 0x80); /* disable doublescan */
182 }
183
184 #include "vga_font_8x16.c"
185
186 static void
187 vga_font_8x16_load(void)
188 {
189         unsigned char *p;
190         int i, j;
191         unsigned char sr2, sr4, gr5, gr6;
192
193 #define height 16
194 #define count 256
195
196         sr2 = vga_sr_read(0x02);
197         sr4 = vga_sr_read(0x04);
198         gr5 = vga_gr_read(0x05);
199         gr6 = vga_gr_read(0x06);
200
201         /* disable odd/even */
202         vga_sr_mask(0x04, 0x04, 0x04);
203         vga_gr_mask(0x05, 0x00, 0x10);
204         vga_gr_mask(0x06, 0x00, 0x02);
205
206         /* plane 2 */
207         vga_sr_write(0x02, 0x04);
208         p = (unsigned char *) VGA_FB;
209         for (i = 0; i < count; i++) {
210                 for (j = 0; j < 32; j++) {
211                         if (j < height)
212                                 *p = vga_font_8x16[i][j];
213                         else
214                                 *p = 0x00;
215                         p++;
216                 }
217         }
218
219         vga_gr_write(0x06, gr6);
220         vga_gr_write(0x05, gr5);
221         vga_sr_write(0x04, sr4);
222         vga_sr_write(0x02, sr2);
223
224         /* set up font size */
225         vga_cr_mask(0x09, 16 - 1, 0x1F);
226 }
227
228 /*
229  *
230  */
231 void
232 vga_cursor_enable(int enable)
233 {
234         if (enable)
235                 vga_cr_mask(0x0A, 0x00, 0x20);
236         else
237                 vga_cr_mask(0x0A, 0x20, 0x20);
238 }
239
240 /*
241  *
242  */
243 void
244 vga_cursor_reset(void)
245 {
246         vga_cr_write(0x0A, 0x2E);
247         vga_cr_write(0x0B, 0x0E);
248         vga_cr_write(0x0E, 0x00);
249         vga_cr_write(0x0F, 0x00);
250 }
251
252 /*
253  *
254  */
255 void
256 vga_cursor_set(unsigned int line, unsigned int character)
257 {
258         unsigned int offset = (80 * line + character) & 0xFFFF;
259
260         vga_cr_write(0x0A, 0x0E);
261         vga_cr_write(0x0B, 0x0E);
262         vga_cr_write(0x0E, offset >> 8);
263         vga_cr_write(0x0F, offset & 0xFF);
264 }
265
266 /*
267  *
268  */
269 void
270 vga_frame_set(unsigned int line, unsigned int character)
271 {
272         unsigned int offset = (80 * line + character) & 0xFFFF;
273
274         vga_cr_write(0x0C, offset >> 8);
275         vga_cr_write(0x0D, offset & 0xFF);
276 }
277
278 /*
279  * simply fills a line with the given string.
280  */
281 void
282 vga_line_write(unsigned int line, const char *string)
283 {
284         unsigned short *p = (unsigned short *) VGA_FB + (80 * line);
285         int i, len = strlen(string);
286
287         for (i = 0; i < 80; i++) {
288                 if (i < len)
289                         p[i] = 0x0F00 | string[i];
290                 else
291                         p[i] = 0x0F00;
292         }
293 }
294
295 /*
296  * set up everything to get a basic 80x25 textmode.
297  */
298 void
299 vga_textmode_init(void)
300 {
301         vga_sr_write(0x00, 0x01); /* clear reset */
302         vga_sr_write(0x01, 0x00);
303
304         /* set up cr */
305         vga_cr_mask(0x03, 0x80, 0xE0);
306         vga_cr_mask(0x05, 0x00, 0x60);
307
308         vga_cr_write(0x08, 0x00);
309
310         vga_cr_write(0x14, 0x00); /* */
311
312         vga_cr_write(0x17, 0x23);
313
314         vga_palette_init();
315
316         vga_mode_set(640, 648, 680, 776, 792, 800,
317                      400, 407, 412, 414, 442, 449, 320);
318
319         vga_cursor_reset();
320         vga_frame_set(0, 0);
321
322         vga_fb_init();
323         vga_fb_clear();
324         vga_font_8x16_load();
325
326         vga_sr_mask(0x00, 0x02, 0x02); /* take us out of reset */
327         vga_cr_mask(0x17, 0x80, 0x80); /* sync! */
328 }