blob: cb828e1da3f3c1fe71a479b28a1d0ea526a29965 [file] [log] [blame]
/*
* This file is part of i915tool
*
* Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "video.h"
int verbose = 1;
static unsigned short addrport, dataport;
struct drm_device *i915;
unsigned short vendor=0x8086, device=0x0116;
struct pci_dev fake = {.vendor_id=0x8086, .device_id = 0x0116};
int dofake = 0;
u8 *bios_image = NULL;
u8 *mmiobase;
u32 mmiophys;
int mmiosize;
size_t bios_image_size;
/* temporary */
unsigned int i915_lvds_downclock = 0;
int i915_vbt_sdvo_panel_type = -1;
/* */
/* not sure how we want to do this so let's guess */
/* to make it easy, we start at zero and assume 250 hz. */
unsigned long msecs(void)
{
struct timeval start, now;
static int first = 0;
unsigned long j;
if (! first++)
gettimeofday(&start, NULL);
gettimeofday(&now, NULL);
j = (now.tv_sec - start.tv_sec)*1000 + (now.tv_usec-start.tv_usec)/1000;
return j;
}
void
mdelay(unsigned long ms)
{
unsigned long start;
start = msecs();
while (msecs() < (start + ms))
;
}
void
hexdump(u8 *base, int size)
{
int i, j;
for(i = 0; i < size/sizeof(u32); i += 8) {
printf("%#x: ", i);
for(j = 0; j < 8; j++)
printf("%08x", base[i+j]);
printf("\n");
}
}
void udelay(int i)
{
printf("UDELAY!\n");
}
unsigned long io_I915_READ(unsigned long addr)
{
unsigned long val;
if (dofake)
return 0xcafebabe;
outl(addr, addrport);
val = inl(dataport);
if (verbose)
fprintf(stderr, "%s: %x <- %x\n", __func__, val, addr);
return val;
}
void io_I915_WRITE(unsigned long addr, unsigned long val)
{
if (dofake)
return;
outl(addr, addrport);
outl(val, dataport);
if (verbose)
fprintf(stderr, "%s: %x -> %x\n", __func__, val, addr);
}
unsigned long I915_READ(unsigned long addr)
{
volatile u32 *ptr = (u32 *)(mmiobase + addr);
unsigned long val;
if (dofake)
return 0xcafebabe;
val = *ptr;
if (verbose)
fprintf(stderr, "%s: %x <- %x\n", __func__, val, addr);
return val;
}
void I915_WRITE(unsigned long addr, unsigned long val)
{
volatile u32 *ptr = (u32 *)(mmiobase + addr);
if (dofake)
return;
*ptr = val;
if (verbose)
fprintf(stderr, "%s: %x -> %x\n", __func__, val, addr);
}
u16 I915_READ16(unsigned long addr)
{
volatile u16 *ptr = (u16 *)(mmiobase + addr);
unsigned long val;
if (dofake)
return 0xbabe;
val = *ptr;
if (verbose)
fprintf(stderr, "%s: %x <- %x\n", __func__, val, addr);
return val;
}
void I915_WRITE16(unsigned long addr, u16 val)
{
volatile u16 *ptr = (u16 *)(mmiobase + addr);
if (dofake)
return;
*ptr = val;
if (verbose)
fprintf(stderr, "%s: %x -> %x\n", __func__, val, addr);
}
#define GTT_RETRY 1000
static int gtt_poll(u32 reg, u32 mask, u32 value)
{
unsigned try = GTT_RETRY;
u32 data;
while (try--) {
data = I915_READ(reg);
if ((data & mask) == value){
printf("succeeds after %d tries\n", GTT_RETRY-try);
return 1;
}
udelay(10);
}
fprintf(stderr, "GT init timeout\n");
return 0;
}
void *pci_map_rom(struct pci_dev *dev, size_t *size)
{
*size = bios_image_size;
return bios_image;
}
void *pci_unmap_rom(struct pci_dev *dev, void *bios)
{
return NULL;
}
void *dmi_check_system(unsigned long ignore)
{
return NULL;
}
void
mapit(void)
{
int kfd;
kfd = open("/dev/mem", O_RDWR);
if (kfd < 0)
errx(1, "/dev/kmem");
mmiobase = mmap(NULL, mmiosize, PROT_WRITE|PROT_READ, MAP_SHARED, kfd,
mmiophys);
if ((void *)-1 == mmiobase)
errx(1, "mmap");
}
void
devinit()
{
u32 val;
/* force wake. */
I915_WRITE(0xa18c, 1);
gtt_poll(0x130090, 1, 1);
}
int main(int argc, char *argv[])
{
struct pci_dev *pci_dev_find(struct drm_device *dev);
for(argc--, argv++; argc; argc--, argv++) {
if (argv[0][0] != '-')
break;
if (!strcmp(argv[0], "-f"))
dofake++;
}
i915 = calloc(1, sizeof(*i915));
i915->dev_private = calloc(1, sizeof(*i915->dev_private));
/* until we do a bit more w/ coccinelle */
i915->dev_private->dev = i915;
if (dofake) {
i915->pdev = &fake;
if (! find_idlist(i915, vendor, device))
errx(1, "can't find fake device in pciidlist");
} else {
if (! pci_dev_find(i915))
errx(1, "No VGA device of any kind found\n");
}
if (argc) {
FILE *fd;
int amt;
/* size it later */
bios_image = malloc(8*1048576);
fd = fopen(argv[0], "r");
amt = fread(bios_image, 65536, 128, fd);
if (amt < 1) {
free(bios_image);
} else {
i915->bios_bin = bios_image;
i915->dev_private->opregion.vbt = bios_image;
bios_image_size = amt * 65536;
fclose(fd);
}
}
/* get the base address for the mmio indirection registers -- BAR 2 */
addrport = i915->pdev->base_addr[4] & ~3;
dataport = addrport + 4;
printf("Addrport is at %x, dataport at %x\n", addrport, dataport);
/* get the base of the mmio space */
mmiophys = i915->pdev->base_addr[0] & ~0xf;
mmiosize = i915->pdev->size[0];
printf("phys base is %#x, size %d\n", mmiophys, mmiosize);
mapit();
devinit();
//hexdump(mmiobase, mmiosize);
/* we should use ioperm but hey ... it's had troubles */
iopl(3);
intel_setup_bios(i915);
if (i915->bios_bin)
intel_parse_bios(i915);
}