#include #include #include #include #include #include #include #include #if defined(CONFIG_PCI_OPTION_ROM_RUN_YABEL)&&CONFIG_PCI_OPTION_ROM_RUN_YABEL #include #endif #include #include #include #include #include #include "hda_verb.h" #include "onboard.h" #include "ec.h" #include #include #include #include #include #include #include #include #include #include #include "i915_reg.h" enum { vmsg = 1, vio = 2, vspin = 4, }; static int verbose = 0; //vmsg ; static unsigned int *mmio; static unsigned int graphics; static unsigned short addrport; static unsigned short dataport; static unsigned int physbase; extern int oprom_is_loaded; #define READ32(addr) io_i915_READ32(addr) #define WRITE32(val, addr) io_i915_WRITE32(val, addr) static unsigned long io_i915_READ32(unsigned long addr) { unsigned long val; outl(addr, addrport); val = inl(dataport); return val; } static void io_i915_WRITE32(unsigned long val, unsigned long addr) { outl(addr, addrport); outl(val, dataport); } /* 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) { int i; for(i = start; i < end; i++){ u32 word = base + i*inc; WRITE32(word|1,(i*4)|1); } } static char *regname(unsigned long addr) { static char name[16]; sprintf(name, "0x%lx", addr); return name; } static unsigned long tickspermicrosecond = 1795; static unsigned long long globalstart; static unsigned long microseconds(unsigned long long start, unsigned long long end) { unsigned long ret; ret = ((end - start)/tickspermicrosecond); return ret; } static unsigned long globalmicroseconds(void) { return microseconds(globalstart, rdtscll()); } /* One-letter commands for code not mean to be ready for humans. * The code was generated by a set of programs/scripts. * M print out a kernel message * R read a register. We do these mainly to ensure that if hardware wanted * the register read, it was read; also, in debug, we can see what was expected * and what was found. This has proven *very* useful to get this debugged. * The udelay, if non-zero, will make sure there is a * udelay() call with the value. * The count is from the kernel and tells us how many times this read was done. * Also useful for debugging and the state * machine uses the info to drive a poll. * W Write a register * V set verbosity. It's a bit mask. * 0 -> nothing * 1 -> print kernel messages * 2 -> print IO ops * 4 -> print the number of times we spin on a register in a poll * 8 -> restore whatever the previous verbosity level was * (only one deep stack) * * Again, this is not really meant for human consumption. There is not a poll * operator as such because, sometimes, there is a read/write/read where the * second read is a poll, and this chipset is so touchy I'm reluctant to move * things around and/or delete too many reads. */ #define M 1 #define R 2 #define W 3 #define V 4 #define I 8 struct iodef { unsigned char op; unsigned int count; const char *msg; unsigned long addr; unsigned long data; unsigned long udelay; } iodefs[] = { #include "i915io.c" }; static int i915_init_done = 0; 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); framebuffer->physical_address = graphics; framebuffer->x_resolution = 2560; framebuffer->y_resolution = 1700; framebuffer->bytes_per_line = 10240; framebuffer->bits_per_pixel = 32; framebuffer->red_mask_pos = 16; framebuffer->red_mask_size = 8; framebuffer->green_mask_pos = 8; framebuffer->green_mask_size = 8; framebuffer->blue_mask_pos = 0; framebuffer->blue_mask_size = 8; framebuffer->reserved_mask_pos = 0; framebuffer->reserved_mask_size = 0; } 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) { 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; }