aboutsummaryrefslogtreecommitdiff
path: root/src/mainboard/intel/wtm2/i915.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainboard/intel/wtm2/i915.c')
-rw-r--r--src/mainboard/intel/wtm2/i915.c333
1 files changed, 90 insertions, 243 deletions
diff --git a/src/mainboard/intel/wtm2/i915.c b/src/mainboard/intel/wtm2/i915.c
index 41c8b15e1c..8103016c51 100644
--- a/src/mainboard/intel/wtm2/i915.c
+++ b/src/mainboard/intel/wtm2/i915.c
@@ -30,7 +30,7 @@
#include <arch/acpi.h>
#include <arch/io.h>
#include <arch/interrupt.h>
-#include <arch/coreboot_tables.h>
+#include <boot/coreboot_tables.h>
#include "hda_verb.h"
#include <smbios.h>
#include <device/pci.h>
@@ -40,15 +40,10 @@
#include <cpu/x86/tsc.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/mtrr.h>
-#include <cpu/amd/mtrr.h>
#include <cpu/x86/msr.h>
#include <edid.h>
#include "i915io.h"
-enum {
- vmsg = 1, vio = 2, vspin = 4,
-};
-
static int verbose = 0;
static unsigned int *mmio;
@@ -57,7 +52,6 @@ static unsigned short addrport;
static unsigned short dataport;
static unsigned int physbase;
extern int oprom_is_loaded;
-static u32 htotal, hblank, hsync, vtotal, vblank, vsync;
const u32 link_edid_data[] = {
0xffffff00, 0x00ffffff, 0x0379e430, 0x00000000,
@@ -70,8 +64,7 @@ const u32 link_edid_data[] = {
0x31504c00, 0x45513932, 0x50532d31, 0x24003141,
};
-#define READ32(addr) io_i915_READ32(addr)
-#define WRITE32(val, addr) io_i915_WRITE32(val, addr)
+static int ioread = 0, iowrite = 0;
static char *regname(unsigned long addr)
{
@@ -80,36 +73,43 @@ static char *regname(unsigned long addr)
return name;
}
-unsigned long io_i915_READ32(unsigned long addr)
+unsigned long io_i915_read32(unsigned long addr)
{
unsigned long val;
outl(addr, addrport);
val = inl(dataport);
+ ioread += 2;
if (verbose & vio)printk(BIOS_SPEW, "%s: Got %08lx\n", regname(addr), val);
return val;
}
-void io_i915_WRITE32(unsigned long val, unsigned long addr)
+void io_i915_write32(unsigned long val, unsigned long addr)
{
if (verbose & vio)printk(BIOS_SPEW, "%s: outl %08lx\n", regname(addr), val);
outl(addr, addrport);
outl(val, dataport);
+ iowrite += 2;
}
+/* GTT is the Global Translation Table for the graphics pipeline.
+ * It is used to translate graphics addresses to physical
+ * memory addresses. As in the CPU, GTTs map 4K pages.
+ * The setgtt function adds a further bit of flexibility:
+ * it allows you to set a range (the first two parameters) to point
+ * to a physical address (third parameter);the physical address is
+ * incremented by a count (fourth parameter) for each GTT in the
+ * range.
+ * Why do it this way? For ultrafast startup,
+ * we can point all the GTT entries to point to one page,
+ * and set that page to 0s:
+ * memset(physbase, 0, 4096);
+ * setgtt(0, 4250, physbase, 0);
+ * this takes about 2 ms, and is a win because zeroing
+ * the page takes a up to 200 ms.
+ * This call sets the GTT to point to a linear range of pages
+ * starting at physbase.
+ */
-/*
- 2560
- 4 words per
- 4 *p
- 10240
- 4k bytes per page
- 4096/p
- 2.50
- 1700 lines
- 1700 * p
- 4250.00
- PTEs
-*/
static void
setgtt(int start, int end, unsigned long base, int inc)
{
@@ -117,7 +117,7 @@ setgtt(int start, int end, unsigned long base, int inc)
for(i = start; i < end; i++){
u32 word = base + i*inc;
- WRITE32(word|1,(i*4)|1);
+ io_i915_write32(word|1,(i*4)|1);
}
}
@@ -137,36 +137,29 @@ static unsigned long globalmicroseconds(void)
return microseconds(globalstart, rdtscll());
}
-extern struct iodef iodefs[];
-extern int niodefs;
-
static int i915_init_done = 0;
-/* fill the palette. This runs when the P opcode is hit. */
-static void palette(void)
-{
- int i;
- unsigned long color = 0;
-
- for(i = 0; i < 256; i++, color += 0x010101){
- io_i915_WRITE32(color, _LGC_PALETTE_A + (i<<2));
- }
-}
-
-int vbe_mode_info_valid(void);
int vbe_mode_info_valid(void)
{
return i915_init_done;
}
-void fill_lb_framebuffer(struct lb_framebuffer *framebuffer);
void fill_lb_framebuffer(struct lb_framebuffer *framebuffer)
{
- printk(BIOS_SPEW, "fill_lb_framebuffer: graphics is %p\n", (void *)graphics);
+ printk(BIOS_SPEW, "fill_lb_framebuffer: graphics is %p\n",
+ (void *)graphics);
+ /* Please note: these will be filled from EDID.
+ * these values are a placeholder.
+ */
framebuffer->physical_address = graphics;
- framebuffer->x_resolution = 2560;
+ /* these are a fantasy, but will be fixed once we're getting
+ * info from the hardware. Hard to get from the device tree,
+ * which is arguably a defect of the device tree. Bear with me,
+ * this Will Get Fixed.
+ */
+ framebuffer->x_resolution = 1960;
framebuffer->y_resolution = 1700;
- framebuffer->bytes_per_line = 10240;
+ framebuffer->bytes_per_line = 1960*4;
framebuffer->bits_per_pixel = 32;
framebuffer->red_mask_pos = 16;
framebuffer->red_mask_size = 8;
@@ -179,94 +172,21 @@ void fill_lb_framebuffer(struct lb_framebuffer *framebuffer)
}
-static unsigned long times[4096];
-
-static int run(int index)
-{
- int i, prev = 0;
- struct iodef *id, *lastidread = 0;
- unsigned long u, t;
- if (index >= niodefs)
- return index;
- /* state machine! */
- for(i = index, id = &iodefs[i]; id->op; i++, id++){
- switch(id->op){
- case M:
- if (verbose & vmsg) printk(BIOS_SPEW, "%ld: %s\n",
- globalmicroseconds(), id->msg);
- break;
- case P:
- palette();
- break;
- case R:
- u = READ32(id->addr);
- if (verbose & vio)
- printk(BIOS_SPEW, "\texpect %08lx\n", id->data);
- /* we're looking for something. */
- if (lastidread->addr == id->addr){
- /* they're going to be polling.
- * just do it 1000 times
- */
- for(t = 0; t < 1000 && id->data != u; t++){
- u = READ32(id->addr);
- }
- if (verbose & vspin) printk(BIOS_SPEW,
- "%s: # loops %ld got %08lx want %08lx\n",
- regname(id->addr),
- t, u, id->data);
- }
- lastidread = id;
- break;
- case W:
- WRITE32(id->data, id->addr);
- if (id->addr == PCH_PP_CONTROL){
- if (verbose & vio)
- printk(BIOS_SPEW, "PCH_PP_CONTROL\n");
- switch(id->data & 0xf){
- case 8: break;
- case 7: break;
- default: udelay(100000);
- if (verbose & vio)
- printk(BIOS_SPEW, "U %d\n", 100000);
- }
- }
- break;
- case V:
- if (id->count < 8){
- prev = verbose;
- verbose = id->count;
- } else {
- verbose = prev;
- }
- printk(BIOS_SPEW, "Change verbosity to %d\n", verbose);
- break;
- case I:
- printk(BIOS_SPEW, "run: return %d\n", i+1);
- return i+1;
- break;
- default:
- printk(BIOS_SPEW, "BAD TABLE, opcode %d @ %d\n", id->op, i);
- return -1;
- }
- if (id->udelay)
- udelay(id->udelay);
- if (i < ARRAY_SIZE(times))
- times[i] = globalmicroseconds();
- }
- printk(BIOS_SPEW, "run: return %d\n", i);
- return i+1;
-}
-
-int i915lightup(unsigned int physbase, unsigned int iobase, unsigned int mmio,
+int i915lightup(unsigned int physbase,
+ unsigned int iobase,
+ unsigned int mmio,
unsigned int gfx);
int i915lightup(unsigned int pphysbase, unsigned int piobase,
unsigned int pmmio, unsigned int pgfx)
{
- static struct edid edid;
+ int must_cycle_power = 0;
+
+ /* frame buffer pointer */
+ u32 *l;
+ int i;
+ unsigned long before_gtt, after_gtt;
- int index;
- u32 auxin[16], auxout[16];
mmio = (void *)pmmio;
addrport = piobase;
dataport = addrport + 4;
@@ -278,128 +198,55 @@ int i915lightup(unsigned int pphysbase, unsigned int piobase,
(void *)graphics, mmio, addrport, physbase);
globalstart = rdtscll();
+ /* turn it on. The VBIOS does it this way, so we hope that's ok. */
+ verbose = 0;
+ io_i915_write32(0xabcd000f, PCH_PP_CONTROL);
- index = run(0);
- if (0){
- decode_edid((unsigned char *)&link_edid_data, sizeof(link_edid_data), &edid);
-
- htotal = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16);
- printk(BIOS_SPEW, "I915_WRITE(HTOTAL(pipe), %08x)\n", htotal);
-
- hblank = (edid.ha - 1) | ((edid.ha + edid.hbl- 1) << 16);
- printk(BIOS_SPEW, "I915_WRITE(HBLANK(pipe),0x%08x)\n", hblank);
-
- hsync = (edid.ha + edid.hso - 1) |
- ((edid.ha + edid.hso + edid.hspw- 1) << 16);
- printk(BIOS_SPEW, "I915_WRITE(HSYNC(pipe),0x%08x)\n", hsync);
-
- vtotal = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16);
- printk(BIOS_SPEW, "I915_WRITE(VTOTAL(pipe), %08x)\n", vtotal);
-
- vblank = (edid.va - 1) | ((edid.va + edid.vbl- 1) << 16);
- printk(BIOS_SPEW, "I915_WRITE(VBLANK(pipe),0x%08x)\n", vblank);
-
- vsync = (edid.va + edid.vso - 1) |((edid.va + edid.vso + edid.vspw- 1) << 16);
- printk(BIOS_SPEW, "I915_WRITE(VSYNC(pipe),0x%08x)\n", vsync);
-
- printk(BIOS_SPEW, "Table has %d elements\n", niodefs);
-
- index = run(0);
- printk(BIOS_SPEW, "Run returns %d\n", index);
- auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_DPCD_REV<<8|0xe;
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 14);
- auxout[0] = 0<<31 /* i2c */|1<<30|0x0<<28/*W*/|0x0<<8|0x0;
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0);
- index = run(index);
- printk(BIOS_SPEW, "Run returns %d\n", index);
- auxout[0] = 0<<31 /* i2c */|0<<30|0x0<<28/*W*/|0x0<<8|0x0;
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 3, auxin, 0);
- index = run(index);
- printk(BIOS_SPEW, "Run returns %d\n", index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_SET_POWER<<8|0x0;
- auxout[1] = 0x01000000;
- /* DP_SET_POWER_D0 | DP_PSR_SINK_INACTIVE |
- * (0x0<<13602104)|0x00000001*/ /* broken, fix. */
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_LINK_BW_SET<<8|0x8;
- auxout[1] = 0x0a840000;
- /*( DP_LINK_BW_2_7 &0xa)|0x0000840a*/
- auxout[2] = 0x00000000;
- auxout[3] = 0x01000000;
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 13, auxin, 0);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
- auxout[1] = 0x21000000;
- /* DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE |
- * DP_SYMBOL_ERROR_COUNT_BOTH |0x00000021*/
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3;
- auxout[1] = 0x00000000;
- /* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5;
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
- auxout[1] = 0x22000000;
- /* DP_TRAINING_PATTERN_2 | DP_LINK_SCRAMBLING_DISABLE |
- * DP_SYMBOL_ERROR_COUNT_BOTH |0x00000022*/
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_LANE0_SET<<8|0x3;
- auxout[1] = 0x00000000;
- /* DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0 |0x00000000*/
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 8, auxin, 0);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x1<<28/*R*/|DP_LANE0_1_STATUS<<8|0x5;
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 4, auxin, 5);
- index = run(index);
- auxout[0] = 1<<31 /* dp */|0x0<<28/*W*/|DP_TRAINING_PATTERN_SET<<8|0x0;
- auxout[1] = 0x00000000;
- /* DP_TRAINING_PATTERN_DISABLE | DP_LINK_QUAL_PATTERN_DISABLE |
- * DP_SYMBOL_ERROR_COUNT_BOTH |0x00000000*/
- intel_dp_aux_ch(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, auxout, 5, auxin, 0);
- index = run(index);
+ /* the AUX channel needs a small amount of time to spin up.
+ * Rather than udelay, do some useful work:
+ * Zero out the frame buffer memory,
+ * and set the global translation table (GTT)
+ */
+ printk(BIOS_SPEW, "Set not-White (%08x) for %d pixels\n", 0xffffff,
+ FRAME_BUFFER_BYTES/sizeof(u32));
+ for(l = (u32 *)graphics, i = 0;
+ i < FRAME_BUFFER_BYTES/sizeof(u32); i++){
+ l[i] = 0x1122ff;
}
+ printk(BIOS_SPEW, "GTT: set %d pages starting at %p\n",
+ FRAME_BUFFER_PAGES, (void *)physbase);
+ before_gtt = globalmicroseconds();
+ setgtt(0, FRAME_BUFFER_PAGES, physbase, 4096);
+ after_gtt = globalmicroseconds();
- if (index != niodefs)
- printk(BIOS_ERR, "Left over IO work in i915_lightup"
- " -- this is likely a table error. "
- "Only %d of %d were done.\n", index, niodefs);
- printk(BIOS_SPEW, "DONE startup\n");
- verbose = 0;
- /* GTT is the Global Translation Table for the graphics pipeline.
- * It is used to translate graphics addresses to physical
- * memory addresses. As in the CPU, GTTs map 4K pages.
- * There are 32 bits per pixel, or 4 bytes,
- * which means 1024 pixels per page.
- * There are 4250 GTTs on Link:
- * 2650 (X) * 1700 (Y) pixels / 1024 pixels per page.
- * The setgtt function adds a further bit of flexibility:
- * it allows you to set a range (the first two parameters) to point
- * to a physical address (third parameter);the physical address is
- * incremented by a count (fourth parameter) for each GTT in the
- * range.
- * Why do it this way? For ultrafast startup,
- * we can point all the GTT entries to point to one page,
- * and set that page to 0s:
- * memset(physbase, 0, 4096);
- * setgtt(0, 4250, physbase, 0);
- * this takes about 2 ms, and is a win because zeroing
- * the page takes a up to 200 ms. We will be exploiting this
- * trick in a later rev of this code.
- * This call sets the GTT to point to a linear range of pages
- * starting at physbase.
+ /* The reset is basically harmless, and can be
+ * repeated by the VBIOS in any event.
*/
- setgtt(0, FRAME_BUFFER_PAGES, physbase, 4096);
- printk(BIOS_SPEW, "memset %p to 0 for %d bytes\n",
- (void *)graphics, FRAME_BUFFER_BYTES);
- memset((void *)graphics, 0, FRAME_BUFFER_BYTES);
- printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds());
+
+ graphics_register_reset(DPA_AUX_CH_CTL, DPA_AUX_CH_DATA1, verbose);
+
+ /* failures after this point can return without
+ * powering off the panel.
+ */
+
+ if (1)
+ goto fail;
+ /* failures after this point MUST power off the panel
+ * and wait 600 ms.
+ */
+
i915_init_done = 1;
oprom_is_loaded = 1;
+ return 1;
+
+fail:
+ printk(BIOS_SPEW, "Graphics could not be started;");
+ if (must_cycle_power){
+ printk(BIOS_SPEW, "Turn off power and wait ...");
+ io_i915_write32(0xabcd0000, PCH_PP_CONTROL);
+ udelay(600000);
+ }
+ printk(BIOS_SPEW, "Returning.\n");
return 0;
+
}