Lenovo ThinkPad X60: cleanup Native VGA init.
[gnutoo-for-coreboot:coreboot.git] / src / mainboard / lenovo / x60 / i915.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2012 Google Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19
20 #include <types.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <device/device.h>
24 #include <device/device.h>
25 #include <device/pci_def.h>
26 #include <device/pci_ops.h>
27 #include <console/console.h>
28 #include <delay.h>
29 #include <pc80/mc146818rtc.h>
30 #include <arch/acpi.h>
31 #include <arch/io.h>
32 #include <arch/interrupt.h>
33 #include <boot/coreboot_tables.h>
34 #include <southbridge/intel/bd82x6x/pch.h>
35 #include <smbios.h>
36 #include <device/pci.h>
37 #include <ec/google/chromeec/ec.h>
38 #include <cbfs_core.h>
39
40 #include <cpu/x86/tsc.h>
41 #include <cpu/x86/cache.h>
42 #include <cpu/x86/mtrr.h>
43 #include <cpu/x86/msr.h>
44 #include <edid.h>
45 #include "i915io.h"
46
47 enum {
48         vmsg = 1, vio = 2, vspin = 4,
49 };
50
51 #define PGETLB_CTL 0x2020
52
53 static int verbose = 0;
54
55 static unsigned int *mmio;
56 static unsigned int graphics;
57 static unsigned short addrport;
58 static unsigned short dataport;
59 static unsigned int physbase;
60 #if 0 //undefined reference
61 extern int oprom_is_loaded;
62 #else
63 int oprom_is_loaded;
64 #endif
65
66 #define PGETBL_CTL              0x2020
67 #define PGETBL_ENABLED          0x00000001
68
69
70 static u32 htotal, hblank, hsync, vtotal, vblank, vsync;
71
72 const u32 x60_edid_data[] = {
73         0x00ffffff, 0xffffff00, 0x30ae0040, 0x00000000,
74         0x000f0103, 0x80191278, 0xeaed7591, 0x574f8b26,
75         0x21505421, 0x08000101, 0x01010101, 0x01010101,
76         0x01010101, 0x01012815, 0x00404100, 0x26301888,
77         0x3600f6b9, 0x00000018, 0xed100040, 0x41002630,
78         0x18883600, 0xf6b90000, 0x00180000, 0x000f0061,
79         0x43326143, 0x280f0100, 0x4ca3584a, 0x000000fe,
80         0x004c544e, 0x31323158, 0x4a2d4c30, 0x370a0000,
81 };
82 #define READ32(addr) io_i915_READ32(addr)
83 #define WRITE32(val, addr) io_i915_WRITE32(val, addr)
84
85 static char *regname(unsigned long addr)
86 {
87         static char name[16];
88         sprintf(name, "0x%lx", addr);
89         return name;
90 }
91
92 unsigned long io_i915_READ32(unsigned long addr)
93 {
94         unsigned long val;
95         outl(addr, addrport);
96         val = inl(dataport);
97         if (verbose & vio)
98                 printk(BIOS_SPEW, "%s: Got %08lx\n", regname(addr), val);
99         return val;
100 }
101
102 void io_i915_WRITE32(unsigned long val, unsigned long addr)
103 {
104         if (verbose & vio)
105                 printk(BIOS_SPEW, "%s: outl %08lx\n", regname(addr), val);
106         outl(addr, addrport);
107         outl(val, dataport);
108 }
109
110
111 /*
112   2560
113   4 words per
114   4 *p
115   10240
116   4k bytes per page
117   4096/p
118   2.50
119   1700 lines
120   1700 * p
121   4250.00
122   PTEs
123 */
124 static void
125 setgtt(int start, int end, unsigned long base, int inc)
126 {
127         int i;
128
129         printk(BIOS_INFO, "%s(%d,%d,0x%08lx,%d);\n",__func__, start, end, base, inc);
130
131         for(i = start; i < end; i++){
132                 //udelay(100);
133                 u32 word = base + i*inc;
134                 WRITE32(word|1,(i*4)|1);
135         }
136 }
137
138 int gtt_setup(unsigned int mmiobase);
139 int gtt_setup(unsigned int mmiobase)
140 {
141         unsigned long PGETBL_save;
142
143         PGETBL_save = read32(mmiobase + PGETBL_CTL) & ~PGETBL_ENABLED;
144         PGETBL_save |= PGETBL_ENABLED;
145
146         printk(BIOS_DEBUG, "PGETBL_save=0x%lx\n",PGETBL_save );
147
148         write32(mmiobase + GFX_FLSH_CNTL, 0);
149
150         write32(mmiobase + PGETBL_CTL, PGETBL_save);
151
152         /* verify */
153         if ( read32( mmiobase + PGETBL_CTL) & PGETBL_ENABLED ){
154                 printk(BIOS_DEBUG, "gtt_setup is enabled!!!\n");
155         }else{
156                 printk(BIOS_DEBUG, "gtt_setup failed!!!\n");
157                 return 1;
158         }
159         write32(mmiobase + GFX_FLSH_CNTL, 0);
160
161         return 0;
162
163
164 }
165
166
167
168
169 static unsigned long tickspermicrosecond = 1795;
170 static unsigned long long globalstart;
171
172 static unsigned long
173 microseconds(unsigned long long start, unsigned long long end)
174 {
175         unsigned long ret;
176         ret = ((end - start)/tickspermicrosecond);
177         return ret;
178 }
179
180 static unsigned long globalmicroseconds(void)
181 {
182         return microseconds(globalstart, rdtscll());
183 }
184
185 extern struct iodef iodefs[];
186 extern int niodefs;
187
188 static int i915_init_done = 0;
189
190 /* fill the palette. This runs when the P opcode is hit. */
191 static void palette(void)
192 {
193         int i;
194         unsigned long color = 0;
195
196         for(i = 0; i < 256; i++, color += 0x010101){
197                 io_i915_WRITE32(color, _LGC_PALETTE_A + (i<<2));
198         }
199 }
200
201 int vbe_mode_info_valid(void);
202 int vbe_mode_info_valid(void)
203 {
204         return i915_init_done;
205 }
206
207 void fill_lb_framebuffer(struct lb_framebuffer *framebuffer);
208 void fill_lb_framebuffer(struct lb_framebuffer *framebuffer)
209 {
210         printk(BIOS_SPEW, "fill_lb_framebuffer: graphics is %p\n", (void *)graphics);
211         framebuffer->physical_address = graphics;
212         framebuffer->x_resolution = 1024;
213         framebuffer->y_resolution = 768;
214         framebuffer->bytes_per_line = 4096;
215         framebuffer->bits_per_pixel = 32;
216         framebuffer->red_mask_pos = 16;
217         framebuffer->red_mask_size = 8;
218         framebuffer->green_mask_pos = 8;
219         framebuffer->green_mask_size = 8;
220         framebuffer->blue_mask_pos = 0;
221         framebuffer->blue_mask_size = 8;
222         framebuffer->reserved_mask_pos = 24;
223         framebuffer->reserved_mask_size = 8;
224 }
225
226 static unsigned long times[4096];
227
228 static int run(int index)
229 {
230         int i, prev = 0;
231         struct iodef *id, *lastidread = 0;
232         unsigned long u, t;
233         if (index >= niodefs)
234                 return index;
235         /* state machine! */
236         for(i = index, id = &iodefs[i]; id->op; i++, id++){
237                 switch(id->op){
238                 case M:
239                         if (verbose & vmsg) printk(BIOS_SPEW, "%ld: %s\n",
240                                                 globalmicroseconds(), id->msg);
241                         break;
242                 case P:
243                         palette();
244                         break;
245                 case R:
246                         u = READ32(id->addr);
247                         if (verbose & vio)
248                                 printk(BIOS_SPEW, "\texpect %08lx\n", id->data);
249                         /* we're looking for something. */
250                         if (lastidread->addr == id->addr){
251                                 /* they're going to be polling.
252                                  * just do it 1000 times
253                                  */
254                                 for (t = 0; t < 1000 && id->data != u; t++){
255                                         u = READ32(id->addr);
256                                 }
257                                 if (verbose & vspin) printk(BIOS_SPEW,
258                                                 "%s: # loops %ld got %08lx want %08lx\n",
259                                                 regname(id->addr),
260                                                 t, u, id->data);
261                         }
262                         lastidread = id;
263                         break;
264                 case W:
265                         WRITE32(id->data, id->addr);
266                         if (id->addr == PCH_PP_CONTROL){
267                                 if (verbose & vio)
268                                         printk(BIOS_SPEW, "PCH_PP_CONTROL\n");
269                                 switch(id->data & 0xf){
270                                 case 8: break;
271                                 case 7: break;
272                                 default: udelay(100000);
273                                         if (verbose & vio)
274                                                 printk(BIOS_SPEW, "U %d\n", 100000);
275                                 }
276                         }
277                         break;
278                 case V:
279                         if (id->count < 8){
280                                 prev = verbose;
281                                 verbose = id->count;
282                         } else {
283                                 verbose = prev;
284                         }
285                         printk(BIOS_SPEW, "Change verbosity to %d\n", verbose);
286                         break;
287                 case I:
288                         printk(BIOS_SPEW, "run: return %d\n", i+1);
289                         return i+1;
290                         break;
291                 default:
292                         printk(BIOS_SPEW, "BAD TABLE, opcode %d @ %d\n", id->op, i);
293                         return -1;
294                 }
295                 if (id->udelay)
296                         udelay(id->udelay);
297                 if (i < ARRAY_SIZE(times))
298                         times[i] = globalmicroseconds();
299         }
300         printk(BIOS_SPEW, "run: return %d\n", i);
301         return i+1;
302 }
303
304 int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio,
305                 unsigned int gfx);
306
307 int i915lightup(unsigned int pphysbase, unsigned int piobase,
308                 unsigned int pmmio, unsigned int pgfx)
309 {
310         static struct edid edid;
311
312         int index;
313         unsigned long temp;
314         u32 auxin[16], auxout[16];
315         mmio = (void *)pmmio;
316         addrport = piobase;
317         dataport = addrport + 4;
318         physbase = pphysbase;
319         graphics = pgfx;
320         printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p"
321                 "addrport %04x physbase %08x\n",
322                 (void *)graphics, mmio, addrport, physbase);
323         globalstart = rdtscll();
324
325
326         decode_edid((unsigned char *)&x60_edid_data, sizeof(x60_edid_data), &edid);
327
328         htotal = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16);
329         printk(BIOS_SPEW, "I915_WRITE(HTOTAL(pipe), %08x)\n", htotal);
330
331         hblank = (edid.ha  - 1) | ((edid.ha + edid.hbl- 1) << 16);
332         printk(BIOS_SPEW, "I915_WRITE(HBLANK(pipe),0x%08x)\n", hblank);
333
334         hsync = (edid.ha + edid.hso  - 1) |
335                 ((edid.ha + edid.hso + edid.hspw- 1) << 16);
336         printk(BIOS_SPEW, "I915_WRITE(HSYNC(pipe),0x%08x)\n", hsync);
337
338         vtotal = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16);
339         printk(BIOS_SPEW, "I915_WRITE(VTOTAL(pipe), %08x)\n", vtotal);
340
341         vblank = (edid.va  - 1) | ((edid.va + edid.vbl- 1) << 16);
342         printk(BIOS_SPEW, "I915_WRITE(VBLANK(pipe),0x%08x)\n", vblank);
343
344         vsync = (edid.va + edid.vso  - 1) |((edid.va + edid.vso + edid.vspw- 1) << 16);
345         printk(BIOS_SPEW, "I915_WRITE(VSYNC(pipe),0x%08x)\n", vsync);
346
347         printk(BIOS_SPEW, "Table has %d elements\n", niodefs);
348
349         index = run(0);
350         printk(BIOS_SPEW, "Run returns %d\n", index);
351         auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_DPCD_REV<<8|0xe;
352         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 14);
353         auxout[0] = 0<<31 /* i2c */|1<<30|0x0<<28/*W*/|0x0<<8|0x0;
354         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0);
355         index = run(index);
356         printk(BIOS_SPEW, "Run returns %d\n", index);
357         auxout[0] = 0<<31 /* i2c */|0<<30|0x0<<28/*W*/|0x0<<8|0x0;
358         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0);
359         index = run(index);
360         printk(BIOS_SPEW, "Run returns %d\n", index);
361         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_SET_POWER<<8|0x0;
362         auxout[1] = 0x01000000;
363         /* DP_SET_POWER_D0 | DP_PSR_SINK_INACTIVE */
364         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
365         index = run(index);
366         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_LINK_BW_SET<<8|0x8;
367         auxout[1] = 0x0a840000;
368         /*( DP_LINK_BW_2_7 &0xa)|0x0000840a*/
369         auxout[2] = 0x00000000;
370         auxout[3] = 0x01000000;
371         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 13, auxin, 0);
372         index = run(index);
373         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
374         auxout[1] = 0x21000000;
375         /* DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE |
376          *      DP_SYMBOL_ERROR_COUNT_BOTH |0x00000021*/
377         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
378         index = run(index);
379         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3;
380         auxout[1] = 0x00000000;
381         /* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/
382         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0);
383         index = run(index);
384         auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5;
385         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5);
386         index = run(index);
387         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
388         auxout[1] = 0x22000000;
389         /* DP_TRAINING_PATTERN_2 | DP_LINK_SCRAMBLING_DISABLE |
390          *      DP_SYMBOL_ERROR_COUNT_BOTH |0x00000022*/
391         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
392         index = run(index);
393         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3;
394         auxout[1] = 0x00000000;
395         /* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/
396         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0);
397         index = run(index);
398         auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5;
399         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5);
400         index = run(index);
401         auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
402         auxout[1] = 0x00000000;
403         /* DP_TRAINING_PATTERN_DISABLE | DP_LINK_QUAL_PATTERN_DISABLE |
404          *      DP_SYMBOL_ERROR_COUNT_BOTH |0x00000000*/
405         intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
406         index = run(index);
407
408         if (index != niodefs)
409                 printk(BIOS_ERR, "Left over IO work in i915_lightup"
410                         " -- this is likely a table error. "
411                         "Only %d of %d were done.\n", index, niodefs);
412         printk(BIOS_SPEW, "DONE startup\n");
413         verbose = 0;
414         /* GTT is the Global Translation Table for the graphics pipeline.
415          * It is used to translate graphics addresses to physical
416          * memory addresses. As in the CPU, GTTs map 4K pages.
417          * There are 32 bits per pixel, or 4 bytes,
418          * which means 1024 pixels per page.
419          * There are 4250 GTTs on Link:
420          * 2650 (X) * 1700 (Y) pixels / 1024 pixels per page.
421          * The setgtt function adds a further bit of flexibility:
422          * it allows you to set a range (the first two parameters) to point
423          * to a physical address (third parameter);the physical address is
424          * incremented by a count (fourth parameter) for each GTT in the
425          * range.
426          * Why do it this way? For ultrafast startup,
427          * we can point all the GTT entries to point to one page,
428          * and set that page to 0s:
429          * memset(physbase, 0, 4096);
430          * setgtt(0, 4250, physbase, 0);
431          * this takes about 2 ms, and is a win because zeroing
432          * the page takes a up to 200 ms. We will be exploiting this
433          * trick in a later rev of this code.
434          * This call sets the GTT to point to a linear range of pages
435          * starting at physbase.
436          */
437         delay(1);
438
439         if ( gtt_setup(pmmio) ){
440                 printk(BIOS_ERR, "ERROR: GTT Setup Failed!!!\n");
441                 return 0;
442         }
443
444         setgtt(0, 776, physbase, 4096);
445
446         temp = READ32(PGETLB_CTL); 
447         printk(BIOS_INFO, "GTT PGETLB_CTL register: 0x%lx\n", temp);
448
449         if (temp & 1)
450                 printk(BIOS_INFO, "GTT Enabled\n");
451         else
452                 printk(BIOS_ERR, "ERROR: GTT is still Disabled!!!\n");
453
454         printk(BIOS_SPEW, "memset %p to 0x00 for %d bytes\n",
455                 (void *)graphics, FRAME_BUFFER_BYTES);
456         memset((void *)graphics, 0x00, FRAME_BUFFER_BYTES);
457
458         printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds());
459         i915_init_done = 1;
460         oprom_is_loaded = 1;
461         return 0;
462 }