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 "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 "stdvga.h" // stdvga_crtc_write
18 /****************************************************************
19 * MSR and High Mem access through VSA Virtual Register
20 ****************************************************************/
22 static union u64_u32_u geode_msrRead(u32 msrAddr)
26 "movw $0x0AC1C, %%dx \n"
27 "movl $0xFC530007, %%eax \n"
31 : "=a" (val.lo), "=d"(val.hi)
38 static void geode_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo)
42 "movw $0x0AC1C, %%dx \n"
43 "movl $0xFC530007, %%eax \n"
49 : "c"(msrAddr), "S" (andhi), "D" (andlo), "b" (orhi), "a" (orlo)
54 static u32 geode_memRead(u32 addr)
58 "movw $0x0AC1C, %%dx \n"
59 "movl $0xFC530001, %%eax \n"
71 static void geode_memWrite(u32 addr, u32 and, u32 or )
74 "movw $0x0AC1C, %%dx \n"
75 "movl $0xFC530001, %%eax \n"
80 : "b"(addr), "S" (and), "D" (or)
85 static int legacyio_check(void)
90 if (CONFIG_VGA_GEODEGX2)
91 val=geode_msrRead(GLIU0_P2D_BM_4);
93 val=geode_msrRead(MSR_GLIU0_BASE4);
94 if (val.lo != 0x0A0fffe0)
97 val=geode_msrRead(GLIU0_IOD_BM_0);
98 if (val.lo != 0x3c0ffff0)
101 val=geode_msrRead(GLIU0_IOD_BM_1);
102 if (val.lo != 0x3d0ffff0)
108 /****************************************************************
109 * Extened CRTC Register functions
110 ****************************************************************/
111 static void crtce_lock(void)
113 stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK
117 static void crtce_unlock(void)
119 stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK
123 static u8 crtce_read(u8 reg)
126 u8 val = stdvga_crtc_read(VGAREG_VGA_CRTC_ADDRESS, reg);
131 static void crtce_write(u8 reg, u8 val)
134 stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, reg, val);
138 /****************************************************************
139 * Display Controller Functions
140 ****************************************************************/
141 static u32 dc_read(u16 seg, u32 reg)
143 u32 val, *dest_far = (void*)reg;
144 val = GET_FARVAR(seg,*dest_far);
148 static void dc_write(u16 seg, u32 reg, u32 val)
150 u32 *dest_far = (void*)reg;
151 SET_FARVAR(seg,*dest_far,val);
154 static void dc_set(u16 seg, u32 reg, u32 and, u32 or)
156 u32 val = dc_read(seg,reg);
159 dc_write(seg,reg,val);
162 static void dc_unlock(u16 seg)
164 dc_write(seg,DC_UNLOCK,DC_LOCK_UNLOCK);
167 static void dc_lock(u16 seg)
169 dc_write(seg,DC_UNLOCK,DC_LOCK_LOCK);
172 static u16 dc_map(u16 seg)
176 reg = crtce_read(EXTENDED_MODE_CONTROL);
193 crtce_write(EXTENDED_MODE_CONTROL,reg);
197 static void dc_unmap(void)
203 /****************************************************************
205 ****************************************************************/
207 /* Set up the dc (display controller) portion of the geodelx
208 * The dc provides hardware support for VGA graphics
209 * for features not accessible from the VGA registers,
210 * the dc's pci bar can be mapped to a vga memory segment
212 static int dc_setup(void)
217 dprintf(2, "DC_SETUP\n");
219 seg = dc_map(SEG_GRAPH);
222 /* zero memory config */
223 dc_write(seg,DC_FB_ST_OFFSET,0x0);
224 dc_write(seg,DC_CB_ST_OFFSET,0x0);
225 dc_write(seg,DC_CURS_ST_OFFSET,0x0);
227 /* read fb-bar from pci, then point dc to the fb base */
228 dc_fb = dc_read(seg,DC_GLIU0_MEM_OFFSET);
229 outl(GEODE_PCI_FB,PORT_PCI_CMD);
230 fb = inl(PORT_PCI_DATA);
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 outl(GEODE_PCI_VP,PORT_PCI_CMD);
263 vp = inl(PORT_PCI_DATA);
265 /* Set mmio registers
266 * there may be some timing issues here, the reads seem
267 * to slow things down enough work reliably
270 reg = geode_memRead(vp+VP_MISC);
271 dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
272 geode_memWrite(vp+VP_MISC,0,VP_BYP_BOTH);
273 reg = geode_memRead(vp+VP_MISC);
274 dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
276 reg = geode_memRead(vp+VP_DCFG);
277 dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
278 geode_memWrite(vp+VP_DCFG, ~0,VP_CRT_EN+VP_HSYNC_EN+VP_VSYNC_EN+VP_DAC_BL_EN+VP_CRT_SKEW);
279 reg = geode_memRead(vp+VP_DCFG);
280 dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
285 static u8 geode_crtc_01[] VAR16 = {
286 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
287 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
288 0x9b, 0x8d, 0x8f, 0x14, 0x1f, 0x97, 0xb9, 0xa3,
290 static u8 geode_crtc_03[] VAR16 = {
291 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
292 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
293 0x9b, 0x8d, 0x8f, 0x28, 0x1f, 0x97, 0xb9, 0xa3,
295 static u8 geode_crtc_04[] VAR16 = {
296 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
297 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
300 static u8 geode_crtc_05[] VAR16 = {
301 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
302 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x9b, 0x8e, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
305 static u8 geode_crtc_06[] VAR16 = {
306 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
307 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xc2,
310 static u8 geode_crtc_07[] VAR16 = {
311 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
312 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
313 0x9b, 0x8d, 0x8f, 0x28, 0x0f, 0x97, 0xb9, 0xa3,
315 static u8 geode_crtc_0d[] VAR16 = {
316 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
317 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xe3,
320 static u8 geode_crtc_0e[] VAR16 = {
321 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
322 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xe3,
325 static u8 geode_crtc_0f[] VAR16 = {
326 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
327 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x65, 0xb9, 0xe3,
330 static u8 geode_crtc_11[] VAR16 = {
331 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0x0b, 0x3e,
332 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
335 static u8 geode_crtc_13[] VAR16 = {
336 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
337 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x9b, 0x8d, 0x8f, 0x28, 0x40, 0x98, 0xb9, 0xa3,
341 int geodevga_init(void)
343 int ret = stdvga_init();
347 dprintf(1,"GEODEVGA_INIT\n");
349 if ((ret=legacyio_check())) {
350 dprintf(1,"GEODEVGA_INIT legacyio_check=0x%x\n",ret);
353 // Updated timings from geode datasheets, table 6-53 in particular
354 static u8 *new_crtc[] VAR16 = {
355 geode_crtc_01, geode_crtc_01, geode_crtc_03, geode_crtc_03,
356 geode_crtc_04, geode_crtc_05, geode_crtc_06, geode_crtc_07,
358 geode_crtc_0d, geode_crtc_0e, geode_crtc_0f, geode_crtc_0f,
359 geode_crtc_11, geode_crtc_11, geode_crtc_13 };
361 for (i=0; i<ARRAY_SIZE(new_crtc); i++) {
362 u8 *crtc = GET_GLOBAL(new_crtc[i]);
364 stdvga_override_crtc(i, crtc);