vgabios: Rename vgaio.c to stdvga.c.
[seabios.git] / vgasrc / geodelx.c
1 // Geode LX VGA functions
2 //
3 // Copyright (C) 2009 Chris Kindt
4 //
5 // Written for Google Summer of Code 2009 for the coreboot project
6 //
7 // This file may be distributed under the terms of the GNU LGPLv3 license.
8
9 #include "geodelx.h"
10 #include "ioport.h" // outb
11 #include "farptr.h" // SET_FARVAR
12 #include "biosvar.h" // GET_BDA
13 #include "vgabios.h" // VGAREG_*
14 #include "util.h" // memset
15 #include "config.h"
16 #include "types.h"
17 #include "bregs.h"
18 #include "stdvga.h" // VGAREG_VGA_CRTC_ADDRESS
19
20
21 /****************************************************************
22 * MSR and High Mem access through VSA Virtual Register
23 ****************************************************************/
24
25 static union u64_u32_u lx_msrRead(u32 msrAddr)
26 {
27     union u64_u32_u val;
28     asm __volatile__ (
29         "movw   $0x0AC1C, %%dx          \n"
30         "movl   $0xFC530007, %%eax      \n"
31         "outl   %%eax, %%dx             \n"
32         "addb   $2, %%dl                \n"
33         "inw    %%dx, %%ax              \n"
34         : "=a" (val.lo), "=d"(val.hi)
35         : "c"(msrAddr)
36         : "cc"
37     );
38     return val;
39 }
40
41 static void lx_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo)
42 {
43     asm __volatile__ (
44         "push   %%eax                   \n"
45         "movw   $0x0AC1C, %%dx          \n"
46         "movl   $0xFC530007, %%eax      \n"
47         "outl   %%eax, %%dx             \n"
48         "addb   $2, %%dl                \n"
49         "pop    %%eax                   \n"
50         "outw   %%ax, %%dx              \n"
51         :
52         : "c"(msrAddr), "S" (andhi), "D" (andlo), "b" (orhi), "a" (orlo)
53         : "%edx","cc"
54     );
55 }
56
57 static u32 lx_memRead(u32 addr)
58 {
59     u32 val;
60     asm __volatile__ (
61         "movw   $0x0AC1C, %%dx          \n"
62         "movl   $0xFC530001, %%eax      \n"
63         "outl   %%eax, %%dx             \n"
64         "addb   $2, %%dl                \n"
65         "inw    %%dx, %%ax              \n"
66         : "=a" (val)
67         : "b"(addr)
68         : "cc"
69     );
70
71     return val;
72 }
73
74 static void lx_memWrite(u32 addr, u32 and, u32 or )
75 {
76     asm __volatile__ (
77         "movw   $0x0AC1C, %%dx          \n"
78         "movl   $0xFC530001, %%eax      \n"
79         "outl   %%eax, %%dx             \n"
80         "addb   $2, %%dl                \n"
81         "outw   %%ax, %%dx              \n"
82         :
83         : "b"(addr), "S" (and), "D" (or)
84         : "%eax","cc"
85     );
86 }
87
88 static int legacyio_check(void)
89 {
90     int ret=0;
91     union u64_u32_u val;
92
93     val=lx_msrRead(MSR_GLIU0_BASE4);
94     if (val.lo != 0x0A0fffe0)
95         ret|=1;
96
97     val=lx_msrRead(GLIU0_IOD_BM_0);
98     if (val.lo != 0x3c0ffff0)
99         ret|=2;
100
101     val=lx_msrRead(GLIU0_IOD_BM_1);
102     if (val.lo != 0x3d0ffff0)
103         ret|=4;
104
105     return ret;
106 }
107
108 /****************************************************************
109 * Extened CRTC Register functions
110 ****************************************************************/
111 static void crtce_lock(void)
112 {
113     outb(EXTENDED_REGISTER_LOCK , VGAREG_VGA_CRTC_ADDRESS);
114     outb(CRTCE_LOCK, VGAREG_VGA_CRTC_DATA);
115 }
116
117 static void crtce_unlock(void)
118 {
119     outb(EXTENDED_REGISTER_LOCK , VGAREG_VGA_CRTC_ADDRESS);
120     outb(CRTCE_UNLOCK, VGAREG_VGA_CRTC_DATA);
121 }
122
123 static u8 crtce_read(u8 reg)
124 {
125     u8 val;
126
127     crtce_unlock();
128     outb(reg , VGAREG_VGA_CRTC_ADDRESS);
129     val = inb(VGAREG_VGA_CRTC_DATA);
130     crtce_lock();
131
132     return val;
133 }
134
135 static void crtce_write(u8 reg, u8 val)
136 {
137     crtce_unlock();
138     outb(reg , VGAREG_VGA_CRTC_ADDRESS);
139     outb(val, VGAREG_VGA_CRTC_DATA);
140     crtce_lock();
141 }
142
143 /****************************************************************
144 * Display Controller Functions
145 ****************************************************************/
146 static u32 dc_read(u16 seg, u32 reg)
147 {
148     u32 val, *dest_far = (void*)reg;
149     val = GET_FARVAR(seg,*dest_far);
150     return val;
151 }
152
153 static void dc_write(u16 seg, u32 reg, u32 val)
154 {
155     u32 *dest_far = (void*)reg;
156     SET_FARVAR(seg,*dest_far,val);
157 }
158
159 static void dc_set(u16 seg, u32 reg, u32 and, u32 or)
160 {
161     u32 val = dc_read(seg,reg);
162     val &=and;
163     val |=or;
164     dc_write(seg,reg,val);
165 }
166
167 static void dc_unlock(u16 seg)
168 {
169     dc_write(seg,DC_UNLOCK,DC_LOCK_UNLOCK);
170 }
171
172 static void dc_lock(u16 seg)
173 {
174     dc_write(seg,DC_UNLOCK,DC_LOCK_LOCK);
175 }
176
177 static u16 dc_map(u16 seg)
178 {
179     u8 reg;
180
181     reg = crtce_read(EXTENDED_MODE_CONTROL);
182     reg &= 0xf9;
183     switch (seg) {
184     case SEG_GRAPH:
185         reg |= 0x02;
186         break;
187     case SEG_MTEXT:
188         reg |= 0x04;
189         break;
190     case SEG_CTEXT:
191         reg |= 0x06;
192         break;
193     default:
194         seg=0;
195         break;
196     }
197
198     crtce_write(EXTENDED_MODE_CONTROL,reg);
199     return seg;
200 }
201
202 static void dc_unmap(void)
203 {
204     dc_map(0);
205 }
206
207
208 /****************************************************************
209 * Init Functions
210 ****************************************************************/
211
212 /* Set up the dc (display controller) portion of the geodelx
213 *  The dc provides hardware support for VGA graphics
214 *  for features not accessible from the VGA registers,
215 *  the dc's pci bar can be mapped to a vga memory segment
216 */
217 static int dc_setup(void)
218 {
219     u32 fb, dc_fb;
220     u16 seg;
221
222     dprintf(2, "DC_SETUP\n");
223
224     seg = dc_map(SEG_GRAPH);
225     dc_unlock(seg);
226
227     /* zero memory config */
228     dc_write(seg,DC_FB_ST_OFFSET,0x0);
229     dc_write(seg,DC_CB_ST_OFFSET,0x0);
230     dc_write(seg,DC_CURS_ST_OFFSET,0x0);
231
232     /* read fb-bar from pci, then point dc to the fb base */
233     dc_fb = dc_read(seg,DC_GLIU0_MEM_OFFSET);
234     outl(LX_PCI_FB,PORT_PCI_CMD);
235     fb = inl(PORT_PCI_DATA);
236     if (fb!=dc_fb) {
237         dc_write(seg,DC_GLIU0_MEM_OFFSET,fb);
238     }
239
240     dc_set(seg,DC_DISPLAY_CFG,DC_CFG_MSK,DC_GDEN+DC_TRUP);
241     dc_set(seg,DC_GENERAL_CFG,0,DC_VGAE);
242
243     dc_lock(seg);
244     dc_unmap();
245
246     return 0;
247 }
248
249 /* Setup the vp (video processor) portion of the geodelx
250 *  Under VGA modes the vp was handled by softvg from inside VSA2.
251 *  Without a softvg module, access is only available through a pci bar.
252 *  The High Mem Access virtual register is used to  configure the
253 *   pci mmio bar from 16bit friendly io space.
254 */
255 int vp_setup(void)
256 {
257     u32 reg,vp;
258
259     dprintf(2,"VP_SETUP\n");
260     /* set output to crt and RGB/YUV */
261     lx_msrWrite(VP_MSR_CONFIG,~0 ,~0xf8,0,0);
262
263     /* get vp register base from pci */
264     outl(LX_PCI_VP,PORT_PCI_CMD);
265     vp = inl(PORT_PCI_DATA);
266
267     /* Set mmio registers
268     * there may be some timing issues here, the reads seem
269     * to slow things down enough work reliably
270     */
271
272     reg = lx_memRead(vp+VP_MISC);
273     dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
274     lx_memWrite(vp+VP_MISC,0,VP_BYP_BOTH);
275     reg = lx_memRead(vp+VP_MISC);
276     dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
277
278     reg = lx_memRead(vp+VP_DCFG);
279     dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
280     lx_memWrite(vp+VP_DCFG, ~0,VP_CRT_EN+VP_HSYNC_EN+VP_VSYNC_EN+VP_DAC_BL_EN+VP_CRT_SKEW);
281     reg = lx_memRead(vp+VP_DCFG);
282     dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
283
284     return 0;
285 }
286
287 static u8 lx_crtc_01[] VAR16 = {
288     0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
289     0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
290     0x9b, 0x8d, 0x8f, 0x14, 0x1f, 0x97, 0xb9, 0xa3,
291     0xff };
292 static u8 lx_crtc_03[] VAR16 = {
293     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
294     0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
295     0x9b, 0x8d, 0x8f, 0x28, 0x1f, 0x97, 0xb9, 0xa3,
296     0xff };
297 static u8 lx_crtc_04[] VAR16 = {
298     0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
299     0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300     0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
301     0xff };
302 static u8 lx_crtc_05[] VAR16 = {
303     0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
304     0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305     0x9b, 0x8e, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
306     0xff };
307 static u8 lx_crtc_06[] VAR16 = {
308     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
309     0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310     0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xc2,
311     0xff };
312 static u8 lx_crtc_07[] VAR16 = {
313     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
314     0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
315     0x9b, 0x8d, 0x8f, 0x28, 0x0f, 0x97, 0xb9, 0xa3,
316     0xff };
317 static u8 lx_crtc_0d[] VAR16 = {
318     0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
319     0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320     0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xe3,
321     0xff };
322 static u8 lx_crtc_0e[] VAR16 = {
323     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
324     0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325     0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xe3,
326     0xff };
327 static u8 lx_crtc_0f[] VAR16 = {
328     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
329     0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330     0x83, 0x85, 0x5d, 0x28, 0x0f, 0x65, 0xb9, 0xe3,
331     0xff };
332 static u8 lx_crtc_11[] VAR16 = {
333     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0x0b, 0x3e,
334     0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335     0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
336     0xff };
337 static u8 lx_crtc_13[] VAR16 = {
338     0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
339     0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340     0x9b, 0x8d, 0x8f, 0x28, 0x40, 0x98, 0xb9, 0xa3,
341     0xff };
342
343 int geodelx_init(void)
344 {
345     int ret;
346
347     dprintf(1,"GEODELX_INIT\n");
348
349     if ((ret=legacyio_check())) {
350         dprintf(1,"GEODELX_INIT legacyio_check=0x%x\n",ret);
351     }
352
353     // Updated timings from geode datasheets, table 6-53 in particular
354     static u8 *new_crtc[] VAR16 = {
355         lx_crtc_01, lx_crtc_01, lx_crtc_03, lx_crtc_03,
356         lx_crtc_04, lx_crtc_05, lx_crtc_06, lx_crtc_07,
357         0, 0, 0, 0, 0,
358         lx_crtc_0d, lx_crtc_0e, lx_crtc_0f, lx_crtc_0f,
359         lx_crtc_11, lx_crtc_11, lx_crtc_13 };
360     int i;
361     for (i=0; i<ARRAY_SIZE(new_crtc); i++) {
362         u8 *crtc = GET_GLOBAL(new_crtc[i]);
363         if (!crtc)
364             continue;
365         struct vgamode_s *vmode_g = find_vga_entry(i);
366         if (!vmode_g)
367             continue;
368         SET_VGA(vmode_g->crtc_regs, crtc);
369     }
370
371     ret |= vp_setup();
372     ret |= dc_setup();
373
374     return ret;
375 }