1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#include <libpayload.h>
31#include <pci.h>
32#include <video_console.h>
33#include <arch/msr.h>
34#include "font8x16.h"
35
36
37
38static const struct mode {
39 unsigned int pll;
40 unsigned int hactive, hblankstart, hsyncstart;
41 unsigned int hsyncend, hblankend, htotal;
42 unsigned int vactive, vblankstart, vsyncstart;
43 unsigned int vsyncend, vblankend, vtotal;
44 unsigned int synccfg;
45} vga_mode = {
46 .pll = 0x215D,
47 .hactive = 640,
48 .vactive = 400,
49 .hblankstart = 640,
50 .hsyncstart = 640 + 40,
51 .hsyncend = 640 + 40 + 96,
52 .hblankend = 640 + 40 + 96 + 24,
53 .htotal = 640 + 40 + 96 + 24,
54 .vblankstart = 400,
55 .vsyncstart = 400 + 39,
56 .vsyncend = 400 + 39 + 2,
57 .vblankend = 400 + 39 + 2 + 9,
58 .vtotal = 400 + 39 + 2 + 9,
59 .synccfg = 0x300,
60};
61
62
63
64static const unsigned int vga_colors[] = {
65 (0x00 << 16) | (0x00 << 8) | 0x00,
66 (0xAA << 16) | (0x00 << 8) | 0x00,
67 (0x00 << 16) | (0xAA << 8) | 0x00,
68 (0xAA << 16) | (0x55 << 8) | 0x00,
69 (0x00 << 16) | (0x00 << 8) | 0xAA,
70 (0xAA << 16) | (0x00 << 8) | 0xAA,
71 (0x00 << 16) | (0xAA << 8) | 0xAA,
72 (0xAA << 16) | (0xAA << 8) | 0xAA,
73 (0x55 << 16) | (0x55 << 8) | 0x55,
74 (0xFF << 16) | (0x55 << 8) | 0x55,
75 (0x55 << 16) | (0xFF << 8) | 0x55,
76 (0xFF << 16) | (0xFF << 8) | 0x55,
77 (0x55 << 16) | (0x55 << 8) | 0xFF,
78 (0xFF << 16) | (0x55 << 8) | 0xFF,
79 (0x55 << 16) | (0xFF << 8) | 0xFF,
80 (0xFF << 16) | (0xFF << 8) | 0xFF,
81};
82
83
84
85static unsigned long dcaddr;
86static unsigned long vgaddr;
87static unsigned long gpaddr;
88static unsigned long fbaddr;
89
90#define DC (phys_to_virt(dcaddr))
91#define VG (phys_to_virt(vgaddr))
92#define GP (phys_to_virt(gpaddr))
93#define FB ((unsigned char *) phys_to_virt(fbaddr))
94
95static void init_video_mode(void)
96{
97 unsigned int lo, hi, val;
98 int i;
99
100
101
102 rdmsr(0x4c000015, lo, hi);
103
104 hi = vga_mode.pll;
105
106 lo &= ~0x1008000;
107 lo |= 0x01;
108
109 wrmsr(0x4c000015, lo, hi);
110 udelay(100);
111
112 for(i = 0; i < 1000; i++) {
113 rdmsr(0x4c000015, lo, hi);
114 if (lo & 0x2000000)
115 break;
116 }
117
118 lo &= ~0x01;
119 wrmsr(0x4c000015, lo, hi);
120
121 rdmsr(0x48002001, lo, hi);
122 lo &= ~0x38;
123 wrmsr(0x48002001, lo, hi);
124
125 writel(0x4758, DC + 0x00);
126
127 val = readl(DC + 0x00);
128
129 writel(0, DC + 0x10);
130 writel(0, DC + 0x14);
131 writel(0, DC + 0x18);
132
133
134
135 val = readl(DC + 0xD4);
136
137 writel((0x4000 << 16) | 0x4000, DC + 0x90);
138 writel(0, DC + 0x94);
139 writel(val & ~0xf3040000, DC + 0xD4);
140
141
142 writel(vga_mode.hactive * vga_mode.vactive | 0x01, DC + 0x2C);
143
144 val = readl(DC + 0x88);
145 writel(val & ~0xC00, DC + 0x88);
146 writel(0, DC + 0x8C);
147
148
149 writel(vga_mode.hactive >> 3, DC + 0x34);
150 writel((vga_mode.hactive + 7) >> 3, DC + 0x30);
151
152
153
154 lo = 0xC0;
155 wrmsr(0x80000011, lo, hi);
156
157
158
159 writel((vga_mode.hactive - 1) | ((vga_mode.htotal - 1) << 16),
160 DC + 0x40);
161
162 writel((vga_mode.hblankstart - 1) | ((vga_mode.hblankend - 1) << 16),
163 DC + 0x44);
164
165 writel((vga_mode.hsyncstart - 1) | ((vga_mode.hsyncend - 1) << 16),
166 DC + 0x48);
167
168 writel((vga_mode.vactive - 1) | ((vga_mode.vtotal - 1) << 16),
169 DC + 0x50);
170
171 writel((vga_mode.vblankstart - 1) | ((vga_mode.vblankend - 1) << 16),
172 DC + 0x54);
173
174 writel((vga_mode.vsyncstart - 1) | ((vga_mode.vsyncend - 1) << 16),
175 DC + 0x58);
176
177 writel(((vga_mode.hactive - 1) << 16) | (vga_mode.vactive - 1),
178 DC + 0x5C);
179
180
181
182
183 writel(0x290000F | vga_mode.synccfg, VG + 0x08);
184
185
186
187 val = readl(VG + 0x50);
188 writel((val & ~0xC00) | 0x01, VG + 0x50);
189
190
191 writel(fbaddr, DC + 0x84);
192
193
194
195 writel(0xB000059, DC + 0x08);
196 writel(0, DC + 0x0C);
197 writel(0x2B601, DC + 0x04);
198}
199
200static void geodelx_set_palette(int entry, unsigned int color)
201{
202 writel(entry, DC + 0x70);
203 writel(color, DC + 0x74);
204}
205
206static void geodelx_scroll_up(void)
207{
208 unsigned char *dst = FB;
209 unsigned char *src = FB + FONT_HEIGHT * vga_mode.hactive;
210 int y;
211
212 for(y = 0; y < vga_mode.vactive - FONT_HEIGHT; y++) {
213 memcpy(dst, src, vga_mode.hactive);
214
215 dst += vga_mode.hactive;
216 src += vga_mode.hactive;
217 }
218
219 for(; y < vga_mode.vactive; y++) {
220 memset(dst, 0, vga_mode.hactive);
221 dst += vga_mode.hactive;
222 }
223}
224
225static void geodelx_clear(void)
226{
227 int row;
228 unsigned char *ptr = FB;
229
230 for(row = 0; row < vga_mode.vactive; row++) {
231 memset(ptr, 0, vga_mode.hactive);
232 ptr += vga_mode.hactive;
233 }
234}
235
236static void geodelx_putc(u8 row, u8 col, unsigned int ch)
237{
238 unsigned char *dst;
239 unsigned char *glyph = font8x16 + ((ch & 0xFF) * FONT_HEIGHT);
240
241 unsigned char bg = (ch >> 12) & 0xF;
242 unsigned char fg = (ch >> 8) & 0xF;
243
244 int x, y;
245
246 dst = FB + ((row * FONT_HEIGHT) * vga_mode.hactive);
247 dst += (col * FONT_WIDTH);
248
249 for(y = 0; y < FONT_HEIGHT; y++) {
250
251 for(x = FONT_WIDTH - 1; x >= 0; x--)
252 dst[FONT_WIDTH - x] = (*glyph & (1 << x)) ?
253 fg : bg;
254
255 dst += vga_mode.hactive;
256 glyph++;
257 }
258}
259
260static int geodelx_init(void)
261{
262 pcidev_t dev;
263 int i;
264
265 if (!pci_find_device(0x1022, 0x2081, &dev))
266 return -1;
267
268 fbaddr = pci_read_resource(dev, 0);
269 gpaddr = pci_read_resource(dev, 1);
270 dcaddr = pci_read_resource(dev, 2);
271 vgaddr = pci_read_resource(dev, 3);
272
273 init_video_mode();
274
275
276
277 for(i = 0; i < ARRAY_SIZE(vga_colors); i++) {
278 geodelx_set_palette(i, vga_colors[i]);
279 }
280
281 geodelx_clear();
282
283 return 0;
284}
285
286struct video_console geodelx_video_console = {
287 .init = geodelx_init,
288 .putc = geodelx_putc,
289 .clear = geodelx_clear,
290 .scroll_up = geodelx_scroll_up,
291
292
293
294
295
296 .columns = 80,
297 .rows = 25
298};
299