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