xref: /openbmc/linux/arch/x86/boot/video-vga.c (revision 78c99ba1)
1 /* -*- linux-c -*- ------------------------------------------------------- *
2  *
3  *   Copyright (C) 1991, 1992 Linus Torvalds
4  *   Copyright 2007 rPath, Inc. - All Rights Reserved
5  *   Copyright 2009 Intel Corporation; author H. Peter Anvin
6  *
7  *   This file is part of the Linux kernel, and is made available under
8  *   the terms of the GNU General Public License version 2.
9  *
10  * ----------------------------------------------------------------------- */
11 
12 /*
13  * Common all-VGA modes
14  */
15 
16 #include "boot.h"
17 #include "video.h"
18 
19 static struct mode_info vga_modes[] = {
20 	{ VIDEO_80x25,  80, 25, 0 },
21 	{ VIDEO_8POINT, 80, 50, 0 },
22 	{ VIDEO_80x43,  80, 43, 0 },
23 	{ VIDEO_80x28,  80, 28, 0 },
24 	{ VIDEO_80x30,  80, 30, 0 },
25 	{ VIDEO_80x34,  80, 34, 0 },
26 	{ VIDEO_80x60,  80, 60, 0 },
27 };
28 
29 static struct mode_info ega_modes[] = {
30 	{ VIDEO_80x25,  80, 25, 0 },
31 	{ VIDEO_8POINT, 80, 43, 0 },
32 };
33 
34 static struct mode_info cga_modes[] = {
35 	{ VIDEO_80x25,  80, 25, 0 },
36 };
37 
38 static __videocard video_vga;
39 
40 /* Set basic 80x25 mode */
41 static u8 vga_set_basic_mode(void)
42 {
43 	struct biosregs ireg, oreg;
44 	u16 ax;
45 	u8 rows;
46 	u8 mode;
47 
48 	initregs(&ireg);
49 
50 #ifdef CONFIG_VIDEO_400_HACK
51 	if (adapter >= ADAPTER_VGA) {
52 		ireg.ax = 0x1202;
53 		ireg.bx = 0x0030;
54 		intcall(0x10, &ireg, NULL);
55 	}
56 #endif
57 
58 	ax = 0x0f00;
59 	intcall(0x10, &ireg, &oreg);
60 	mode = oreg.al;
61 
62 	set_fs(0);
63 	rows = rdfs8(0x484);	/* rows minus one */
64 
65 #ifndef CONFIG_VIDEO_400_HACK
66 	if ((oreg.ax == 0x5003 || oreg.ax == 0x5007) &&
67 	    (rows == 0 || rows == 24))
68 		return mode;
69 #endif
70 
71 	if (mode != 3 && mode != 7)
72 		mode = 3;
73 
74 	/* Set the mode */
75 	ireg.ax = mode;		/* AH=0: set mode */
76 	intcall(0x10, &ireg, NULL);
77 	do_restore = 1;
78 	return mode;
79 }
80 
81 static void vga_set_8font(void)
82 {
83 	/* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
84 	struct biosregs ireg;
85 
86 	initregs(&ireg);
87 
88 	/* Set 8x8 font */
89 	ireg.ax = 0x1112;
90 	/* ireg.bl = 0; */
91 	intcall(0x10, &ireg, NULL);
92 
93 	/* Use alternate print screen */
94 	ireg.ax = 0x1200;
95 	ireg.bl = 0x20;
96 	intcall(0x10, &ireg, NULL);
97 
98 	/* Turn off cursor emulation */
99 	ireg.ax = 0x1201;
100 	ireg.bl = 0x34;
101 	intcall(0x10, &ireg, NULL);
102 
103 	/* Cursor is scan lines 6-7 */
104 	ireg.ax = 0x0100;
105 	ireg.cx = 0x0607;
106 	intcall(0x10, &ireg, NULL);
107 }
108 
109 static void vga_set_14font(void)
110 {
111 	/* Set 9x14 font - 80x28 on VGA */
112 	struct biosregs ireg;
113 
114 	initregs(&ireg);
115 
116 	/* Set 9x14 font */
117 	ireg.ax = 0x1111;
118 	/* ireg.bl = 0; */
119 	intcall(0x10, &ireg, NULL);
120 
121 	/* Turn off cursor emulation */
122 	ireg.ax = 0x1201;
123 	ireg.bl = 0x34;
124 	intcall(0x10, &ireg, NULL);
125 
126 	/* Cursor is scan lines 11-12 */
127 	ireg.ax = 0x0100;
128 	ireg.cx = 0x0b0c;
129 	intcall(0x10, &ireg, NULL);
130 }
131 
132 static void vga_set_80x43(void)
133 {
134 	/* Set 80x43 mode on VGA (not EGA) */
135 	struct biosregs ireg;
136 
137 	initregs(&ireg);
138 
139 	/* Set 350 scans */
140 	ireg.ax = 0x1201;
141 	ireg.bl = 0x30;
142 	intcall(0x10, &ireg, NULL);
143 
144 	/* Reset video mode */
145 	ireg.ax = 0x0003;
146 	intcall(0x10, &ireg, NULL);
147 
148 	vga_set_8font();
149 }
150 
151 /* I/O address of the VGA CRTC */
152 u16 vga_crtc(void)
153 {
154 	return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
155 }
156 
157 static void vga_set_480_scanlines(void)
158 {
159 	u16 crtc;		/* CRTC base address */
160 	u8  csel;		/* CRTC miscellaneous output register */
161 
162 	crtc = vga_crtc();
163 
164 	out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
165 	out_idx(0x0b, crtc, 0x06); /* Vertical total */
166 	out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
167 	out_idx(0xea, crtc, 0x10); /* Vertical sync start */
168 	out_idx(0xdf, crtc, 0x12); /* Vertical display end */
169 	out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
170 	out_idx(0x04, crtc, 0x16); /* Vertical blank end */
171 	csel = inb(0x3cc);
172 	csel &= 0x0d;
173 	csel |= 0xe2;
174 	outb(csel, 0x3c2);
175 }
176 
177 static void vga_set_vertical_end(int lines)
178 {
179 	u16 crtc;		/* CRTC base address */
180 	u8  ovfw;		/* CRTC overflow register */
181 	int end = lines-1;
182 
183 	crtc = vga_crtc();
184 
185 	ovfw = 0x3c | ((end >> (8-1)) & 0x02) | ((end >> (9-6)) & 0x40);
186 
187 	out_idx(ovfw, crtc, 0x07); /* Vertical overflow */
188 	out_idx(end,  crtc, 0x12); /* Vertical display end */
189 }
190 
191 static void vga_set_80x30(void)
192 {
193 	vga_set_480_scanlines();
194 	vga_set_vertical_end(30*16);
195 }
196 
197 static void vga_set_80x34(void)
198 {
199 	vga_set_480_scanlines();
200 	vga_set_14font();
201 	vga_set_vertical_end(34*14);
202 }
203 
204 static void vga_set_80x60(void)
205 {
206 	vga_set_480_scanlines();
207 	vga_set_8font();
208 	vga_set_vertical_end(60*8);
209 }
210 
211 static int vga_set_mode(struct mode_info *mode)
212 {
213 	/* Set the basic mode */
214 	vga_set_basic_mode();
215 
216 	/* Override a possibly broken BIOS */
217 	force_x = mode->x;
218 	force_y = mode->y;
219 
220 	switch (mode->mode) {
221 	case VIDEO_80x25:
222 		break;
223 	case VIDEO_8POINT:
224 		vga_set_8font();
225 		break;
226 	case VIDEO_80x43:
227 		vga_set_80x43();
228 		break;
229 	case VIDEO_80x28:
230 		vga_set_14font();
231 		break;
232 	case VIDEO_80x30:
233 		vga_set_80x30();
234 		break;
235 	case VIDEO_80x34:
236 		vga_set_80x34();
237 		break;
238 	case VIDEO_80x60:
239 		vga_set_80x60();
240 		break;
241 	}
242 
243 	return 0;
244 }
245 
246 /*
247  * Note: this probe includes basic information required by all
248  * systems.  It should be executed first, by making sure
249  * video-vga.c is listed first in the Makefile.
250  */
251 static int vga_probe(void)
252 {
253 	static const char *card_name[] = {
254 		"CGA/MDA/HGC", "EGA", "VGA"
255 	};
256 	static struct mode_info *mode_lists[] = {
257 		cga_modes,
258 		ega_modes,
259 		vga_modes,
260 	};
261 	static int mode_count[] = {
262 		sizeof(cga_modes)/sizeof(struct mode_info),
263 		sizeof(ega_modes)/sizeof(struct mode_info),
264 		sizeof(vga_modes)/sizeof(struct mode_info),
265 	};
266 
267 	struct biosregs ireg, oreg;
268 
269 	initregs(&ireg);
270 
271 	ireg.ax = 0x1200;
272 	ireg.bl = 0x10;		/* Check EGA/VGA */
273 	intcall(0x10, &ireg, &oreg);
274 
275 #ifndef _WAKEUP
276 	boot_params.screen_info.orig_video_ega_bx = oreg.bx;
277 #endif
278 
279 	/* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
280 	if (oreg.bl != 0x10) {
281 		/* EGA/VGA */
282 		ireg.ax = 0x1a00;
283 		intcall(0x10, &ireg, &oreg);
284 
285 		if (oreg.al == 0x1a) {
286 			adapter = ADAPTER_VGA;
287 #ifndef _WAKEUP
288 			boot_params.screen_info.orig_video_isVGA = 1;
289 #endif
290 		} else {
291 			adapter = ADAPTER_EGA;
292 		}
293 	} else {
294 		adapter = ADAPTER_CGA;
295 	}
296 
297 	video_vga.modes = mode_lists[adapter];
298 	video_vga.card_name = card_name[adapter];
299 	return mode_count[adapter];
300 }
301 
302 static __videocard video_vga = {
303 	.card_name	= "VGA",
304 	.probe		= vga_probe,
305 	.set_mode	= vga_set_mode,
306 };
307