1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 by Ralf Baechle (ralf@linux-mips.org)
7 *
8 * This will eventually go into the qemu firmware.
9 */
10#include <linux/init.h>
11#include <linux/screen_info.h>
12#include <linux/tty.h>
13#include <asm/io.h>
14#include <video/vga.h>
15
16/*
17 * This will eventually be done by the firmware; right now Linux assumes to
18 * run on the uninitialized hardware.
19 */
20#undef LOAD_VGA_FONT
21
22static unsigned char sr[8] __initdata = {	/* Sequencer */
23	0x03, 0x00, 0x03, 0x04, 0x02, 0x00, 0x00, 0x00
24};
25
26static unsigned char gr[16] __initdata= {	/* Graphics Controller */
27	0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00,
28	0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29};
30
31static unsigned char ar[21] __initdata= {	/* Attribute Controller */
32	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
33	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
34	0x0c, 0x01, 0x07, 0x13, 0x00
35};
36
37static unsigned char cr[32] __initdata= {	/* CRT Controller */
38	0x91, 0x4f, 0x4f, 0x95, 0x57, 0x4f, 0xc0, 0x1f,
39	0x00, 0x4f, 0x0d, 0x0e, 0x02, 0x30, 0x09, 0xb0,
40	0x90, 0x83, 0x8f, 0x28, 0x1f, 0x8f, 0xc1, 0xa3,
41	0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
42};
43
44static struct rgb {
45	unsigned char r;
46	unsigned char g;
47	unsigned char b;
48} palette[16] __initdata= {
49	[ 0] = {0x00, 0x00, 0x00},
50	[ 1] = {0x00, 0x00, 0x2a},
51	[ 2] = {0x00, 0x2a, 0x00},
52	[ 3] = {0x00, 0x2a, 0x2a},
53	[ 4] = {0x2a, 0x00, 0x00},
54	[ 5] = {0x2a, 0x00, 0x2a},
55	[ 6] = {0x2a, 0x15, 0x00},
56	[ 7] = {0x2a, 0x2a, 0x2a},
57	[ 8] = {0x15, 0x15, 0x15},
58	[ 9] = {0x15, 0x15, 0x3f},
59	[10] = {0x15, 0x3f, 0x15},
60	[11] = {0x15, 0x3f, 0x3f},
61	[12] = {0x3f, 0x15, 0x15},
62	[13] = {0x3f, 0x15, 0x3f},
63	[14] = {0x3f, 0x3f, 0x15},
64	[15] = {0x3f, 0x3f, 0x3f}
65
66};
67
68void __init qvga_init_ibm(void)
69{
70	int i;
71
72	for (i = 0; i < 8; i++) {	/* Sequencer registers */
73		outb(i, 0x3c4);
74		outb(sr[i], 0x3c5);
75	}
76
77	for (i = 0; i < 16; i++) {	/* Graphics Controller registers */
78		outb(i, 0x3ce);
79		outb(gr[i], 0x3cf);
80	}
81
82	for (i = 0; i < 21; i++) {	/* Attribute Controller registers */
83		outb(i, 0x3c0);
84		outb(ar[i], 0x3c1);
85	}
86	outb(0x20, 0x3c0);		/* enable bit in *index* register */
87
88	for (i = 0; i < 32; i++) {	/* CRT Controller registers */
89		outb(i, 0x3d4);
90		outb(cr[i], 0x3d5);
91	}
92
93	for (i = 0; i < 16; i++) {	/* palette */
94		outb(i, 0x3c8);
95		outb(palette[i].r, 0x3c9);
96		outb(palette[i].g, 0x3c9);
97		outb(palette[i].b, 0x3c9);
98	}
99
100	 for (i = 0; i < 0x20000; i += 2)
101		*(volatile unsigned short *) (0xb00a0000 + i) = 0xaaaa;
102}
103
104#ifdef LOAD_VGA_FONT
105#include "/home/ralf/src/qemu/qemu-mips/vgafont.h"
106
107static void __init
108qvga_load_font(unsigned char *def, unsigned int c)
109{
110	volatile void *w = (volatile void *) 0xb00a0000;
111
112	vga_wseq(NULL, 0, 1);
113	vga_wseq(NULL, 2, 4);
114	vga_wseq(NULL, 4, 7);
115	vga_wseq(NULL, 0, 3);
116	vga_wgfx(NULL, 4, 2);
117	vga_wgfx(NULL, 5, 0);
118	vga_wgfx(NULL, 6, 0);
119
120	memcpy(w, def, c);
121
122	vga_wseq(NULL, 0, 1);
123	vga_wseq(NULL, 2, 3);
124	vga_wseq(NULL, 4, 3);
125	vga_wseq(NULL, 0, 3);
126	vga_wgfx(NULL, 4, 0);
127	vga_wgfx(NULL, 5, 0x10);
128	vga_wgfx(NULL, 6, 0xe);
129}
130#endif
131
132void __init qvga_init(void)
133{
134	struct screen_info *si = &screen_info;
135	unsigned int h;
136	int i;
137
138#ifdef LOAD_VGA_FONT
139	qvga_load_font(vgafont16, 4096);
140#endif
141
142	vga_wgfx(NULL, 5, 0x10);	/* Set odd/even mode */
143	vga_wgfx(NULL, 6, 0x0c);	/* map to offset 0xb8000, text mode */
144	vga_wseq(NULL, 2, 3);		/* Planes 0 & 1 */
145	vga_wseq(NULL, 3, 4);		/* Font offset */
146	outb(1, VGA_MIS_W);		/* set msr to MSR_COLOR_EMULATION */
147	vga_wcrt(NULL, 1, 79);		/* 80 columns */
148	vga_wcrt(NULL, 9, 15);		/* 16 pixels per character */
149	vga_wcrt(NULL, 0x0c, 0);	/* start address high 8 bit */
150	vga_wcrt(NULL, 0x0d, 0);	/* start address low 8 bit */
151	vga_wcrt(NULL, 0x13, 0x28);	/* line offset */
152	vga_wcrt(NULL, 0x07, 0x1f);	/* line compare bit 8 */
153	vga_wcrt(NULL, 0x09, 0x4f);	/* line compare bit 9 */
154	vga_wcrt(NULL, 0x18, 0xff);	/* line compare low 8 bit */
155
156	h = (25 * 16);
157	vga_wcrt(NULL, 0x12, h);
158
159	outb(7, 0x3d4);
160	outb((inb(0x3d5) & ~0x42) | ((h >> 7) & 2) | ((h >> 3) & 0x40), 0x3d5);
161
162	for (i = 0; i < 21; i++)	/* Attribute Controller */
163		vga_wattr(NULL, i, ar[i]);
164	outb(0x20, 0x3c0);		/* Set bit 5 in Attribute Controller */
165					/* index ...  VGA is so stupid I want */
166					/* to cry all day ... */
167	outb(0, VGA_PEL_IW);
168	for (i = 0; i < 16; i++) {	/* palette */
169		outb(palette[i].r, VGA_PEL_D);
170		outb(palette[i].g, VGA_PEL_D);
171		outb(palette[i].b, VGA_PEL_D);
172	}
173
174	si->orig_x		= 0; 			/* Cursor x position */
175	si->orig_y		= 0;			/* Cursor y position */
176	si->orig_video_cols	= 80;			/* Columns */
177	si->orig_video_lines	= 25;			/* Lines */
178	si->orig_video_isVGA	= VIDEO_TYPE_VGAC;	/* Card type */
179	si->orig_video_points	= 16;
180
181}
182