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