blob: a5a58cdbe003be5848424743d2d634528a5873e9 [file] [log] [blame]
Nils31eabf92012-01-14 12:11:41 -05001// 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
Nils31eabf92012-01-14 12:11:41 -05009#include "biosvar.h" // GET_BDA
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040010#include "farptr.h" // SET_FARVAR
11#include "geodevga.h" // geodevga_setup
Kevin O'Connor5d369d82013-09-02 20:48:46 -040012#include "hw/pci.h" // pci_config_readl
13#include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040014#include "output.h" // dprintf
15#include "stdvga.h" // stdvga_crtc_write
Kevin O'Connor2f2ec112016-08-05 11:14:58 -040016#include "vgabios.h" // SET_VGA
17#include "vgautil.h" // VBE_total_memory
Nils31eabf92012-01-14 12:11:41 -050018
19
20/****************************************************************
21* MSR and High Mem access through VSA Virtual Register
22****************************************************************/
23
Kevin O'Connorf47461f2012-09-03 12:32:01 -040024static u64 geode_msr_read(u32 msrAddr)
Nils31eabf92012-01-14 12:11:41 -050025{
26 union u64_u32_u val;
27 asm __volatile__ (
28 "movw $0x0AC1C, %%dx \n"
29 "movl $0xFC530007, %%eax \n"
30 "outl %%eax, %%dx \n"
31 "addb $2, %%dl \n"
32 "inw %%dx, %%ax \n"
33 : "=a" (val.lo), "=d"(val.hi)
34 : "c"(msrAddr)
35 : "cc"
36 );
Christian Gmeiner0f5628d2013-02-14 10:34:36 +010037
38 dprintf(4, "%s(0x%08x) = 0x%08x-0x%08x\n"
39 , __func__, msrAddr, val.hi, val.lo);
Kevin O'Connorf47461f2012-09-03 12:32:01 -040040 return val.val;
Nils31eabf92012-01-14 12:11:41 -050041}
42
Kevin O'Connorf47461f2012-09-03 12:32:01 -040043static void geode_msr_mask(u32 msrAddr, u64 off, u64 on)
Nils31eabf92012-01-14 12:11:41 -050044{
Kevin O'Connorf47461f2012-09-03 12:32:01 -040045 union u64_u32_u uand, uor;
46 uand.val = ~off;
47 uor.val = on;
Christian Gmeiner0f5628d2013-02-14 10:34:36 +010048
49 dprintf(4, "%s(0x%08x, 0x%016llx, 0x%016llx)\n"
50 , __func__, msrAddr, off, on);
51
Nils31eabf92012-01-14 12:11:41 -050052 asm __volatile__ (
53 "push %%eax \n"
54 "movw $0x0AC1C, %%dx \n"
55 "movl $0xFC530007, %%eax \n"
56 "outl %%eax, %%dx \n"
57 "addb $2, %%dl \n"
58 "pop %%eax \n"
59 "outw %%ax, %%dx \n"
60 :
Kevin O'Connorf47461f2012-09-03 12:32:01 -040061 : "c"(msrAddr), "S" (uand.hi), "D" (uand.lo), "b" (uor.hi), "a" (uor.lo)
Nils31eabf92012-01-14 12:11:41 -050062 : "%edx","cc"
63 );
64}
65
Kevin O'Connorf47461f2012-09-03 12:32:01 -040066static u32 geode_mem_read(u32 addr)
Nils31eabf92012-01-14 12:11:41 -050067{
68 u32 val;
69 asm __volatile__ (
70 "movw $0x0AC1C, %%dx \n"
71 "movl $0xFC530001, %%eax \n"
72 "outl %%eax, %%dx \n"
73 "addb $2, %%dl \n"
74 "inw %%dx, %%ax \n"
75 : "=a" (val)
76 : "b"(addr)
77 : "cc"
78 );
79
80 return val;
81}
82
Kevin O'Connorf47461f2012-09-03 12:32:01 -040083static void geode_mem_mask(u32 addr, u32 off, u32 or)
Nils31eabf92012-01-14 12:11:41 -050084{
85 asm __volatile__ (
86 "movw $0x0AC1C, %%dx \n"
87 "movl $0xFC530001, %%eax \n"
88 "outl %%eax, %%dx \n"
89 "addb $2, %%dl \n"
90 "outw %%ax, %%dx \n"
91 :
Kevin O'Connorf47461f2012-09-03 12:32:01 -040092 : "b"(addr), "S" (~off), "D" (or)
Nils31eabf92012-01-14 12:11:41 -050093 : "%eax","cc"
94 );
95}
96
Christian Gmeiner119ece92012-10-01 14:02:43 +020097#define VP_FP_START 0x400
98
Kevin O'Connoref7f73f2012-09-16 13:24:30 -040099static u32 GeodeFB VAR16;
100static u32 GeodeDC VAR16;
101static u32 GeodeVP VAR16;
Christian Gmeiner7bec6db2012-09-01 17:13:02 +0200102
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400103static u32 geode_dc_read(int reg)
Christian Gmeinerd136fd72012-09-01 17:13:04 +0200104{
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400105 u32 val = geode_mem_read(GET_GLOBAL(GeodeDC) + reg);
106 dprintf(4, "%s(0x%08x) = 0x%08x\n"
107 , __func__, GET_GLOBAL(GeodeDC) + reg, val);
Christian Gmeinerd136fd72012-09-01 17:13:04 +0200108 return val;
109}
110
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400111static void geode_dc_write(int reg, u32 val)
Christian Gmeinerd136fd72012-09-01 17:13:04 +0200112{
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400113 dprintf(4, "%s(0x%08x, 0x%08x)\n"
114 , __func__, GET_GLOBAL(GeodeDC) + reg, val);
115 geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, ~0, val);
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400116}
117
118static void geode_dc_mask(int reg, u32 off, u32 on)
119{
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400120 dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n"
121 , __func__, GET_GLOBAL(GeodeDC) + reg, off, on);
122 geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, off, on);
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400123}
124
125static u32 geode_vp_read(int reg)
126{
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400127 u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + reg);
128 dprintf(4, "%s(0x%08x) = 0x%08x\n"
129 , __func__, GET_GLOBAL(GeodeVP) + reg, val);
Christian Gmeinerd136fd72012-09-01 17:13:04 +0200130 return val;
131}
132
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400133static void geode_vp_write(int reg, u32 val)
Christian Gmeinerd136fd72012-09-01 17:13:04 +0200134{
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400135 dprintf(4, "%s(0x%08x, 0x%08x)\n"
136 , __func__, GET_GLOBAL(GeodeVP) + reg, val);
137 geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, ~0, val);
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400138}
139
140static void geode_vp_mask(int reg, u32 off, u32 on)
141{
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400142 dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n"
143 , __func__, GET_GLOBAL(GeodeVP) + reg, off, on);
144 geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, off, on);
Christian Gmeinerd136fd72012-09-01 17:13:04 +0200145}
146
Christian Gmeiner119ece92012-10-01 14:02:43 +0200147static u32 geode_fp_read(int reg)
148{
149 u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + VP_FP_START + reg);
150 dprintf(4, "%s(0x%08x) = 0x%08x\n"
Christian Gmeinerbb7e54a2013-02-14 10:34:32 +0100151 , __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val);
Christian Gmeiner119ece92012-10-01 14:02:43 +0200152 return val;
153}
154
155static void geode_fp_write(int reg, u32 val)
156{
157 dprintf(4, "%s(0x%08x, 0x%08x)\n"
158 , __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val);
Christian Gmeinerbb7e54a2013-02-14 10:34:32 +0100159 geode_mem_mask(GET_GLOBAL(GeodeVP) + VP_FP_START + reg, ~0, val);
Christian Gmeiner119ece92012-10-01 14:02:43 +0200160}
161
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400162/****************************************************************
163 * Helper functions
164 ****************************************************************/
165
Nils31eabf92012-01-14 12:11:41 -0500166static int legacyio_check(void)
167{
168 int ret=0;
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400169 u64 val;
Nils31eabf92012-01-14 12:11:41 -0500170
Nils24ddd862012-01-14 12:15:14 -0500171 if (CONFIG_VGA_GEODEGX2)
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400172 val = geode_msr_read(GLIU0_P2D_BM_4);
Nils24ddd862012-01-14 12:15:14 -0500173 else
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400174 val = geode_msr_read(MSR_GLIU0_BASE4);
175 if ((val & 0xffffffff) != 0x0A0fffe0)
Nils31eabf92012-01-14 12:11:41 -0500176 ret|=1;
177
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400178 val = geode_msr_read(GLIU0_IOD_BM_0);
179 if ((val & 0xffffffff) != 0x3c0ffff0)
Nils31eabf92012-01-14 12:11:41 -0500180 ret|=2;
181
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400182 val = geode_msr_read(GLIU0_IOD_BM_1);
183 if ((val & 0xffffffff) != 0x3d0ffff0)
Nils31eabf92012-01-14 12:11:41 -0500184 ret|=4;
185
186 return ret;
187}
188
Christian Gmeiner9de339d2012-09-01 17:12:56 +0200189static u32 framebuffer_size(void)
190{
Christian Gmeiner9de339d2012-09-01 17:12:56 +0200191 /* We use the P2D_R0 msr to read out the number of pages.
192 * One page has a size of 4k
193 *
194 * Bit Name Description
195 * 39:20 PMAX Physical Memory Address Max
196 * 19:0 PMIX Physical Memory Address Min
197 *
198 */
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400199 u64 msr = geode_msr_read(GLIU0_P2D_RO);
Christian Gmeiner9de339d2012-09-01 17:12:56 +0200200
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400201 u32 pmax = (msr >> 20) & 0x000fffff;
202 u32 pmin = msr & 0x000fffff;
203
204 u32 val = pmax - pmin;
Christian Gmeiner9de339d2012-09-01 17:12:56 +0200205 val += 1;
206
207 /* The page size is 4k */
208 return (val << 12);
209}
Nils31eabf92012-01-14 12:11:41 -0500210
211/****************************************************************
Nils31eabf92012-01-14 12:11:41 -0500212* Init Functions
213****************************************************************/
214
Christian Gmeiner42f33ff2013-02-14 10:34:35 +0100215static void geodevga_set_output_mode(void)
216{
217 u64 msr_addr;
218 u64 msr;
219
220 /* set output to crt and RGB/YUV */
221 if (CONFIG_VGA_GEODEGX2)
222 msr_addr = VP_MSR_CONFIG_GX2;
223 else
224 msr_addr = VP_MSR_CONFIG_LX;
225
226 /* set output mode (RGB/YUV) */
227 msr = geode_msr_read(msr_addr);
228 msr &= ~VP_MSR_CONFIG_FMT; // mask out FMT (bits 5:3)
229
230 if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) {
231 msr |= VP_MSR_CONFIG_FMT_FP; // flat panel
232
233 if (CONFIG_VGA_OUTPUT_CRT_PANEL) {
234 msr |= VP_MSR_CONFIG_FPC; // simultaneous Flat Panel and CRT
235 dprintf(1, "output: simultaneous Flat Panel and CRT\n");
236 } else {
237 msr &= ~VP_MSR_CONFIG_FPC; // no simultaneous Flat Panel and CRT
238 dprintf(1, "ouput: flat panel\n");
239 }
240 } else {
241 msr |= VP_MSR_CONFIG_FMT_CRT; // CRT only
242 dprintf(1, "output: CRT\n");
243 }
244 geode_msr_mask(msr_addr, ~msr, msr);
245}
246
Nils31eabf92012-01-14 12:11:41 -0500247/* Set up the dc (display controller) portion of the geodelx
Christian Gmeinerc13c1812012-09-01 17:12:52 +0200248* The dc provides hardware support for VGA graphics.
Nils31eabf92012-01-14 12:11:41 -0500249*/
Christian Gmeiner11ebc7d2012-09-01 17:13:03 +0200250static void dc_setup(void)
Nils31eabf92012-01-14 12:11:41 -0500251{
Nils31eabf92012-01-14 12:11:41 -0500252 dprintf(2, "DC_SETUP\n");
253
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400254 geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK);
Nils31eabf92012-01-14 12:11:41 -0500255
256 /* zero memory config */
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400257 geode_dc_write(DC_FB_ST_OFFSET, 0x0);
258 geode_dc_write(DC_CB_ST_OFFSET, 0x0);
259 geode_dc_write(DC_CURS_ST_OFFSET, 0x0);
Nils31eabf92012-01-14 12:11:41 -0500260
Christian Gmeiner286e0132012-10-01 14:02:42 +0200261 geode_dc_mask(DC_DISPLAY_CFG, ~DC_CFG_MSK, DC_DISPLAY_CFG_GDEN|DC_DISPLAY_CFG_TRUP);
Christian Gmeiner1337eb32013-02-14 10:34:37 +0100262 geode_dc_write(DC_GENERAL_CFG, DC_GENERAL_CFG_VGAE);
Nils31eabf92012-01-14 12:11:41 -0500263
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400264 geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK);
Nils31eabf92012-01-14 12:11:41 -0500265}
266
267/* Setup the vp (video processor) portion of the geodelx
268* Under VGA modes the vp was handled by softvg from inside VSA2.
269* Without a softvg module, access is only available through a pci bar.
270* The High Mem Access virtual register is used to configure the
271* pci mmio bar from 16bit friendly io space.
272*/
Christian Gmeiner11ebc7d2012-09-01 17:13:03 +0200273static void vp_setup(void)
Nils31eabf92012-01-14 12:11:41 -0500274{
Nils31eabf92012-01-14 12:11:41 -0500275 dprintf(2,"VP_SETUP\n");
Christian Gmeinereac884d2012-10-01 14:02:46 +0200276
Christian Gmeiner42f33ff2013-02-14 10:34:35 +0100277 geodevga_set_output_mode();
Nils31eabf92012-01-14 12:11:41 -0500278
Nils31eabf92012-01-14 12:11:41 -0500279 /* Set mmio registers
280 * there may be some timing issues here, the reads seem
281 * to slow things down enough work reliably
282 */
283
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400284 u32 reg = geode_vp_read(VP_MISC);
Nils31eabf92012-01-14 12:11:41 -0500285 dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
Christian Gmeiner286e0132012-10-01 14:02:42 +0200286 geode_vp_write(VP_MISC, VP_DCFG_BYP_BOTH);
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400287 reg = geode_vp_read(VP_MISC);
Nils31eabf92012-01-14 12:11:41 -0500288 dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
289
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400290 reg = geode_vp_read(VP_DCFG);
Nils31eabf92012-01-14 12:11:41 -0500291 dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
Christian Gmeiner286e0132012-10-01 14:02:42 +0200292 geode_vp_mask(VP_DCFG, 0, VP_DCFG_CRT_EN|VP_DCFG_HSYNC_EN|VP_DCFG_VSYNC_EN|VP_DCFG_DAC_BL_EN|VP_DCFG_CRT_SKEW);
Kevin O'Connorf47461f2012-09-03 12:32:01 -0400293 reg = geode_vp_read(VP_DCFG);
Nils31eabf92012-01-14 12:11:41 -0500294 dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
Christian Gmeiner02203b52012-10-01 14:02:49 +0200295
296 /* setup flat panel */
297 if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) {
Christian Gmeiner42f33ff2013-02-14 10:34:35 +0100298 u64 msr;
299
Christian Gmeiner02203b52012-10-01 14:02:49 +0200300 dprintf(1, "Setting up flat panel\n");
301 /* write timing register */
302 geode_fp_write(FP_PT1, 0x0);
303 geode_fp_write(FP_PT2, FP_PT2_SCRC);
304
305 /* set pad select for TFT/LVDS */
306 msr = VP_MSR_PADSEL_TFT_SEL_HIGH;
307 msr = msr << 32;
308 msr |= VP_MSR_PADSEL_TFT_SEL_LOW;
309 geode_msr_mask(VP_MSR_PADSEL, ~msr, msr);
310
311 /* turn the panel on (if it isn't already) */
312 reg = geode_fp_read(FP_PM);
313 reg |= FP_PM_P;
314 geode_fp_write(FP_PM, reg);
315 }
Nils31eabf92012-01-14 12:11:41 -0500316}
317
318static u8 geode_crtc_01[] VAR16 = {
319 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
320 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
321 0x9b, 0x8d, 0x8f, 0x14, 0x1f, 0x97, 0xb9, 0xa3,
322 0xff };
323static u8 geode_crtc_03[] VAR16 = {
324 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
325 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
326 0x9b, 0x8d, 0x8f, 0x28, 0x1f, 0x97, 0xb9, 0xa3,
327 0xff };
328static u8 geode_crtc_04[] VAR16 = {
329 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
330 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
332 0xff };
333static u8 geode_crtc_05[] VAR16 = {
334 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
335 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x9b, 0x8e, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2,
337 0xff };
338static u8 geode_crtc_06[] VAR16 = {
339 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
340 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xc2,
342 0xff };
343static u8 geode_crtc_07[] VAR16 = {
344 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
345 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
346 0x9b, 0x8d, 0x8f, 0x28, 0x0f, 0x97, 0xb9, 0xa3,
347 0xff };
348static u8 geode_crtc_0d[] VAR16 = {
349 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f,
350 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xe3,
352 0xff };
353static u8 geode_crtc_0e[] VAR16 = {
354 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
355 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xe3,
357 0xff };
358static u8 geode_crtc_0f[] VAR16 = {
359 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
360 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x65, 0xb9, 0xe3,
362 0xff };
363static u8 geode_crtc_11[] VAR16 = {
364 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0x0b, 0x3e,
365 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
367 0xff };
368static u8 geode_crtc_13[] VAR16 = {
369 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f,
370 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x9b, 0x8d, 0x8f, 0x28, 0x40, 0x98, 0xb9, 0xa3,
372 0xff };
373
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500374int geodevga_setup(void)
Nils31eabf92012-01-14 12:11:41 -0500375{
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500376 int ret = stdvga_setup();
Nils31eabf92012-01-14 12:11:41 -0500377 if (ret)
378 return ret;
379
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500380 dprintf(1,"GEODEVGA_SETUP\n");
Nils31eabf92012-01-14 12:11:41 -0500381
382 if ((ret=legacyio_check())) {
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500383 dprintf(1,"GEODEVGA_SETUP legacyio_check=0x%x\n",ret);
Nils31eabf92012-01-14 12:11:41 -0500384 }
385
386 // Updated timings from geode datasheets, table 6-53 in particular
387 static u8 *new_crtc[] VAR16 = {
388 geode_crtc_01, geode_crtc_01, geode_crtc_03, geode_crtc_03,
389 geode_crtc_04, geode_crtc_05, geode_crtc_06, geode_crtc_07,
390 0, 0, 0, 0, 0,
391 geode_crtc_0d, geode_crtc_0e, geode_crtc_0f, geode_crtc_0f,
392 geode_crtc_11, geode_crtc_11, geode_crtc_13 };
393 int i;
394 for (i=0; i<ARRAY_SIZE(new_crtc); i++) {
395 u8 *crtc = GET_GLOBAL(new_crtc[i]);
Kevin O'Connor69b01cb2012-01-14 23:25:24 -0500396 if (crtc)
397 stdvga_override_crtc(i, crtc);
Nils31eabf92012-01-14 12:11:41 -0500398 }
399
Kevin O'Connor8cf8f8e2012-01-16 19:05:27 -0500400 if (GET_GLOBAL(VgaBDF) < 0)
401 // Device should be at 00:01.1
402 SET_VGA(VgaBDF, pci_to_bdf(0, 1, 1));
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400403
Christian Gmeiner7bec6db2012-09-01 17:13:02 +0200404 // setup geode struct which is used for register access
Kevin O'Connoref7f73f2012-09-16 13:24:30 -0400405 SET_VGA(GeodeFB, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_0));
406 SET_VGA(GeodeDC, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_2));
407 SET_VGA(GeodeVP, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3));
408
409 dprintf(1, "fb addr: 0x%08x\n", GET_GLOBAL(GeodeFB));
410 dprintf(1, "dc addr: 0x%08x\n", GET_GLOBAL(GeodeDC));
411 dprintf(1, "vp addr: 0x%08x\n", GET_GLOBAL(GeodeVP));
412
Christian Gmeiner32057082013-02-14 10:34:34 +0100413 /* setup framebuffer */
414 geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK);
415
416 /* read fb-bar from pci, then point dc to the fb base */
417 u32 fb = GET_GLOBAL(GeodeFB);
418 if (geode_dc_read(DC_GLIU0_MEM_OFFSET) != fb)
419 geode_dc_write(DC_GLIU0_MEM_OFFSET, fb);
420
421 geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK);
422
423 u32 fb_size = framebuffer_size(); // in byte
424 dprintf(1, "%d KB of video memory at 0x%08x\n", fb_size / 1024, fb);
425
426 /* update VBE variables */
427 SET_VGA(VBE_framebuffer, fb);
428 SET_VGA(VBE_total_memory, fb_size / 1024 / 64); // number of 64K blocks
429
Christian Gmeiner11ebc7d2012-09-01 17:13:03 +0200430 vp_setup();
431 dc_setup();
Nils31eabf92012-01-14 12:11:41 -0500432
Christian Gmeiner11ebc7d2012-09-01 17:13:03 +0200433 return 0;
Nils31eabf92012-01-14 12:11:41 -0500434}