|
|
1.1 root 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: if (GET_GLOBAL(VgaBDF) < 0)
367: // Device should be at 00:01.1
368: SET_VGA(VgaBDF, pci_to_bdf(0, 1, 1));
369: ret |= vp_setup();
370: ret |= dc_setup();
371:
372: return ret;
373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.