#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#include "kdrive.h"
#include "kxv.h"
#include "klinux.h"
#include "i810.h"
#include "agp.h"
#include "i810draw.h"
#ifndef I810_DEBUG
int I810_DEBUG = (0
);
#endif
static Bool
i810ModeInit(KdScreenInfo *screen, const KdMonitorTiming *t);
static void
i810PrintMode( vgaRegPtr vgaReg, I810RegPtr mode );
Bool
i810CardInit (KdCardInfo *card)
{
int i;
I810CardInfo *i810c;
i810c = (I810CardInfo *) xalloc (sizeof (I810CardInfo));
if (!i810c)
return FALSE;
i810c->videoRam=2048;
if (card->attr.address[1] != 0) {
i810c->LinearAddr = card->attr.address[0] & 0xFF000000;
if (!i810c->LinearAddr) {
fprintf(stderr,"No valid FB address in PCI config space(1)\n");
xfree(i810c);
return FALSE;
} else {
}
} else {
fprintf(stderr,"No valid FB address in PCI config space(2)\n");
xfree(i810c);
return FALSE;
}
if (card->attr.address[1]) {
i810c->MMIOAddr = card->attr.address[1] & 0xFFF80000;
i810c->MMIOBase =
KdMapDevice (i810c->MMIOAddr, I810_REG_SIZE);
if (!i810c->MMIOBase) {
fprintf(stderr,"No valid MMIO address in PCI config space(1)\n");
xfree(i810c);
return FALSE;
} else {
}
} else {
fprintf(stderr,"No valid MMIO address in PCI config space(2)\n");
xfree(i810c);
return FALSE;
}
{
unsigned long *p;
if (!(p= (unsigned long *) LinuxGetPciCfg(&card->attr)))
return FALSE;
if ( (p[WHTCFG_PAMR_DRP] & LM_FREQ_MASK) == LM_FREQ_133 )
i810c->LmFreqSel = 133;
else
i810c->LmFreqSel = 100;
xfree(p);
}
i810c->FbMapSize = 32*1024*1024;
for (i = 2 ; i < i810c->FbMapSize ; i <<= 1);
i810c->FbMapSize = i;
i810c->FbBase =
KdMapDevice (i810c->LinearAddr, i810c->FbMapSize);
if (!i810c->FbBase) return FALSE;
card->driver=i810c;
return TRUE;
}
static void
i810ScreenFini (KdScreenInfo *screen)
{
I810ScreenInfo *i810s = (I810ScreenInfo *) screen->driver;
xfree (i810s);
screen->driver = 0;
}
static Bool
i810InitScreen (ScreenPtr pScreen) {
#ifdef XV
i810InitVideo(pScreen);
#endif
return TRUE;
}
static Bool
i810FinishInitScreen(ScreenPtr pScreen)
{
return TRUE;
}
static void
i810CardFini (KdCardInfo *card)
{
I810CardInfo *i810c = (I810CardInfo *) card->driver;
KdUnmapDevice (i810c->FbBase, i810c->FbMapSize);
KdUnmapDevice (i810c->MMIOBase, I810_REG_SIZE);
xfree (i810c);
card->driver = 0;
}
struct wm_info {
double freq;
unsigned int wm;
};
struct wm_info i810_wm_8_100[] = {
{ 0, 0x22003000 },
{ 25.2, 0x22003000 },
{ 28.0, 0x22003000 },
{ 31.5, 0x22003000 },
{ 36.0, 0x22007000 },
{ 40.0, 0x22007000 },
{ 45.0, 0x22007000 },
{ 49.5, 0x22008000 },
{ 50.0, 0x22008000 },
{ 56.3, 0x22008000 },
{ 65.0, 0x22008000 },
{ 75.0, 0x22008000 },
{ 78.8, 0x22008000 },
{ 80.0, 0x22008000 },
{ 94.0, 0x22008000 },
{ 96.0, 0x22107000 },
{ 99.0, 0x22107000 },
{ 108.0, 0x22107000 },
{ 121.0, 0x22107000 },
{ 128.9, 0x22107000 },
{ 132.0, 0x22109000 },
{ 135.0, 0x22109000 },
{ 157.5, 0x2210b000 },
{ 162.0, 0x2210b000 },
{ 175.5, 0x2210b000 },
{ 189.0, 0x2220e000 },
{ 202.5, 0x2220e000 }
};
struct wm_info i810_wm_16_100[] = {
{ 0, 0x22004000 },
{ 25.2, 0x22006000 },
{ 28.0, 0x22006000 },
{ 31.5, 0x22007000 },
{ 36.0, 0x22007000 },
{ 40.0, 0x22007000 },
{ 45.0, 0x22007000 },
{ 49.5, 0x22009000 },
{ 50.0, 0x22009000 },
{ 56.3, 0x22108000 },
{ 65.0, 0x2210e000 },
{ 75.0, 0x2210e000 },
{ 78.8, 0x2210e000 },
{ 80.0, 0x22210000 },
{ 94.5, 0x22210000 },
{ 96.0, 0x22210000 },
{ 99.0, 0x22210000 },
{ 108.0, 0x22210000 },
{ 121.0, 0x22210000 },
{ 128.9, 0x22210000 },
{ 132.0, 0x22314000 },
{ 135.0, 0x22314000 },
{ 157.5, 0x22415000 },
{ 162.0, 0x22416000 },
{ 175.5, 0x22416000 },
{ 189.0, 0x22416000 },
{ 195.0, 0x22416000 },
{ 202.5, 0x22416000 }
};
struct wm_info i810_wm_24_100[] = {
{ 0, 0x22006000 },
{ 25.2, 0x22009000 },
{ 28.0, 0x22009000 },
{ 31.5, 0x2200a000 },
{ 36.0, 0x2210c000 },
{ 40.0, 0x2210c000 },
{ 45.0, 0x2210c000 },
{ 49.5, 0x22111000 },
{ 50.0, 0x22111000 },
{ 56.3, 0x22111000 },
{ 65.0, 0x22214000 },
{ 75.0, 0x22214000 },
{ 78.8, 0x22215000 },
{ 80.0, 0x22216000 },
{ 94.5, 0x22218000 },
{ 96.0, 0x22418000 },
{ 99.0, 0x22418000 },
{ 108.0, 0x22418000 },
{ 121.0, 0x22418000 },
{ 128.9, 0x22419000 },
{ 132.0, 0x22519000 },
{ 135.0, 0x4441d000 },
{ 157.5, 0x44419000 },
{ 162.0, 0x44419000 },
{ 175.5, 0x44419000 },
{ 189.0, 0x44419000 },
{ 195.0, 0x44419000 },
{ 202.5, 0x44419000 }
};
struct wm_info i810_wm_32_100[] = {
{ 0, 0x2210b000 },
{ 60, 0x22415000 },
{ 80, 0x22419000 }
};
struct wm_info i810_wm_8_133[] = {
{ 0, 0x22003000 },
{ 25.2, 0x22003000 },
{ 28.0, 0x22003000 },
{ 31.5, 0x22003000 },
{ 36.0, 0x22007000 },
{ 40.0, 0x22007000 },
{ 45.0, 0x22007000 },
{ 49.5, 0x22008000 },
{ 50.0, 0x22008000 },
{ 56.3, 0x22008000 },
{ 65.0, 0x22008000 },
{ 75.0, 0x22008000 },
{ 78.8, 0x22008000 },
{ 80.0, 0x22008000 },
{ 94.0, 0x22008000 },
{ 96.0, 0x22107000 },
{ 99.0, 0x22107000 },
{ 108.0, 0x22107000 },
{ 121.0, 0x22107000 },
{ 128.9, 0x22107000 },
{ 132.0, 0x22109000 },
{ 135.0, 0x22109000 },
{ 157.5, 0x2210b000 },
{ 162.0, 0x2210b000 },
{ 175.5, 0x2210b000 },
{ 189.0, 0x2220e000 },
{ 202.5, 0x2220e000 }
};
struct wm_info i810_wm_16_133[] = {
{ 0, 0x22004000 },
{ 25.2, 0x22006000 },
{ 28.0, 0x22006000 },
{ 31.5, 0x22007000 },
{ 36.0, 0x22007000 },
{ 40.0, 0x22007000 },
{ 45.0, 0x22007000 },
{ 49.5, 0x22009000 },
{ 50.0, 0x22009000 },
{ 56.3, 0x22108000 },
{ 65.0, 0x2210e000 },
{ 75.0, 0x2210e000 },
{ 78.8, 0x2210e000 },
{ 80.0, 0x22210000 },
{ 94.5, 0x22210000 },
{ 96.0, 0x22210000 },
{ 99.0, 0x22210000 },
{ 108.0, 0x22210000 },
{ 121.0, 0x22210000 },
{ 128.9, 0x22210000 },
{ 132.0, 0x22314000 },
{ 135.0, 0x22314000 },
{ 157.5, 0x22415000 },
{ 162.0, 0x22416000 },
{ 175.5, 0x22416000 },
{ 189.0, 0x22416000 },
{ 195.0, 0x22416000 },
{ 202.5, 0x22416000 }
};
struct wm_info i810_wm_24_133[] = {
{ 0, 0x22006000 },
{ 25.2, 0x22009000 },
{ 28.0, 0x22009000 },
{ 31.5, 0x2200a000 },
{ 36.0, 0x2210c000 },
{ 40.0, 0x2210c000 },
{ 45.0, 0x2210c000 },
{ 49.5, 0x22111000 },
{ 50.0, 0x22111000 },
{ 56.3, 0x22111000 },
{ 65.0, 0x22214000 },
{ 75.0, 0x22214000 },
{ 78.8, 0x22215000 },
{ 80.0, 0x22216000 },
{ 94.5, 0x22218000 },
{ 96.0, 0x22418000 },
{ 99.0, 0x22418000 },
{ 108.0, 0x22418000 },
{ 121.0, 0x22418000 },
{ 128.9, 0x22419000 },
{ 132.0, 0x22519000 },
{ 135.0, 0x4441d000 },
{ 157.5, 0x44419000 },
{ 162.0, 0x44419000 },
{ 175.5, 0x44419000 },
{ 189.0, 0x44419000 },
{ 195.0, 0x44419000 },
{ 202.5, 0x44419000 }
};
static void
i810WriteControlMMIO(I810CardInfo *i810c, int addr, CARD8 index, CARD8 val) {
moutb(addr, index);
moutb(addr+1, val);
}
static CARD8
i810ReadControlMMIO(I810CardInfo *i810c, int addr, CARD8 index) {
moutb(addr, index);
return minb(addr+1);
}
static Bool
i810ModeSupported (KdScreenInfo *screen, const KdMonitorTiming *t)
{
if (t->horizontal > 1600 || t->horizontal < 640) return FALSE;
if (t->vertical > 1200 || t->horizontal < 350) return FALSE;
return TRUE;
}
static Bool
i810ModeUsable (KdScreenInfo *screen)
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = (I810CardInfo *) card->driver;
int byte_width, pixel_width, screen_size;
if (screen->fb[0].depth >= 24)
{
screen->fb[0].depth = 24;
screen->fb[0].bitsPerPixel = 24;
screen->dumb = TRUE;
}
else if (screen->fb[0].depth >= 16)
{
screen->fb[0].depth = 16;
screen->fb[0].bitsPerPixel = 16;
}
else if (screen->fb[0].depth >= 15)
{
screen->fb[0].depth = 15;
screen->fb[0].bitsPerPixel = 16;
}
else
{
screen->fb[0].depth = 8;
screen->fb[0].bitsPerPixel = 8;
}
byte_width = screen->width * (screen->fb[0].bitsPerPixel >> 3);
pixel_width = screen->width;
screen->fb[0].pixelStride = pixel_width;
screen->fb[0].byteStride = byte_width;
screen_size = byte_width * screen->height;
return screen_size <= (i810c->videoRam * 1024);
}
static int i810AllocateGARTMemory( KdScreenInfo *screen )
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = (I810CardInfo *) card->driver;
unsigned long size = i810c->videoRam * 1024;
int key;
long tom = 0;
unsigned long physical;
if (!KdAgpGARTSupported())
return FALSE;
if (!KdAcquireGART(screen->mynum))
return FALSE;
i810c->agpAcquired2d = TRUE;
if ((key = KdAllocateGARTMemory(screen->mynum, size, 0, NULL)) == -1)
return FALSE;
i810c->VramOffset = 0;
i810c->VramKey = key;
if (!KdBindGARTMemory(screen->mynum, key, 0))
return FALSE;
i810c->SysMem.Start = 0;
i810c->SysMem.Size = size;
i810c->SysMem.End = size;
i810c->SavedSysMem = i810c->SysMem;
tom = i810c->SysMem.End;
i810c->DcacheMem.Start = 0;
i810c->DcacheMem.End = 0;
i810c->DcacheMem.Size = 0;
i810c->CursorPhysical = 0;
size = 1024 * 4096;
tom += 0x7ffff;
tom &= ~0x7ffff;
if ((key = KdAllocateGARTMemory(screen->mynum, size, AGP_DCACHE_MEMORY, NULL)) != -1) {
i810c->DcacheOffset= tom;
i810c->DcacheKey = key;
if (!KdBindGARTMemory(screen->mynum, key, tom)) {
fprintf(stderr,"Allocation of %ld bytes for DCACHE failed\n", size);
i810c->DcacheKey = -1;
} else {
i810c->DcacheMem.Start = tom;
i810c->DcacheMem.Size = size;
i810c->DcacheMem.End = i810c->DcacheMem.Start + i810c->DcacheMem.Size;
tom = i810c->DcacheMem.End;
}
} else {
fprintf(stderr,
"No physical memory available for %ld bytes of DCACHE\n",
size);
i810c->DcacheKey = -1;
}
size = 4096;
if ((key = KdAllocateGARTMemory(screen->mynum, size, AGP_PHYS_MEMORY,
&physical)) == -1) {
fprintf(stderr,
"No physical memory available for HW cursor\n");
i810c->HwcursKey = -1;
} else {
i810c->HwcursOffset= tom;
i810c->HwcursKey = key;
if (!KdBindGARTMemory(screen->mynum, key, tom)) {
fprintf(stderr,
"Allocation of %ld bytes for HW cursor failed\n",
size);
i810c->HwcursKey = -1;
} else {
i810c->CursorPhysical = physical;
i810c->CursorStart = tom;
tom += size;
}
}
if (i810c->CursorStart != 0) {
i810c->OverlayPhysical = i810c->CursorPhysical + 1024;
i810c->OverlayStart = i810c->CursorStart + 1024;
}
i810c->GttBound = 1;
return TRUE;
}
static int i810AllocLow( I810MemRange *result, I810MemRange *pool, int size )
{
if (size > pool->Size) return FALSE;
pool->Size -= size;
result->Size = size;
result->Start = pool->Start;
result->End = pool->Start += size;
return TRUE;
}
static int i810AllocHigh( I810MemRange *result, I810MemRange *pool, int size )
{
if (size > pool->Size) return 0;
pool->Size -= size;
result->Size = size;
result->End = pool->End;
result->Start = pool->End -= size;
return 1;
}
static Bool
i810AllocateFront(KdScreenInfo *screen) {
KdCardInfo *card = screen->card;
I810CardInfo *i810c = (I810CardInfo *) card->driver;
int cache_lines = -1;
if(i810c->DoneFrontAlloc)
return TRUE;
memset(&(i810c->FbMemBox), 0, sizeof(BoxRec));
i810c->FbMemBox.x1=0;
i810c->FbMemBox.x2=screen->width;
i810c->FbMemBox.y1=0;
i810c->FbMemBox.y2=screen->height;
cache_lines = 0;
if(cache_lines >= 0)
i810c->FbMemBox.y2 += cache_lines;
else {
i810c->FbMemBox.y2 += (screen->fb[0].depth == 24) ? 256 : 384;
if (screen->width <= 1024)
i810c->FbMemBox.y2 += (screen->fb[0].depth == 24) ? 256 : 384;
cache_lines = i810c->FbMemBox.y2 - screen->height;
}
if (I810_DEBUG)
ErrorF("Adding %i scanlines for pixmap caching\n", cache_lines);
i810AllocLow( &(i810c->FrontBuffer),
&(i810c->SysMem),
((i810c->FbMemBox.x2 *
i810c->FbMemBox.y2 *
i810c->cpp) + 4095) & ~4095);
memset( &(i810c->LpRing), 0, sizeof( I810RingBuffer ) );
if(i810AllocLow( &(i810c->LpRing.mem), &(i810c->SysMem), 16*4096 )) {
if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
ErrorF( "ring buffer at local %lx\n",
i810c->LpRing.mem.Start);
i810c->LpRing.tail_mask = i810c->LpRing.mem.Size - 1;
i810c->LpRing.virtual_start = i810c->FbBase + i810c->LpRing.mem.Start;
i810c->LpRing.head = 0;
i810c->LpRing.tail = 0;
i810c->LpRing.space = 0;
}
if ( i810AllocLow( &i810c->Scratch, &(i810c->SysMem), 64*1024 ) ||
i810AllocLow( &i810c->Scratch, &(i810c->SysMem), 16*1024 ) ) {
if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
ErrorF("Allocated Scratch Memory\n");
}
#ifdef XV
if ( i810AllocHigh( &i810c->XvMem, &(i810c->SysMem), 720*720*2 )) {
if (I810_DEBUG & DEBUG_VERBOSE_MEMORY)
ErrorF("Allocated overlay Memory\n");
}
#endif
i810c->DoneFrontAlloc = TRUE;
return TRUE;
}
static Bool
i810MapMem(KdScreenInfo *screen)
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = (I810CardInfo *) card->driver;
i810c->LpRing.virtual_start = i810c->FbBase + i810c->LpRing.mem.Start;
return TRUE;
}
Bool
i810ScreenInit (KdScreenInfo *screen)
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = (I810CardInfo *) card->driver;
I810ScreenInfo *i810s;
int i;
const KdMonitorTiming *t;
i810s = (I810ScreenInfo *) xalloc (sizeof (I810ScreenInfo));
if (!i810s)
return FALSE;
memset (i810s, '\0', sizeof (I810ScreenInfo));
i810s->i810c = i810c;
if (!screen->width || !screen->height)
{
screen->width = 720;
screen->height = 576;
screen->rate = 52;
#if 0
screen->width = 1024;
screen->height = 768;
screen->rate = 72;
#endif
}
if (!screen->fb[0].depth)
screen->fb[0].depth = 16;
t = KdFindMode (screen, i810ModeSupported);
screen->rate = t->rate;
screen->width = t->horizontal;
screen->height = t->vertical;
if (!KdTuneMode (screen, i810ModeUsable, i810ModeSupported))
{
xfree (i810c);
return FALSE;
}
switch (screen->fb[0].depth) {
case 8:
screen->fb[0].visuals = ((1 << StaticGray) |
(1 << GrayScale) |
(1 << StaticColor) |
(1 << PseudoColor) |
(1 << TrueColor) |
(1 << DirectColor));
screen->fb[0].blueMask = 0x00;
screen->fb[0].greenMask = 0x00;
screen->fb[0].redMask = 0x00;
break;
case 15:
screen->fb[0].visuals = (1 << TrueColor);
screen->fb[0].blueMask = 0x001f;
screen->fb[0].greenMask = 0x03e0;
screen->fb[0].redMask = 0x7c00;
i810c->colorKey = 0x043f;
break;
case 16:
screen->fb[0].visuals = (1 << TrueColor);
screen->fb[0].blueMask = 0x001f;
screen->fb[0].greenMask = 0x07e0;
screen->fb[0].redMask = 0xf800;
i810c->colorKey = 0x083f;
break;
case 24:
screen->fb[0].visuals = (1 << TrueColor);
screen->fb[0].blueMask = 0x0000ff;
screen->fb[0].greenMask = 0x00ff00;
screen->fb[0].redMask = 0xff0000;
i810c->colorKey = 0x0101ff;
break;
default:
fprintf(stderr,"Unsupported depth %d\n",screen->fb[0].depth);
return FALSE;
}
for (i=0; i<768; i++) i810c->vga.ModeReg.DAC[i] = 0x00;
if (screen->fb[0].depth >= 4)
i810c->vga.ModeReg.Attribute[OVERSCAN] = 0xFF;
#ifdef I810CFG_SHOW_OVERSCAN
i810c->vga.ModeReg.DAC[765] = 0x3F;
i810c->vga.ModeReg.DAC[766] = 0x00;
i810c->vga.ModeReg.DAC[767] = 0x3F;
i810c->vga.ModeReg.Attribute[OVERSCAN] = 0xFF;
i810c->vga.ShowOverscan = TRUE;
#else
i810c->vga.ShowOverscan = FALSE;
#endif
i810c->vga.paletteEnabled = FALSE;
i810c->vga.cmapSaved = FALSE;
i810c->vga.MMIOBase = i810c->MMIOBase;
i810c->cpp = screen->fb[0].bitsPerPixel/8;
switch (screen->fb[0].bitsPerPixel) {
case 8:
i810c->MaxClock = 203000;
break;
case 16:
i810c->MaxClock = 163000;
break;
case 24:
i810c->MaxClock = 136000;
break;
case 32:
i810c->MaxClock = 86000;
default:
fprintf(stderr,"Unsupported bpp %d\n",screen->fb[0].bitsPerPixel);
return FALSE;
}
if (!i810AllocateGARTMemory( screen )) {
return FALSE;
}
i810AllocateFront(screen);
if (!i810MapMem(screen)) return FALSE;
screen->fb[0].frameBuffer = i810c->FbBase;
screen->driver = i810s;
return TRUE;
}
static void
DoSave(KdCardInfo *card, vgaRegPtr vgaReg, I810RegPtr i810Reg, Bool saveFonts)
{
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
int i;
vgaReg->MiscOutReg = mmioReadMiscOut(vgap);
if (vgaReg->MiscOutReg & 0x01)
vgap->IOBase = VGA_IOBASE_COLOR;
else
vgap->IOBase = VGA_IOBASE_MONO;
for (i = 0; i < VGA_NUM_CRTC; i++) {
vgaReg->CRTC[i] = mmioReadCrtc(vgap, i);
}
mmioEnablePalette(vgap);
for (i = 0; i < VGA_NUM_ATTR; i++) {
vgaReg->Attribute[i] = mmioReadAttr(vgap, i);
}
mmioDisablePalette(vgap);
for (i = 0; i < VGA_NUM_GFX; i++) {
vgaReg->Graphics[i] = mmioReadGr(vgap, i);
}
for (i = 1; i < VGA_NUM_SEQ; i++) {
vgaReg->Sequencer[i] = mmioReadSeq(vgap, i);
}
i810Reg->IOControl = mmioReadCrtc(vgap, IO_CTNL);
i810Reg->AddressMapping = i810ReadControlMMIO(i810c, GRX, ADDRESS_MAPPING);
i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
i810Reg->ExtVertTotal=mmioReadCrtc(vgap, EXT_VERT_TOTAL);
i810Reg->ExtVertDispEnd=mmioReadCrtc(vgap, EXT_VERT_DISPLAY);
i810Reg->ExtVertSyncStart=mmioReadCrtc(vgap, EXT_VERT_SYNC_START);
i810Reg->ExtVertBlankStart=mmioReadCrtc(vgap, EXT_VERT_BLANK_START);
i810Reg->ExtHorizTotal=mmioReadCrtc(vgap, EXT_HORIZ_TOTAL);
i810Reg->ExtHorizBlank=mmioReadCrtc(vgap, EXT_HORIZ_BLANK);
i810Reg->ExtOffset=mmioReadCrtc(vgap, EXT_OFFSET);
i810Reg->InterlaceControl=mmioReadCrtc(vgap, INTERLACE_CNTL);
i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
for (i = 0 ; i < 8 ; i++)
i810Reg->Fence[i] = INREG(FENCE+i*4);
i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
i810Reg->LprbStart = INREG(LP_RING + RING_START);
i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
i810Reg->LprbLen & RING_VALID) {
i810PrintErrorState( i810c );
FatalError( "Active ring not flushed\n");
}
if (I810_DEBUG) {
fprintf(stderr,"Got mode in I810Save:\n");
i810PrintMode( vgaReg, i810Reg );
}
}
static void
i810Preserve(KdCardInfo *card)
{
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
DoSave(card, &vgap->SavedReg, &i810c->SavedReg, TRUE);
}
void
i810PrintErrorState(i810CardInfo *i810c)
{
fprintf(stderr, "pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
INREG(PGETBL_CTL),
INREG(PGE_ERR));
fprintf(stderr, "ipeir: %lx iphdr: %lx\n",
INREG(IPEIR),
INREG(IPEHR));
fprintf(stderr, "LP ring tail: %lx head: %lx len: %lx start %lx\n",
INREG(LP_RING + RING_TAIL),
INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
INREG(LP_RING + RING_LEN),
INREG(LP_RING + RING_START));
fprintf(stderr, "eir: %x esr: %x emr: %x\n",
INREG16(EIR),
INREG16(ESR),
INREG16(EMR));
fprintf(stderr, "instdone: %x instpm: %x\n",
INREG16(INST_DONE),
INREG8(INST_PM));
fprintf(stderr, "memmode: %lx instps: %lx\n",
INREG(MEMMODE),
INREG(INST_PS));
fprintf(stderr, "hwstam: %x ier: %x imr: %x iir: %x\n",
INREG16(HWSTAM),
INREG16(IER),
INREG16(IMR),
INREG16(IIR));
}
static Bool
i810BindGARTMemory( KdScreenInfo *screen )
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
if (!i810c->GttBound) {
if (!KdAcquireGART(screen->mynum))
return FALSE;
if (!KdBindGARTMemory(screen->mynum, i810c->VramKey,
i810c->VramOffset))
return FALSE;
if (i810c->DcacheKey != -1) {
if (!KdBindGARTMemory(screen->mynum, i810c->DcacheKey,
i810c->DcacheOffset))
return FALSE;
}
if (i810c->HwcursKey != -1) {
if (!KdBindGARTMemory(screen->mynum, i810c->HwcursKey,
i810c->HwcursOffset))
return FALSE;
}
i810c->GttBound = 1;
}
return TRUE;
}
static Bool
i810UnbindGARTMemory(KdScreenInfo *screen)
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
if (KdAgpGARTSupported() && i810c->GttBound) {
if (!KdUnbindGARTMemory(screen->mynum, i810c->VramKey))
return FALSE;
if (i810c->DcacheKey != -1) {
if (!KdUnbindGARTMemory(screen->mynum, i810c->DcacheKey))
return FALSE;
}
if (i810c->HwcursKey != -1) {
if (!KdUnbindGARTMemory(screen->mynum, i810c->HwcursKey))
return FALSE;
}
if (!KdReleaseGART(screen->mynum))
return FALSE;
i810c->GttBound = 0;
}
return TRUE;
}
#define MAX_VCO_FREQ 600.0
#define TARGET_MAX_N 30
#define REF_FREQ 24.0
#define CALC_VCLK(m,n,p) \
(double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
static void
i810CalcVCLK( KdScreenInfo *screen, double freq )
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
I810RegPtr i810Reg = &i810c->ModeReg;
int m, n, p;
double f_out, f_best;
double f_err;
double f_vco;
int m_best = 0, n_best = 0, p_best = 0;
double f_target = freq;
double err_max = 0.005;
double err_target = 0.001;
double err_best = 999999.0;
p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2);
f_vco = f_target * (1 << p);
n = 2;
do {
n++;
m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
if (m < 3) m = 3;
f_out = CALC_VCLK(m,n,p);
f_err = 1.0 - (f_target/f_out);
if (fabs(f_err) < err_max) {
m_best = m;
n_best = n;
f_best = f_out;
err_best = f_err;
}
} while ((fabs(f_err) >= err_target) &&
((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
if (fabs(f_err) < err_target) {
m_best = m;
n_best = n;
}
i810Reg->VideoClk2_M = (m_best-2) & 0x3FF;
i810Reg->VideoClk2_N = (n_best-2) & 0x3FF;
i810Reg->VideoClk2_DivisorSel = (p_best << 4);
}
#define Elements(x) (sizeof(x)/sizeof(*x))
static unsigned int
i810CalcWatermark( KdScreenInfo *screen, double freq, Bool dcache )
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
struct wm_info *tab;
int nr;
int i;
if (i810c->LmFreqSel == 100) {
switch(screen->fb[0].bitsPerPixel) {
case 8:
tab = i810_wm_8_100;
nr = Elements(i810_wm_8_100);
break;
case 16:
tab = i810_wm_16_100;
nr = Elements(i810_wm_16_100);
break;
case 24:
tab = i810_wm_24_100;
nr = Elements(i810_wm_24_100);
break;
default:
return 0;
}
} else {
switch(screen->fb[0].bitsPerPixel) {
case 8:
tab = i810_wm_8_133;
nr = Elements(i810_wm_8_133);
break;
case 16:
tab = i810_wm_16_133;
nr = Elements(i810_wm_16_133);
break;
case 24:
tab = i810_wm_24_133;
nr = Elements(i810_wm_24_133);
break;
default:
return 0;
}
}
for (i = 0 ; i < nr && tab[i].freq < freq ; i++);
if (i == nr)
i--;
if (dcache)
return (tab[i].wm & ~0xffffff) | ((tab[i].wm>>12) & 0xfff);
else
return tab[i].wm;
}
static void i810PrintMode( vgaRegPtr vgaReg, I810RegPtr mode )
{
int i;
fprintf(stderr," MiscOut: %x\n", vgaReg->MiscOutReg);
fprintf(stderr,"SEQ: ");
for (i = 0 ; i < VGA_NUM_SEQ ; i++) {
if ((i&7)==0) fprintf(stderr,"\n");
fprintf(stderr," %d: %x", i, vgaReg->Sequencer[i]);
}
fprintf(stderr,"\n");
fprintf(stderr,"CRTC: ");
for (i = 0 ; i < VGA_NUM_CRTC ; i++) {
if ((i&3)==0) fprintf(stderr,"\n");
fprintf(stderr," CR%02x: %2x", i, vgaReg->CRTC[i]);
}
fprintf(stderr,"\n");
fprintf(stderr,"GFX: ");
for (i = 0 ; i < VGA_NUM_GFX ; i++) {
if ((i&3)==0) fprintf(stderr,"\n");
fprintf(stderr," GR%02x: %02x", i, vgaReg->Graphics[i]);
}
fprintf(stderr,"\n");
fprintf(stderr,"ATTR: ");
for (i = 0 ; i < VGA_NUM_ATTR ; i++) {
if ((i&7)==0) fprintf(stderr,"\n");
fprintf(stderr," %d: %x", i, vgaReg->Attribute[i]);
}
fprintf(stderr,"\n");
fprintf(stderr," DisplayControl: %x\n", mode->DisplayControl);
fprintf(stderr," PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
fprintf(stderr," PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
fprintf(stderr," PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
fprintf(stderr," VideoClk2_M: %x\n", mode->VideoClk2_M);
fprintf(stderr," VideoClk2_N: %x\n", mode->VideoClk2_N);
fprintf(stderr," VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
fprintf(stderr," AddressMapping: %x\n", mode->AddressMapping);
fprintf(stderr," IOControl: %x\n", mode->IOControl);
fprintf(stderr," BitBLTControl: %x\n", mode->BitBLTControl);
fprintf(stderr," ExtVertTotal: %x\n", mode->ExtVertTotal);
fprintf(stderr," ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
fprintf(stderr," ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
fprintf(stderr," ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
fprintf(stderr," ExtHorizTotal: %x\n", mode->ExtHorizTotal);
fprintf(stderr," ExtHorizBlank: %x\n", mode->ExtHorizBlank);
fprintf(stderr," ExtOffset: %x\n", mode->ExtOffset);
fprintf(stderr," InterlaceControl: %x\n", mode->InterlaceControl);
fprintf(stderr," LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
fprintf(stderr," LprbTail: %x\n", mode->LprbTail);
fprintf(stderr," LprbHead: %x\n", mode->LprbHead);
fprintf(stderr," LprbStart: %x\n", mode->LprbStart);
fprintf(stderr," LprbLen: %x\n", mode->LprbLen);
fprintf(stderr," OverlayActiveStart: %x\n", mode->OverlayActiveStart);
fprintf(stderr," OverlayActiveEnd: %x\n", mode->OverlayActiveEnd);
}
static void
i810VGASeqReset(i810VGAPtr vgap, Bool start)
{
if (start)
{
mmioWriteSeq(vgap, 0x00, 0x01);
}
else
{
mmioWriteSeq(vgap, 0x00, 0x03);
}
}
static void
i810VGAProtect(KdCardInfo *card, Bool on)
{
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
unsigned char tmp;
if (on) {
tmp = mmioReadSeq(vgap, 0x01);
i810VGASeqReset(vgap, TRUE);
mmioWriteSeq(vgap, 0x01, tmp | 0x20);
mmioEnablePalette(vgap);
} else {
tmp = mmioReadSeq(vgap, 0x01);
mmioWriteSeq(vgap, 0x01, tmp & ~0x20);
i810VGASeqReset(vgap, FALSE);
mmioDisablePalette(vgap);
}
}
void
i810VGABlankScreen(KdCardInfo *card, Bool on)
{
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
unsigned char scrn;
scrn = mmioReadSeq(vgap, 0x01);
if (on) {
scrn &= ~0x20;
} else {
scrn |= 0x20;
}
mmioWriteSeq(vgap,0x00,0x01);
mmioWriteSeq(vgap, 0x01, scrn);
mmioWriteSeq(vgap,0x00,0x03);
}
static void
DoRestore(KdCardInfo *card, vgaRegPtr vgaReg, I810RegPtr i810Reg,
Bool restoreFonts) {
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
unsigned char temp;
unsigned int itemp;
int i;
if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
fprintf(stderr,"Setting mode in DoRestore:\n");
i810PrintMode( vgaReg, i810Reg );
}
i810VGAProtect(card, TRUE);
usleep(50000);
temp = INREG8( DRAM_ROW_CNTL_HI );
temp &= ~DRAM_REFRESH_RATE;
temp |= DRAM_REFRESH_DISABLE;
OUTREG8( DRAM_ROW_CNTL_HI, temp );
usleep(1000);
OUTREG16( VCLK2_VCO_M, i810Reg->VideoClk2_M);
OUTREG16( VCLK2_VCO_N, i810Reg->VideoClk2_N);
OUTREG8( VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel);
temp = INREG8(PIXPIPE_CONFIG_0);
temp &= 0x7F;
temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
OUTREG8( PIXPIPE_CONFIG_0, temp );
if (vgaReg->MiscOutReg & 0x01)
vgap->IOBase = VGA_IOBASE_COLOR;
else
vgap->IOBase = VGA_IOBASE_MONO;
mmioWriteMiscOut(vgap, vgaReg->MiscOutReg);
for (i = 1; i < VGA_NUM_SEQ; i++)
mmioWriteSeq(vgap, i, vgaReg->Sequencer[i]);
mmioWriteCrtc(vgap, 17, vgaReg->CRTC[17] & ~0x80);
for (i = 0; i < VGA_NUM_CRTC; i++) {
mmioWriteCrtc(vgap, i, vgaReg->CRTC[i]);
}
for (i = 0; i < VGA_NUM_GFX; i++)
mmioWriteGr(vgap, i, vgaReg->Graphics[i]);
mmioEnablePalette(vgap);
for (i = 0; i < VGA_NUM_ATTR; i++)
mmioWriteAttr(vgap, i, vgaReg->Attribute[i]);
mmioDisablePalette(vgap);
mmioWriteCrtc(vgap, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
mmioWriteCrtc(vgap, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
mmioWriteCrtc(vgap, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
mmioWriteCrtc(vgap, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
mmioWriteCrtc(vgap, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
mmioWriteCrtc(vgap, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
mmioWriteCrtc(vgap, EXT_START_ADDR_HI, 0);
mmioWriteCrtc(vgap, EXT_START_ADDR, EXT_START_ADDR_ENABLE);
mmioWriteCrtc(vgap, EXT_OFFSET, i810Reg->ExtOffset);
mmioWriteCrtc(vgap, 0x13, vgaReg->CRTC[0x13]);
temp=mmioReadCrtc(vgap, INTERLACE_CNTL);
temp &= ~INTERLACE_ENABLE;
temp |= i810Reg->InterlaceControl;
mmioWriteCrtc(vgap, INTERLACE_CNTL, temp);
temp=i810ReadControlMMIO(i810c, GRX, ADDRESS_MAPPING);
temp &= 0xE0;
temp |= i810Reg->AddressMapping;
i810WriteControlMMIO(i810c, GRX, ADDRESS_MAPPING, temp);
OUTREG(0x6001C, (i810Reg->OverlayActiveEnd << 16) | i810Reg->OverlayActiveStart);
temp = INREG8( DRAM_ROW_CNTL_HI );
temp &= ~DRAM_REFRESH_RATE;
temp |= DRAM_REFRESH_60HZ;
OUTREG8( DRAM_ROW_CNTL_HI, temp );
temp = INREG8( BITBLT_CNTL );
temp &= ~COLEXP_MODE;
temp |= i810Reg->BitBLTControl;
OUTREG8( BITBLT_CNTL, temp );
temp = INREG8( DISPLAY_CNTL );
temp &= ~(VGA_WRAP_MODE | GUI_MODE);
temp |= i810Reg->DisplayControl;
OUTREG8( DISPLAY_CNTL, temp );
temp = INREG8( PIXPIPE_CONFIG_0 );
temp &= 0x64;
temp |= i810Reg->PixelPipeCfg0;
OUTREG8( PIXPIPE_CONFIG_0, temp );
temp = INREG8( PIXPIPE_CONFIG_2 );
temp &= 0xF3;
temp |= i810Reg->PixelPipeCfg2;
OUTREG8( PIXPIPE_CONFIG_2, temp );
temp = INREG8( PIXPIPE_CONFIG_1 );
temp &= ~DISPLAY_COLOR_MODE;
temp &= 0xEF;
temp |= i810Reg->PixelPipeCfg1;
OUTREG8( PIXPIPE_CONFIG_1, temp );
OUTREG16(EIR, 0);
itemp = INREG(FWATER_BLC);
itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
MM_BURST_LENGTH | MM_FIFO_WATERMARK );
itemp |= i810Reg->LMI_FIFO_Watermark;
OUTREG(FWATER_BLC, itemp);
for (i = 0 ; i < 8 ; i++) {
OUTREG( FENCE+i*4, i810Reg->Fence[i] );
if (I810_DEBUG & DEBUG_VERBOSE_VGA)
fprintf(stderr,"Fence Register : %x\n", i810Reg->Fence[i]);
}
itemp = INREG(LP_RING + RING_LEN);
itemp &= ~RING_VALID_MASK;
OUTREG(LP_RING + RING_LEN, itemp );
OUTREG(LP_RING + RING_TAIL, 0 );
OUTREG(LP_RING + RING_HEAD, 0 );
i810c->LpRing.head = 0;
i810c->LpRing.tail = 0;
itemp = INREG(LP_RING + RING_START);
itemp &= ~(START_ADDR);
itemp |= i810Reg->LprbStart;
OUTREG(LP_RING + RING_START, itemp );
itemp = INREG(LP_RING + RING_LEN);
itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
itemp |= i810Reg->LprbLen;
OUTREG(LP_RING + RING_LEN, itemp );
i810VGAProtect(card, FALSE);
temp=mmioReadCrtc(vgap, IO_CTNL);
temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
temp |= i810Reg->IOControl;
mmioWriteCrtc(vgap, IO_CTNL, temp);
mmioWriteCrtc(vgap, 0x11, mmioReadCrtc(vgap, 0x11) | 0x80);
}
static Bool
i810SetMode(KdScreenInfo *screen, const KdMonitorTiming *t)
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
I810RegPtr i810Reg = &i810c->ModeReg;
vgaRegPtr pVga = &vgap->ModeReg;
double dclk = t->clock/1000.0;
switch (screen->fb[0].bitsPerPixel) {
case 8:
pVga->CRTC[0x13] = screen->width >> 3;
i810Reg->ExtOffset = screen->width >> 11;
i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
i810Reg->BitBLTControl = COLEXP_8BPP;
break;
case 16:
i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
pVga->CRTC[0x13] = screen->width >> 2;
i810Reg->ExtOffset = screen->width >> 10;
i810Reg->BitBLTControl = COLEXP_16BPP;
break;
case 24:
pVga->CRTC[0x13] = (screen->width * 3) >> 3;
i810Reg->ExtOffset = (screen->width * 3) >> 11;
i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
i810Reg->BitBLTControl = COLEXP_24BPP;
break;
default:
break;
}
i810Reg->PixelPipeCfg0 = DAC_8_BIT;
i810Reg->PixelPipeCfg1 |= 0x10;
i810Reg->IOControl = EXTENDED_CRTC_CNTL;
i810Reg->AddressMapping = (LINEAR_MODE_ENABLE |
GTT_MEM_MAP_ENABLE);
i810Reg->DisplayControl = HIRES_MODE;
i810Reg->OverlayActiveStart = t->horizontal + t->hblank - 32;
i810Reg->OverlayActiveEnd = t->horizontal - 32;
i810Reg->InterlaceControl = INTERLACE_DISABLE;
pVga->Attribute[0x11] = 0;
i810CalcVCLK(screen, dclk);
pVga->MiscOutReg |= 0x0C;
i810Reg->LMI_FIFO_Watermark = i810CalcWatermark(screen, dclk, FALSE);
i810Reg->LprbTail = 0;
i810Reg->LprbHead = 0;
i810Reg->LprbStart = i810c->LpRing.mem.Start;
if (i810Reg->LprbStart)
i810Reg->LprbLen = ((i810c->LpRing.mem.Size-4096) |
RING_NO_REPORT | RING_VALID);
else
i810Reg->LprbLen = RING_INVALID;
return TRUE;
}
static Bool
i810ModeInit(KdScreenInfo *screen, const KdMonitorTiming *t)
{
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
vgaRegPtr pVga;
i810VGAUnlock(vgap);
if (!i810VGAInit(screen, t)) return FALSE;
pVga = &vgap->ModeReg;
if (!i810SetMode(screen, t)) return FALSE;
DoRestore(screen->card, &vgap->ModeReg, &i810c->ModeReg, FALSE);
return TRUE;
}
Bool
i810VGAInit(KdScreenInfo *screen, const KdMonitorTiming *t)
{
unsigned int i;
int hactive, hblank, hbp, hfp;
int vactive, vblank, vbp, vfp;
int h_screen_off = 0, h_adjust = 0, h_total, h_display_end, h_blank_start;
int h_blank_end, h_sync_start, h_sync_end, v_total, v_retrace_start;
int v_retrace_end, v_display_end, v_blank_start, v_blank_end;
KdCardInfo *card = screen->card;
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
I810RegPtr ireg = &i810c->ModeReg;
vgaRegPtr regp;
int depth = screen->fb[0].depth;
regp = &vgap->ModeReg;
regp->MiscOutReg = 0x23;
if (t->vpol == KdSyncNegative) regp->MiscOutReg |= 0x40;
if (t->hpol == KdSyncNegative) regp->MiscOutReg |= 0x80;
if (depth == 4)
regp->Sequencer[0] = 0x02;
else
regp->Sequencer[0] = 0x00;
regp->Sequencer[1] = 0x01;
if (depth == 1)
regp->Sequencer[2] = 1 << BIT_PLANE;
else
regp->Sequencer[2] = 0x0F;
regp->Sequencer[3] = 0x00;
if (depth < 8)
regp->Sequencer[4] = 0x06;
else
regp->Sequencer[4] = 0x0E;
hactive = t->horizontal;
hblank = t->hblank;
hbp = t->hbp;
hfp = t->hfp;
vactive = t->vertical;
vblank = t->vblank;
vbp = t->vbp;
vfp = t->vfp;
switch (screen->fb[0].bitsPerPixel) {
case 8:
hactive /= 8;
hblank /= 8;
hfp /= 8;
hbp /= 8;
h_screen_off = hactive;
h_adjust = 1;
break;
case 16:
hactive /= 8;
hblank /= 8;
hfp /= 8;
hbp /= 8;
h_screen_off = hactive * 2;
h_adjust = 1;
break;
case 24:
hactive /= 8;
hblank /= 8;
hfp /= 8;
hbp /= 8;
h_screen_off = hactive * 3;
h_adjust = 1;
break;
case 32:
hactive /= 8;
hblank /= 8;
hfp /= 8;
hbp /= 8;
h_screen_off = hactive * 4;
h_adjust = 1;
break;
}
h_total = hactive + hblank - 5;
h_display_end = hactive - 1;
h_blank_start = h_display_end;
h_blank_end = h_blank_start + hblank;
h_sync_start = hactive + hfp + h_adjust;
h_sync_end = h_sync_start + hblank - hbp - hfp;
regp->CRTC[0x0] = h_total;
ireg->ExtHorizTotal=(h_total & 0x100) >> 8;
regp->CRTC[0x1] = h_display_end;
regp->CRTC[0x2] = h_blank_start;
regp->CRTC[0x3] = 0x80 | (h_blank_end & 0x1f);
regp->CRTC[0x5] = (h_blank_end & 0x20) << 2;
regp->CRTC[0x4] = h_sync_start;
regp->CRTC[0x5] |= h_sync_end & 0x1f;
regp->CRTC[0x13] = h_screen_off;
ireg->ExtOffset = h_screen_off >> 8;
v_total = vactive + vblank - 2;
v_retrace_start = vactive + vfp - 1;
v_retrace_end = v_retrace_start + vblank - vbp - vfp;
v_display_end = vactive - 1;
v_blank_start = vactive - 1;
v_blank_end = v_blank_start + vblank ;
regp->CRTC[0x6] = v_total;
ireg->ExtVertTotal = v_total >> 8;
regp->CRTC[0x10] = v_retrace_start;
ireg->ExtVertSyncStart = v_retrace_start >> 8;
regp->CRTC[0x11] = v_retrace_end;
regp->CRTC[0x12] = v_display_end;
ireg->ExtVertDispEnd = v_display_end >> 8;
regp->CRTC[0x15] = v_blank_start;
ireg->ExtVertBlankStart = v_blank_start >> 8;
regp->CRTC[0x16] = v_blank_end;
if (depth < 8)
regp->CRTC[23] = 0xE3;
else
regp->CRTC[23] = 0xC3;
regp->CRTC[24] = 0xFF;
regp->Graphics[0] = 0x00;
regp->Graphics[1] = 0x00;
regp->Graphics[2] = 0x00;
regp->Graphics[3] = 0x00;
if (depth == 1) {
regp->Graphics[4] = BIT_PLANE;
regp->Graphics[5] = 0x00;
} else {
regp->Graphics[4] = 0x00;
if (depth == 4)
regp->Graphics[5] = 0x02;
else
regp->Graphics[5] = 0x40;
}
regp->Graphics[6] = 0x05;
regp->Graphics[7] = 0x0F;
regp->Graphics[8] = 0xFF;
if (depth == 1) {
Bool flipPixels = FALSE;
for (i=0; i<16; i++)
if (((i & (1 << BIT_PLANE)) != 0) != flipPixels)
regp->Attribute[i] = WHITE_VALUE;
else
regp->Attribute[i] = BLACK_VALUE;
regp->Attribute[16] = 0x01;
if (!vgap->ShowOverscan)
regp->Attribute[OVERSCAN] = OVERSCAN_VALUE;
} else {
regp->Attribute[0] = 0x00;
regp->Attribute[1] = 0x01;
regp->Attribute[2] = 0x02;
regp->Attribute[3] = 0x03;
regp->Attribute[4] = 0x04;
regp->Attribute[5] = 0x05;
regp->Attribute[6] = 0x06;
regp->Attribute[7] = 0x07;
regp->Attribute[8] = 0x08;
regp->Attribute[9] = 0x09;
regp->Attribute[10] = 0x0A;
regp->Attribute[11] = 0x0B;
regp->Attribute[12] = 0x0C;
regp->Attribute[13] = 0x0D;
regp->Attribute[14] = 0x0E;
regp->Attribute[15] = 0x0F;
if (depth == 4)
regp->Attribute[16] = 0x81;
else
regp->Attribute[16] = 0x41;
}
regp->Attribute[18] = 0x0F;
regp->Attribute[19] = 0x00;
regp->Attribute[20] = 0x00;
return(TRUE);
}
void
i810VGALock(i810VGAPtr vgap)
{
mmioWriteCrtc(vgap, 0x11, mmioReadCrtc(vgap, 0x11) & ~0x80);
}
void
i810VGAUnlock(i810VGAPtr vgap)
{
mmioWriteCrtc(vgap, 0x11, mmioReadCrtc(vgap, 0x11) | 0x80);
}
static void
i810Restore(KdCardInfo *card) {
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
if (I810_DEBUG)
fprintf(stderr,"i810Restore\n");
DoRestore(card, &vgap->SavedReg, &i810c->SavedReg, TRUE);
}
static Bool
i810Enable (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
KdCardInfo *card = pScreenPriv->card;
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
const KdMonitorTiming *t;
if (I810_DEBUG)
fprintf(stderr,"i810Enable\n");
vgap->IOBase = (mmioReadMiscOut(vgap) & 0x01) ?
VGA_IOBASE_COLOR : VGA_IOBASE_MONO;
{
I810RegPtr i810Reg = &i810c->ModeReg;
int i;
for (i = 0 ; i < 8 ; i++)
i810Reg->Fence[i] = 0;
}
t = KdFindMode (screen, i810ModeSupported);
if (!i810BindGARTMemory(screen))
return FALSE;
if (!i810ModeInit(screen, t)) return FALSE;
{
unsigned char SEQ01=0;
int DPMSSyncSelect=0;
SEQ01 = 0x00;
DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
SEQ01 |= i810ReadControlMMIO(i810c, SRX, 0x01) & ~0x20;
i810WriteControlMMIO(i810c, SRX, 0x01, SEQ01);
OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
}
#ifdef XV
KdXVEnable (pScreen);
#endif
return TRUE;
}
static void
i810Disable(ScreenPtr pScreen) {
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
KdCardInfo *card = pScreenPriv->card;
I810CardInfo *i810c = card->driver;
i810VGAPtr vgap = &i810c->vga;
if (I810_DEBUG)
fprintf(stderr,"i810Disable\n");
#ifdef XV
KdXVDisable (pScreen);
#endif
i810Restore(screen->card);
if (!i810UnbindGARTMemory(screen))
return;
i810VGALock(vgap);
}
static Bool
i810DPMS(ScreenPtr pScreen, int mode)
{
KdScreenPriv(pScreen);
KdCardInfo *card = pScreenPriv->card;
I810CardInfo *i810c = card->driver;
unsigned char SEQ01=0;
int DPMSSyncSelect=0;
if (I810_DEBUG)
fprintf(stderr,"i810DPMS: %d\n",mode);
switch (mode) {
case KD_DPMS_NORMAL:
SEQ01 = 0x00;
DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
break;
case KD_DPMS_STANDBY:
SEQ01 = 0x20;
DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
break;
case KD_DPMS_SUSPEND:
SEQ01 = 0x20;
DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
break;
case KD_DPMS_POWERDOWN:
SEQ01 = 0x20;
DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
break;
}
SEQ01 |= i810ReadControlMMIO(i810c, SRX, 0x01) & ~0x20;
i810WriteControlMMIO(i810c, SRX, 0x01, SEQ01);
OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
return TRUE;
}
static void
i810GetColors (ScreenPtr pScreen, int fb, int ndefs, xColorItem *c)
{
if (I810_DEBUG)
fprintf(stderr,"i810GetColors (NOT IMPLEMENTED)\n");
}
#define DACDelay(hw) \
do { \
unsigned char temp = Vminb((hw)->IOBase + VGA_IN_STAT_1_OFFSET); \
temp = Vminb((hw)->IOBase + VGA_IN_STAT_1_OFFSET); \
} while (0)
static void
i810PutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
KdCardInfo *card = screen->card;
I810CardInfo *i810c = (I810CardInfo *) card->driver;
i810VGAPtr vgap = &i810c->vga;
if (I810_DEBUG)
fprintf(stderr,"i810PutColors\n");
while (ndef--)
{
mmioWriteDacWriteAddr(vgap, pdefs->pixel);
DACDelay(vgap);
mmioWriteDacData(vgap, pdefs->red);
DACDelay(vgap);
mmioWriteDacData(vgap, pdefs->green);
DACDelay(vgap);
mmioWriteDacData(vgap, pdefs->blue);
DACDelay(vgap);
pdefs++;
}
}
KdCardFuncs i810Funcs = {
i810CardInit,
i810ScreenInit,
i810InitScreen,
i810FinishInitScreen,
NULL,
i810Preserve,
i810Enable,
i810DPMS,
i810Disable,
i810Restore,
i810ScreenFini,
i810CardFini,
i810CursorInit,
i810CursorEnable,
i810CursorDisable,
i810CursorFini,
NULL,
i810InitAccel,
i810EnableAccel,
i810DisableAccel,
i810FiniAccel,
i810GetColors,
i810PutColors,
};