Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 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. |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 14 | */ |
| 15 | |
| 16 | #include <types.h> |
| 17 | #include <string.h> |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 18 | #include <stdlib.h> |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 19 | #include <device/device.h> |
| 20 | #include <device/device.h> |
| 21 | #include <device/pci_def.h> |
| 22 | #include <device/pci_ops.h> |
| 23 | #include <console/console.h> |
| 24 | #include <delay.h> |
| 25 | #include <pc80/mc146818rtc.h> |
| 26 | #include <arch/acpi.h> |
| 27 | #include <arch/io.h> |
| 28 | #include <arch/interrupt.h> |
Stefan Reinauer | 3e4e303 | 2013-03-20 14:08:04 -0700 | [diff] [blame] | 29 | #include <boot/coreboot_tables.h> |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 30 | #include "onboard.h" |
| 31 | #include "ec.h" |
| 32 | #include <southbridge/intel/bd82x6x/pch.h> |
Vladimir Serbinenko | 12fcb86 | 2014-02-23 00:09:48 +0100 | [diff] [blame] | 33 | #include <northbridge/intel/sandybridge/gma.h> |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 34 | #include <smbios.h> |
| 35 | #include <device/pci.h> |
| 36 | #include <ec/google/chromeec/ec.h> |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 37 | |
| 38 | #include <cpu/x86/tsc.h> |
| 39 | #include <cpu/x86/cache.h> |
| 40 | #include <cpu/x86/mtrr.h> |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 41 | #include <cpu/x86/msr.h> |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 42 | #include <edid.h> |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 43 | #include "i915io.h" |
| 44 | |
| 45 | enum { |
| 46 | vmsg = 1, vio = 2, vspin = 4, |
| 47 | }; |
| 48 | |
| 49 | static int verbose = 0; |
| 50 | |
| 51 | static unsigned int *mmio; |
| 52 | static unsigned int graphics; |
| 53 | static unsigned short addrport; |
| 54 | static unsigned short dataport; |
| 55 | static unsigned int physbase; |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 56 | static u32 htotal, hblank, hsync, vtotal, vblank, vsync; |
| 57 | |
| 58 | const u32 link_edid_data[] = { |
| 59 | 0xffffff00, 0x00ffffff, 0x0379e430, 0x00000000, |
| 60 | 0x04011500, 0x96121ba5, 0xa2d54f02, 0x26935259, |
| 61 | 0x00545017, 0x01010000, 0x01010101, 0x01010101, |
| 62 | 0x01010101, 0x6f6d0101, 0xa4a0a000, 0x20306031, |
| 63 | 0xb510003a, 0x19000010, 0x00000000, 0x00000000, |
| 64 | 0x00000000, 0x00000000, 0x00000000, 0x4c00fe00, |
| 65 | 0x69442047, 0x616c7073, 0x20200a79, 0xfe000000, |
| 66 | 0x31504c00, 0x45513932, 0x50532d31, 0x24003141, |
| 67 | }; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 68 | |
| 69 | #define READ32(addr) io_i915_READ32(addr) |
| 70 | #define WRITE32(val, addr) io_i915_WRITE32(val, addr) |
| 71 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 72 | static char *regname(unsigned long addr) |
| 73 | { |
| 74 | static char name[16]; |
Vladimir Serbinenko | a37383d | 2013-11-26 02:41:26 +0100 | [diff] [blame] | 75 | snprintf(name, sizeof (name), "0x%lx", addr); |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 76 | return name; |
| 77 | } |
| 78 | |
Ronald G. Minnich | 665e3d2 | 2013-02-27 09:54:47 -0800 | [diff] [blame] | 79 | unsigned long io_i915_READ32(unsigned long addr) |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 80 | { |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 81 | unsigned long val; |
| 82 | outl(addr, addrport); |
| 83 | val = inl(dataport); |
| 84 | if (verbose & vio) |
| 85 | printk(BIOS_SPEW, "%s: Got %08lx\n", regname(addr), val); |
| 86 | return val; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 87 | } |
| 88 | |
Ronald G. Minnich | 665e3d2 | 2013-02-27 09:54:47 -0800 | [diff] [blame] | 89 | void io_i915_WRITE32(unsigned long val, unsigned long addr) |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 90 | { |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 91 | if (verbose & vio) |
| 92 | printk(BIOS_SPEW, "%s: outl %08lx\n", regname(addr), val); |
| 93 | outl(addr, addrport); |
| 94 | outl(val, dataport); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | |
| 98 | /* |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 99 | 2560 |
| 100 | 4 words per |
| 101 | 4 *p |
| 102 | 10240 |
| 103 | 4k bytes per page |
| 104 | 4096/p |
| 105 | 2.50 |
| 106 | 1700 lines |
| 107 | 1700 * p |
| 108 | 4250.00 |
| 109 | PTEs |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 110 | */ |
| 111 | static void |
| 112 | setgtt(int start, int end, unsigned long base, int inc) |
| 113 | { |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 114 | int i; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 115 | |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 116 | for(i = start; i < end; i++){ |
| 117 | u32 word = base + i*inc; |
| 118 | WRITE32(word|1,(i*4)|1); |
| 119 | } |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 120 | } |
| 121 | |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 122 | static unsigned long tickspermicrosecond = 1795; |
| 123 | static unsigned long long globalstart; |
| 124 | |
| 125 | static unsigned long |
| 126 | microseconds(unsigned long long start, unsigned long long end) |
| 127 | { |
| 128 | unsigned long ret; |
| 129 | ret = ((end - start)/tickspermicrosecond); |
| 130 | return ret; |
| 131 | } |
| 132 | |
| 133 | static unsigned long globalmicroseconds(void) |
| 134 | { |
| 135 | return microseconds(globalstart, rdtscll()); |
| 136 | } |
| 137 | |
| 138 | extern struct iodef iodefs[]; |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 139 | extern int niodefs; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 140 | |
| 141 | static int i915_init_done = 0; |
| 142 | |
Ronald G. Minnich | ec2d914 | 2013-03-05 13:32:24 -0800 | [diff] [blame] | 143 | /* fill the palette. This runs when the P opcode is hit. */ |
Ronald G. Minnich | 7982de1 | 2013-06-05 08:35:52 -0700 | [diff] [blame] | 144 | /* and, yes, it's needed for even 32 bits per pixel */ |
Ronald G. Minnich | ec2d914 | 2013-03-05 13:32:24 -0800 | [diff] [blame] | 145 | static void palette(void) |
| 146 | { |
| 147 | int i; |
| 148 | unsigned long color = 0; |
| 149 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 150 | for(i = 0; i < 256; i++, color += 0x010101){ |
Ronald G. Minnich | ec2d914 | 2013-03-05 13:32:24 -0800 | [diff] [blame] | 151 | io_i915_WRITE32(color, _LGC_PALETTE_A + (i<<2)); |
| 152 | } |
| 153 | } |
| 154 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 155 | static unsigned long times[4096]; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 156 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 157 | static int run(int index) |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 158 | { |
| 159 | int i, prev = 0; |
| 160 | struct iodef *id, *lastidread = 0; |
| 161 | unsigned long u, t; |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 162 | if (index >= niodefs) |
| 163 | return index; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 164 | /* state machine! */ |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 165 | for(i = index, id = &iodefs[i]; id->op; i++, id++){ |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 166 | switch(id->op){ |
| 167 | case M: |
| 168 | if (verbose & vmsg) printk(BIOS_SPEW, "%ld: %s\n", |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 169 | globalmicroseconds(), id->msg); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 170 | break; |
Ronald G. Minnich | ec2d914 | 2013-03-05 13:32:24 -0800 | [diff] [blame] | 171 | case P: |
| 172 | palette(); |
| 173 | break; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 174 | case R: |
| 175 | u = READ32(id->addr); |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 176 | if (verbose & vio) |
| 177 | printk(BIOS_SPEW, "\texpect %08lx\n", id->data); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 178 | /* we're looking for something. */ |
| 179 | if (lastidread->addr == id->addr){ |
| 180 | /* they're going to be polling. |
| 181 | * just do it 1000 times |
| 182 | */ |
Ronald G. Minnich | ec2d914 | 2013-03-05 13:32:24 -0800 | [diff] [blame] | 183 | for (t = 0; t < 1000 && id->data != u; t++){ |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 184 | u = READ32(id->addr); |
| 185 | } |
| 186 | if (verbose & vspin) printk(BIOS_SPEW, |
| 187 | "%s: # loops %ld got %08lx want %08lx\n", |
| 188 | regname(id->addr), |
| 189 | t, u, id->data); |
| 190 | } |
| 191 | lastidread = id; |
| 192 | break; |
| 193 | case W: |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 194 | WRITE32(id->data, id->addr); |
| 195 | if (id->addr == PCH_PP_CONTROL){ |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 196 | if (verbose & vio) |
| 197 | printk(BIOS_SPEW, "PCH_PP_CONTROL\n"); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 198 | switch(id->data & 0xf){ |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 199 | case 8: break; |
| 200 | case 7: break; |
| 201 | default: udelay(100000); |
| 202 | if (verbose & vio) |
| 203 | printk(BIOS_SPEW, "U %d\n", 100000); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 204 | } |
| 205 | } |
| 206 | break; |
| 207 | case V: |
| 208 | if (id->count < 8){ |
| 209 | prev = verbose; |
| 210 | verbose = id->count; |
| 211 | } else { |
| 212 | verbose = prev; |
| 213 | } |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 214 | printk(BIOS_SPEW, "Change verbosity to %d\n", verbose); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 215 | break; |
| 216 | case I: |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 217 | printk(BIOS_SPEW, "run: return %d\n", i+1); |
| 218 | return i+1; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 219 | break; |
| 220 | default: |
| 221 | printk(BIOS_SPEW, "BAD TABLE, opcode %d @ %d\n", id->op, i); |
| 222 | return -1; |
| 223 | } |
| 224 | if (id->udelay) |
| 225 | udelay(id->udelay); |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 226 | if (i < ARRAY_SIZE(times)) |
| 227 | times[i] = globalmicroseconds(); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 228 | } |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 229 | printk(BIOS_SPEW, "run: return %d\n", i); |
| 230 | return i+1; |
| 231 | } |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 232 | |
Vladimir Serbinenko | a71bdc3 | 2014-08-30 00:35:39 +0200 | [diff] [blame] | 233 | int i915lightup_sandy(const struct i915_gpu_controller_info *info, |
| 234 | u32 pphysbase, u16 piobase, u32 pmmio, u32 pgfx) |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 235 | { |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 236 | static struct edid edid; |
Ronald G. Minnich | 7982de1 | 2013-06-05 08:35:52 -0700 | [diff] [blame] | 237 | int edid_ok; |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 238 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 239 | int index; |
| 240 | u32 auxin[16], auxout[16]; |
| 241 | mmio = (void *)pmmio; |
| 242 | addrport = piobase; |
| 243 | dataport = addrport + 4; |
| 244 | physbase = pphysbase; |
| 245 | graphics = pgfx; |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 246 | printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p" |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 247 | "addrport %04x physbase %08x\n", |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 248 | (void *)graphics, mmio, addrport, physbase); |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 249 | globalstart = rdtscll(); |
| 250 | |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 251 | |
Ronald G. Minnich | 7982de1 | 2013-06-05 08:35:52 -0700 | [diff] [blame] | 252 | edid_ok = decode_edid((unsigned char *)&link_edid_data, |
| 253 | sizeof(link_edid_data), &edid); |
| 254 | printk(BIOS_SPEW, "decode edid returns %d\n", edid_ok); |
Ronald G. Minnich | 9518b56 | 2013-09-19 16:45:22 -0700 | [diff] [blame] | 255 | edid.framebuffer_bits_per_pixel = 32; |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 256 | |
| 257 | htotal = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16); |
| 258 | printk(BIOS_SPEW, "I915_WRITE(HTOTAL(pipe), %08x)\n", htotal); |
| 259 | |
| 260 | hblank = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16); |
| 261 | printk(BIOS_SPEW, "I915_WRITE(HBLANK(pipe),0x%08x)\n", hblank); |
| 262 | |
| 263 | hsync = (edid.ha + edid.hso - 1) | |
| 264 | ((edid.ha + edid.hso + edid.hspw- 1) << 16); |
| 265 | printk(BIOS_SPEW, "I915_WRITE(HSYNC(pipe),0x%08x)\n", hsync); |
| 266 | |
| 267 | vtotal = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16); |
| 268 | printk(BIOS_SPEW, "I915_WRITE(VTOTAL(pipe), %08x)\n", vtotal); |
| 269 | |
| 270 | vblank = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16); |
| 271 | printk(BIOS_SPEW, "I915_WRITE(VBLANK(pipe),0x%08x)\n", vblank); |
| 272 | |
| 273 | vsync = (edid.va + edid.vso - 1) |((edid.va + edid.vso + edid.vspw- 1) << 16); |
| 274 | printk(BIOS_SPEW, "I915_WRITE(VSYNC(pipe),0x%08x)\n", vsync); |
| 275 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 276 | printk(BIOS_SPEW, "Table has %d elements\n", niodefs); |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 277 | |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 278 | index = run(0); |
| 279 | printk(BIOS_SPEW, "Run returns %d\n", index); |
| 280 | auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_DPCD_REV<<8|0xe; |
| 281 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 14); |
| 282 | auxout[0] = 0<<31 /* i2c */|1<<30|0x0<<28/*W*/|0x0<<8|0x0; |
| 283 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0); |
| 284 | index = run(index); |
| 285 | printk(BIOS_SPEW, "Run returns %d\n", index); |
| 286 | auxout[0] = 0<<31 /* i2c */|0<<30|0x0<<28/*W*/|0x0<<8|0x0; |
| 287 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0); |
| 288 | index = run(index); |
| 289 | printk(BIOS_SPEW, "Run returns %d\n", index); |
| 290 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_SET_POWER<<8|0x0; |
| 291 | auxout[1] = 0x01000000; |
| 292 | /* DP_SET_POWER_D0 | DP_PSR_SINK_INACTIVE */ |
| 293 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0); |
| 294 | index = run(index); |
| 295 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_LINK_BW_SET<<8|0x8; |
| 296 | auxout[1] = 0x0a840000; |
| 297 | /*( DP_LINK_BW_2_7 &0xa)|0x0000840a*/ |
| 298 | auxout[2] = 0x00000000; |
| 299 | auxout[3] = 0x01000000; |
| 300 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 13, auxin, 0); |
| 301 | index = run(index); |
| 302 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0; |
| 303 | auxout[1] = 0x21000000; |
| 304 | /* DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE | |
| 305 | * DP_SYMBOL_ERROR_COUNT_BOTH |0x00000021*/ |
| 306 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0); |
| 307 | index = run(index); |
| 308 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3; |
| 309 | auxout[1] = 0x00000000; |
| 310 | /* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/ |
| 311 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0); |
| 312 | index = run(index); |
| 313 | auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5; |
| 314 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5); |
| 315 | index = run(index); |
| 316 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0; |
| 317 | auxout[1] = 0x22000000; |
| 318 | /* DP_TRAINING_PATTERN_2 | DP_LINK_SCRAMBLING_DISABLE | |
| 319 | * DP_SYMBOL_ERROR_COUNT_BOTH |0x00000022*/ |
| 320 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0); |
| 321 | index = run(index); |
| 322 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3; |
| 323 | auxout[1] = 0x00000000; |
| 324 | /* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/ |
| 325 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0); |
| 326 | index = run(index); |
| 327 | auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5; |
| 328 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5); |
| 329 | index = run(index); |
| 330 | auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0; |
| 331 | auxout[1] = 0x00000000; |
| 332 | /* DP_TRAINING_PATTERN_DISABLE | DP_LINK_QUAL_PATTERN_DISABLE | |
| 333 | * DP_SYMBOL_ERROR_COUNT_BOTH |0x00000000*/ |
| 334 | intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0); |
| 335 | index = run(index); |
| 336 | |
| 337 | if (index != niodefs) |
| 338 | printk(BIOS_ERR, "Left over IO work in i915_lightup" |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 339 | " -- this is likely a table error. " |
| 340 | "Only %d of %d were done.\n", index, niodefs); |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 341 | printk(BIOS_SPEW, "DONE startup\n"); |
| 342 | verbose = 0; |
| 343 | /* GTT is the Global Translation Table for the graphics pipeline. |
| 344 | * It is used to translate graphics addresses to physical |
| 345 | * memory addresses. As in the CPU, GTTs map 4K pages. |
| 346 | * There are 32 bits per pixel, or 4 bytes, |
| 347 | * which means 1024 pixels per page. |
| 348 | * There are 4250 GTTs on Link: |
| 349 | * 2650 (X) * 1700 (Y) pixels / 1024 pixels per page. |
| 350 | * The setgtt function adds a further bit of flexibility: |
| 351 | * it allows you to set a range (the first two parameters) to point |
| 352 | * to a physical address (third parameter);the physical address is |
| 353 | * incremented by a count (fourth parameter) for each GTT in the |
| 354 | * range. |
| 355 | * Why do it this way? For ultrafast startup, |
| 356 | * we can point all the GTT entries to point to one page, |
| 357 | * and set that page to 0s: |
| 358 | * memset(physbase, 0, 4096); |
| 359 | * setgtt(0, 4250, physbase, 0); |
| 360 | * this takes about 2 ms, and is a win because zeroing |
| 361 | * the page takes a up to 200 ms. We will be exploiting this |
| 362 | * trick in a later rev of this code. |
| 363 | * This call sets the GTT to point to a linear range of pages |
| 364 | * starting at physbase. |
| 365 | */ |
| 366 | setgtt(0, FRAME_BUFFER_PAGES, physbase, 4096); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 367 | printk(BIOS_SPEW, "memset %p to 0 for %d bytes\n", |
Ronald G. Minnich | b3b72f3 | 2013-03-13 14:35:01 -0700 | [diff] [blame] | 368 | (void *)graphics, FRAME_BUFFER_BYTES); |
Ronald G. Minnich | a95a13b | 2013-03-05 17:07:40 -0800 | [diff] [blame] | 369 | memset((void *)graphics, 0, FRAME_BUFFER_BYTES); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 370 | printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds()); |
Ronald G. Minnich | 3a75e5e | 2013-10-28 15:01:54 -0700 | [diff] [blame] | 371 | set_vbe_mode_info_valid(&edid, (uintptr_t)graphics); |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 372 | i915_init_done = 1; |
Kyösti Mälkki | ab56b3b | 2013-11-28 16:44:51 +0200 | [diff] [blame] | 373 | return i915_init_done; |
Stefan Reinauer | 49428d8 | 2013-02-21 15:48:37 -0800 | [diff] [blame] | 374 | } |