1 // Geode GX2/LX VGA functions
3 // Copyright (C) 2009 Chris Kindt
5 // Written for Google Summer of Code 2009 for the coreboot project
7 // This file may be distributed under the terms of the GNU LGPLv3 license.
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
19 /****************************************************************
20 * MSR and High Mem access through VSA Virtual Register
21 ****************************************************************/
23 static union u64_u32_u geode_msrRead(u32 msrAddr)
27 "movw $0x0AC1C, %%dx \n"
28 "movl $0xFC530007, %%eax \n"
32 : "=a" (val.lo), "=d"(val.hi)
39 static void geode_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo)
43 "movw $0x0AC1C, %%dx \n"
44 "movl $0xFC530007, %%eax \n"
50 : "c"(msrAddr), "S" (andhi), "D" (andlo), "b" (orhi), "a" (orlo)
55 static u32 geode_memRead(u32 addr)
59 "movw $0x0AC1C, %%dx \n"
60 "movl $0xFC530001, %%eax \n"
72 static void geode_memWrite(u32 addr, u32 and, u32 or )
75 "movw $0x0AC1C, %%dx \n"
76 "movl $0xFC530001, %%eax \n"
81 : "b"(addr), "S" (and), "D" (or)
86 static int legacyio_check(void)
91 if (CONFIG_VGA_GEODEGX2)
92 val=geode_msrRead(GLIU0_P2D_BM_4);
94 val=geode_msrRead(MSR_GLIU0_BASE4);
95 if (val.lo != 0x0A0fffe0)
98 val=geode_msrRead(GLIU0_IOD_BM_0);
99 if (val.lo != 0x3c0ffff0)
102 val=geode_msrRead(GLIU0_IOD_BM_1);
103 if (val.lo != 0x3d0ffff0)
109 /****************************************************************
110 * Extened CRTC Register functions
111 ****************************************************************/
112 static void crtce_lock(void)
114 stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK
118 static void crtce_unlock(void)
120 stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK
124 static u8 crtce_read(u8 reg)
127 u8 val = stdvga_crtc_read(VGAREG_VGA_CRTC_ADDRESS, reg);
132 static void crtce_write(u8 reg, u8 val)
135 stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, reg, val);
139 /****************************************************************
140 * Display Controller Functions
141 ****************************************************************/
142 static u32 dc_read(u16 seg, u32 reg)
144 u32 val, *dest_far = (void*)reg;
145 val = GET_FARVAR(seg,*dest_far);
149 static void dc_write(u16 seg, u32 reg, u32 val)
151 u32 *dest_far = (void*)reg;
152 SET_FARVAR(seg,*dest_far,val);
155 static void dc_set(u16 seg, u32 reg, u32 and, u32 or)
157 u32 val = dc_read(seg,reg);
160 dc_write(seg,reg,val);
163 static void dc_unlock(u16 seg)
165 dc_write(seg,DC_UNLOCK,DC_LOCK_UNLOCK);
168 static void dc_lock(u16 seg)
170 dc_write(seg,DC_UNLOCK,DC_LOCK_LOCK);
173 static u16 dc_map(u16 seg)
177 reg = crtce_read(EXTENDED_MODE_CONTROL);
194 crtce_write(EXTENDED_MODE_CONTROL,reg);
198 static void dc_unmap(void)
204 /****************************************************************
206 ****************************************************************/
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
213 static int dc_setup(void)
218 dprintf(2, "DC_SETUP\n");
220 seg = dc_map(SEG_GRAPH);
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);
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);
232 dc_write(seg,DC_GLIU0_MEM_OFFSET,fb);
235 dc_set(seg,DC_DISPLAY_CFG,DC_CFG_MSK,DC_GDEN+DC_TRUP);
236 dc_set(seg,DC_GENERAL_CFG,0,DC_VGAE);
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.
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);
259 geode_msrWrite(VP_MSR_CONFIG_LX, ~0, ~0xf8, 0, 0);
261 /* get vp register base from pci */
262 vp = pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3);
264 /* Set mmio registers
265 * there may be some timing issues here, the reads seem
266 * to slow things down enough work reliably
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);
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);
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
340 int geodevga_init(void)
342 int ret = stdvga_init();
346 dprintf(1,"GEODEVGA_INIT\n");
348 if ((ret=legacyio_check())) {
349 dprintf(1,"GEODEVGA_INIT legacyio_check=0x%x\n",ret);
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,
357 geode_crtc_0d, geode_crtc_0e, geode_crtc_0f, geode_crtc_0f,
358 geode_crtc_11, geode_crtc_11, geode_crtc_13 };
360 for (i=0; i<ARRAY_SIZE(new_crtc); i++) {
361 u8 *crtc = GET_GLOBAL(new_crtc[i]);
363 stdvga_override_crtc(i, crtc);
366 if (GET_GLOBAL(VgaBDF) < 0)
367 // Device should be at 00:01.1
368 SET_VGA(VgaBDF, pci_to_bdf(0, 1, 1));