int i915lightup(unsigned int pphysbase, unsigned int piobase, unsigned int pmmio, unsigned int pgfx) { int i, prev = 0; struct iodef *id, *lastidread = 0; unsigned long u, t; static unsigned long times[4096]; mmio = (void *)pmmio; addrport = piobase; dataport = addrport + 4; physbase = pphysbase; graphics = pgfx; printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p" "addrport %04x physbase %08x\n", (void *)graphics, mmio, addrport, physbase); globalstart = rdtscll(); /* state machine! */ for(i = 0, id = iodefs; i < ARRAY_SIZE(iodefs); i++, id++){ switch(id->op){ case M: if (verbose & vmsg) printk(BIOS_SPEW, "%ld: %s\n", globalmicroseconds(), id->msg); break; case R: u = READ32(id->addr); if (verbose & vio)printk(BIOS_SPEW, "%s: Got %08lx, expect %08lx\n", regname(id->addr), u, 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: if (verbose & vio)printk(BIOS_SPEW, "%s: outl %08lx\n", regname(id->addr), id->data); WRITE32(id->data, id->addr); if (id->addr == PCH_PP_CONTROL){ switch(id->data & 0xf){ case 8: break; case 7: break; default: udelay(100000); } } break; case V: if (id->count < 8){ prev = verbose; verbose = id->count; } else { verbose = prev; } break; case I: break; default: printk(BIOS_SPEW, "BAD TABLE, opcode %d @ %d\n", id->op, i); return -1; } if (id->udelay) udelay(id->udelay); times[i] = globalmicroseconds(); } /* optional, we don't even want to take timestamp overhead * if we can avoid it. */ if (0) for(i = 0, id = iodefs; i < ARRAY_SIZE(iodefs); i++, id++){ switch(id->op){ case R: printk(BIOS_SPEW, "%ld: R %08lx\n", times[i], id->addr); break; case W: printk(BIOS_SPEW, "%ld: W %08lx %08lx\n", times[i], id->addr, id->data); break; } } setgtt(0, 4520, physbase, 4096); printk(BIOS_SPEW, "memset %p to 0 for %d bytes\n", (void *)graphics, 4520*4096); memset((void *)graphics, 0, 4520*4096); printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds()); i915_init_done = 1; oprom_is_loaded = 1; return 0; }
int i915lightup(unsigned int pphysbase, unsigned int piobase, unsigned int pmmio, unsigned int pgfx) { static struct edid edid; int index; unsigned long temp; mmio = (void *)pmmio; addrport = piobase; dataport = addrport + 4; physbase = pphysbase; graphics = pgfx; printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p addrport %04x physbase %08x\n", (void *)graphics, mmio, addrport, physbase); globalstart = rdtscll(); decode_edid((unsigned char *)&x60_edid_data, sizeof(x60_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); 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. */ if (gtt_setup(pmmio)) { printk(BIOS_ERR, "ERROR: GTT Setup Failed!!!\n"); return 0; } setgtt(0, 800 , physbase, 4096); temp = READ32(PGETLB_CTL); printk(BIOS_INFO, "GTT PGETLB_CTL register: 0x%lx\n", temp); if (temp & 1) printk(BIOS_INFO, "GTT Enabled\n"); else printk(BIOS_ERR, "ERROR: GTT is still Disabled!!!\n"); printk(BIOS_SPEW, "memset %p to 0x00 for %d bytes\n", (void *)graphics, FRAME_BUFFER_BYTES); memset((void *)graphics, 0x00, FRAME_BUFFER_BYTES); printk(BIOS_SPEW, "%ld microseconds\n", globalmicroseconds()); i915_init_done = 1; return 0; }
int i915lightup(unsigned int pphysbase, unsigned int piobase, unsigned int pmmio, unsigned int pgfx) { int must_cycle_power = 0; /* frame buffer pointer */ u32 *l; int i; unsigned long before_gtt, after_gtt; mmio = (void *)pmmio; addrport = piobase; dataport = addrport + 4; physbase = pphysbase; graphics = pgfx; printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p" "addrport %04x physbase %08x\n", (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); /* 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(); /* The reset is basically harmless, and can be * repeated by the VBIOS in any event. */ 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; }
int i915lightup(unsigned int pphysbase, unsigned int piobase, unsigned int pmmio, unsigned int pgfx) { static struct edid edid; int index; u32 auxin[16], auxout[16]; mmio = (void *)pmmio; addrport = piobase; dataport = addrport + 4; physbase = pphysbase; graphics = pgfx; printk(BIOS_SPEW, "i915lightup: graphics %p mmio %p" "addrport %04x physbase %08x\n", (void *)graphics, mmio, addrport, physbase); globalstart = rdtscll(); 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 */ 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); 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. */ 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()); i915_init_done = 1; oprom_is_loaded = 1; return 0; }