#ifndef PRINT_MODE_INFO
#define PRINT_MODE_INFO 0
#endif
#include "xf86.h"
#include "xf86_ansic.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86RAC.h"
#include "xf86cmap.h"
#include "compiler.h"
#include "mibstore.h"
#include "vgaHW.h"
#include "mipointer.h"
#include "micmap.h"
#include "fb.h"
#include "regionstr.h"
#include "xf86xv.h"
#include "Xv.h"
#include "vbe.h"
#include "vbeModes.h"
#include "i830.h"
#ifdef XF86DRI
#include "dri.h"
#endif
#define BIT(x) (1 << (x))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define NB_OF(x) (sizeof (x) / sizeof (*x))
static SymTabRec I830BIOSChipsets[] = {
{PCI_CHIP_I830_M, "i830"},
{PCI_CHIP_845_G, "845G"},
{PCI_CHIP_I855_GM, "852GM/855GM"},
{PCI_CHIP_I865_G, "865G"},
{-1, NULL}
};
static PciChipsets I830BIOSPciChipsets[] = {
{PCI_CHIP_I830_M, PCI_CHIP_I830_M, RES_SHARED_VGA},
{PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA},
{PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA},
{PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA},
{-1, -1, RES_UNDEFINED}
};
typedef enum {
OPTION_NOACCEL,
OPTION_SW_CURSOR,
OPTION_CACHE_LINES,
OPTION_DRI,
OPTION_PAGEFLIP,
OPTION_XVIDEO,
OPTION_VIDEO_KEY,
OPTION_COLOR_KEY,
OPTION_VBE_RESTORE,
OPTION_DISPLAY_INFO
} I830Opts;
static OptionInfoRec I830BIOSOptions[] = {
{OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE},
{OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE},
{OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, TRUE},
{OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE},
{OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE},
{OPTION_VBE_RESTORE, "VBERestore", OPTV_BOOLEAN, {0}, FALSE},
{OPTION_DISPLAY_INFO,"DisplayInfo", OPTV_BOOLEAN, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE}
};
static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn,
int PowerManagementMode, int flags);
static void I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags);
static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen);
static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack);
static Bool I830BIOSEnterVT(int scrnIndex, int flags);
static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode,
VbeCRTCInfoBlock *block);
#ifdef I830DEBUG
void
I830DPRINTF_stub(const char *filename, int line, const char *function,
const char *fmt, ...)
{
va_list ap;
ErrorF("\n##############################################\n"
"*** In function %s, on line %d, in file %s ***\n",
function, line, filename);
va_start(ap, fmt);
VErrorF(fmt, ap);
va_end(ap);
ErrorF("##############################################\n\n");
}
#else
void
I830DPRINTF_stub(const char *filename, int line, const char *function,
const char *fmt, ...)
{
}
#endif
const OptionInfoRec *
I830BIOSAvailableOptions(int chipid, int busid)
{
int i;
for (i = 0; I830BIOSPciChipsets[i].PCIid > 0; i++) {
if (chipid == I830BIOSPciChipsets[i].PCIid)
return I830BIOSOptions;
}
return NULL;
}
static Bool
I830BIOSGetRec(ScrnInfoPtr pScrn)
{
I830Ptr pI830;
if (pScrn->driverPrivate)
return TRUE;
pI830 = pScrn->driverPrivate = xnfcalloc(sizeof(I830Rec), 1);
pI830->vesa = xnfcalloc(sizeof(VESARec), 1);
return TRUE;
}
static void
I830BIOSFreeRec(ScrnInfoPtr pScrn)
{
I830Ptr pI830;
VESAPtr pVesa;
DisplayModePtr mode;
if (!pScrn)
return;
if (!pScrn->driverPrivate)
return;
pI830 = I830PTR(pScrn);
mode = pScrn->modes;
if (mode) {
do {
if (mode->Private) {
VbeModeInfoData *data = (VbeModeInfoData *) mode->Private;
if (data->block)
xfree(data->block);
xfree(data);
mode->Private = NULL;
}
mode = mode->next;
} while (mode && mode != pScrn->modes);
}
if (pI830->vbeInfo)
VBEFreeVBEInfo(pI830->vbeInfo);
if (pI830->pVbe)
vbeFree(pI830->pVbe);
pVesa = pI830->vesa;
if (pVesa->monitor)
xfree(pVesa->monitor);
if (pVesa->savedPal)
xfree(pVesa->savedPal);
xfree(pVesa);
xfree(pScrn->driverPrivate);
pScrn->driverPrivate = NULL;
}
static void
I830BIOSProbeDDC(ScrnInfoPtr pScrn, int index)
{
vbeInfoPtr pVbe;
pVbe = VBEInit(NULL, index);
ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
}
static const int refreshes[] = {
43, 56, 60, 70, 72, 75, 85, 100, 120
};
static const int nrefreshes = sizeof(refreshes) / sizeof(refreshes[0]);
static Bool
Check5fStatus(ScrnInfoPtr pScrn, int func, int ax)
{
if (ax == 0x005f)
return TRUE;
else if (ax == 0x015f) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Extended BIOS function 0x%04x failed.\n", func);
return FALSE;
} else if ((ax & 0xff) != 0x5f) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Extended BIOS function 0x%04x not supported.\n", func);
return FALSE;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Extended BIOS function 0x%04x returns 0x%04x.\n",
func, ax & 0xffff);
return FALSE;
}
}
#if 0
static int
BitToRefresh(int bits)
{
int i;
for (i = 0; i < nrefreshes; i++)
if (bits & (1 << i))
return refreshes[i];
return 0;
}
static int
GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "GetRefreshRate\n");
if (mode & 0x100)
return 0;
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f05;
pVbe->pInt10->bx = (mode & 0xff) | 0x100;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax)) {
if (availRefresh)
*availRefresh = pVbe->pInt10->bx;
return BitToRefresh(pVbe->pInt10->cx);
} else
return 0;
}
#endif
static int
SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh)
{
int i;
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "SetRefreshRate: mode 0x%x, refresh: %d\n", mode, refresh);
if (mode & 0x100)
return 0;
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f05;
pVbe->pInt10->bx = mode & 0xff;
for (i = nrefreshes - 1; i >= 0; i--) {
if (refreshes[i] <= (refresh + 2))
break;
}
if (i == 0) {
if (refresh >= refreshes[nrefreshes - 1])
i = nrefreshes - 1;
}
DPRINTF(PFX, "Setting refresh rate to %dHz for mode 0x%02x\n",
refreshes[i], mode & 0xff);
pVbe->pInt10->cx = 1 << i;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f05, pVbe->pInt10->ax))
return refreshes[i];
else
return 0;
}
static Bool
GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
int devicesPipeA, int devicesPipeB, int *maxBandwidth,
int *bandwidthPipeA, int *bandwidthPipeB)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "GetModeSupport: modes 0x%x, 0x%x, devices: 0x%x, 0x%x\n",
modePipeA, modePipeB, devicesPipeA, devicesPipeB);
if ((modePipeA & 0x100) || (modePipeB & 0x100))
return 0;
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f28;
pVbe->pInt10->bx = (modePipeA & 0xff) | ((modePipeB & 0xff) << 8);
if ((devicesPipeA & 0x80) || (devicesPipeB & 0x80))
pVbe->pInt10->cx = 0x8000;
else
pVbe->pInt10->cx = (devicesPipeA & 0xff) | ((devicesPipeB & 0xff) << 8);
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f28, pVbe->pInt10->ax)) {
if (maxBandwidth)
*maxBandwidth = pVbe->pInt10->cx;
if (bandwidthPipeA)
*bandwidthPipeA = pVbe->pInt10->dx & 0xffff;
if (bandwidthPipeB)
*bandwidthPipeB = (pVbe->pInt10->dx >> 16) & 0xffff;
return TRUE;
} else
return FALSE;
}
static int
GetLFPCompMode(ScrnInfoPtr pScrn)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "GetLFPCompMode\n");
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f61;
pVbe->pInt10->bx = 0x100;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax))
return pVbe->pInt10->cx & 0xffff;
else
return -1;
}
#if 0
static Bool
SetLFPCompMode(ScrnInfoPtr pScrn, int compMode)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "SetLFPCompMode: compMode %d\n", compMode);
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f61;
pVbe->pInt10->bx = 0;
pVbe->pInt10->cx = compMode;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
return Check5fStatus(pScrn, 0x5f61, pVbe->pInt10->ax);
}
#endif
static int
GetDisplayDevices(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
DPRINTF(PFX, "GetDisplayDevices\n");
#if 0
{
CARD32 temp;
ErrorF("ADPA is 0x%08x\n", INREG(ADPA));
ErrorF("DVOA is 0x%08x\n", INREG(DVOA));
ErrorF("DVOB is 0x%08x\n", INREG(DVOB));
ErrorF("DVOC is 0x%08x\n", INREG(DVOC));
ErrorF("LVDS is 0x%08x\n", INREG(LVDS));
temp = INREG(DVOA_SRCDIM);
ErrorF("DVOA_SRCDIM is 0x%08x (%d x %d)\n", temp,
(temp >> 12) & 0xfff, temp & 0xfff);
temp = INREG(DVOB_SRCDIM);
ErrorF("DVOB_SRCDIM is 0x%08x (%d x %d)\n", temp,
(temp >> 12) & 0xfff, temp & 0xfff);
temp = INREG(DVOC_SRCDIM);
ErrorF("DVOC_SRCDIM is 0x%08x (%d x %d)\n", temp,
(temp >> 12) & 0xfff, temp & 0xfff);
ErrorF("SWF0 is 0x%08x\n", INREG(SWF0));
ErrorF("SWF4 is 0x%08x\n", INREG(SWF4));
}
#endif
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f64;
pVbe->pInt10->bx = 0x100;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
return pVbe->pInt10->cx & 0xffff;
else
return -1;
}
static Bool
SetDisplayDevices(ScrnInfoPtr pScrn, int devices)
{
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
CARD32 temp;
DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices);
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f64;
pVbe->pInt10->bx = 0x1;
pVbe->pInt10->cx = devices;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
return TRUE;
else {
ErrorF("Writing config directly to SWF0\n");
temp = INREG(SWF0);
OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff));
ErrorF("SetDisplayDevices failed. devices is 0x%x instead of 0x%x\n",
GetDisplayDevices(pScrn), devices);
return FALSE;
}
}
#if 0
static Bool
GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached,
int *encoderPresent)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "GetDevicePresence\n");
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f64;
pVbe->pInt10->bx = 0x200;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
if (required)
*required = ((pVbe->pInt10->bx & 0x1) == 0);
if (attached)
*attached = (pVbe->pInt10->cx >> 8) & 0xff;
if (encoderPresent)
*encoderPresent = pVbe->pInt10->cx & 0xff;
return TRUE;
} else
return FALSE;
}
#endif
static Bool
GetDisplayInfo(ScrnInfoPtr pScrn, int device, Bool *attached, Bool *present,
short *x, short *y)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "GetDisplayInfo: device: 0x%x\n", device);
switch (device & 0xff) {
case 0x01:
case 0x02:
case 0x04:
case 0x08:
case 0x10:
case 0x20:
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"GetDisplayInfo: invalid device: 0x%x\n", device & 0xff);
return FALSE;
}
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f64;
pVbe->pInt10->bx = 0x300;
pVbe->pInt10->cx = device & 0xff;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) {
if (attached)
*attached = ((pVbe->pInt10->bx & 0x2) != 0);
if (present)
*present = ((pVbe->pInt10->bx & 0x1) != 0);
if (pVbe->pInt10->cx != (device & 0xff)) {
if (y) {
*y = pVbe->pInt10->cx & 0xffff;
}
if (x) {
*x = (pVbe->pInt10->cx >> 16) & 0xffff;
}
}
return TRUE;
} else
return FALSE;
}
static const char *displayDevices[] = {
"CRT",
"TV",
"DFP (digital flat panel)",
"LFP (local flat panel)",
"TV2 (second TV)",
"DFP2 (second digital flat panel)",
NULL
};
static const char *
DeviceToString(int device)
{
static int savedDevice = -1;
static int bit = 0;
const char *name;
if (device == -1) {
device = savedDevice;
bit = 0;
}
if (device == -1)
return NULL;
while (displayDevices[bit]) {
if (device & (1 << bit)) {
name = displayDevices[bit];
savedDevice = device & ~(1 << bit);
bit++;
return name;
}
bit++;
}
return NULL;
}
static void
PrintDisplayDeviceInfo(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int pipe, n;
int displays;
DPRINTF(PFX, "PrintDisplayDeviceInfo\n");
displays = pI830->configuredDevices;
if (displays == -1) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"No active display devices.\n");
return;
}
for (n = 0; n < pI830->availablePipes; n++) {
pipe = ((displays >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
if (pipe) {
const char *name;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Currently active displays on Pipe %c:\n", PIPE_NAME(n));
name = DeviceToString(pipe);
do {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\t%s\n", name);
name = DeviceToString(-1);
} while (name);
if (pipe & PIPE_UNKNOWN_ACTIVE)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"\tSome unknown display devices may also be present\n");
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"No active displays on Pipe %c.\n", PIPE_NAME(n));
}
if (pI830->pipeDisplaySize[n].x2 != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Lowest common panel size for pipe %c is %d x %d\n",
PIPE_NAME(n), pI830->pipeDisplaySize[n].x2,
pI830->pipeDisplaySize[n].y2);
} else if (pI830->pipeEnabled[n] && pipe & ~PIPE_CRT_ACTIVE) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"No display size information available for pipe %c.\n",
PIPE_NAME(n));
}
}
}
static void
GetPipeSizes(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int pipe, n;
DisplayType i;
DPRINTF(PFX, "GetPipeSizes\n");
for (n = 0; n < pI830->availablePipes; n++) {
pipe = (pI830->configuredDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK;
pI830->pipeDisplaySize[n].x1 = pI830->pipeDisplaySize[n].y1 = 0;
pI830->pipeDisplaySize[n].x2 = pI830->pipeDisplaySize[n].y2 = 4096;
for (i = 0; i < NumKnownDisplayTypes; i++) {
if (pipe & (1 << i) & PIPE_SIZED_DISP_MASK) {
if (pI830->displaySize[i].x2 != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Size of device %s is %d x %d\n",
displayDevices[i],
pI830->displaySize[i].x2,
pI830->displaySize[i].y2);
if (pI830->displaySize[i].x2 < pI830->pipeDisplaySize[n].x2)
pI830->pipeDisplaySize[n].x2 = pI830->displaySize[i].x2;
if (pI830->displaySize[i].y2 < pI830->pipeDisplaySize[n].y2)
pI830->pipeDisplaySize[n].y2 = pI830->displaySize[i].y2;
}
}
}
if (pI830->pipeDisplaySize[n].x2 == 4096)
pI830->pipeDisplaySize[n].x2 = 0;
if (pI830->pipeDisplaySize[n].y2 == 4096)
pI830->pipeDisplaySize[n].y2 = 0;
}
}
static Bool
I830DetectDisplayDevice(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int pipe, n;
DisplayType i;
if (pI830->displayInfo) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Broken BIOSes cause the system to hang here.\n"
"\t If you encounter this problem please add \n"
"\t\t Option \"DisplayInfo\" \"FALSE\"\n"
"\t to the Device section of your XF86Config file.\n");
for (i = 0; i < NumKnownDisplayTypes; i++) {
if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i],
&pI830->displayPresent[i],
&pI830->displaySize[i].x2,
&pI830->displaySize[i].y2)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Display Info: %s: attached: %s, present: %s, size: "
"(%d,%d)\n", displayDevices[i],
BOOLTOSTRING(pI830->displayAttached[i]),
BOOLTOSTRING(pI830->displayPresent[i]),
pI830->displaySize[i].x2, pI830->displaySize[i].y2);
}
}
}
pI830->configuredDevices = GetDisplayDevices(pScrn);
if (pI830->configuredDevices == -1) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Failed to detect active display devices\n");
return FALSE;
}
for (n = 0; n < pI830->availablePipes; n++) {
pipe = ((pI830->configuredDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK);
if (pipe) {
pI830->pipeEnabled[n] = TRUE;
}
}
GetPipeSizes(pScrn);
PrintDisplayDeviceInfo(pScrn);
#if 0
enabledDevices = PIPE_CRT_ACTIVE;
if (!SetDisplayDevices(pScrn, enabledDevices)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Failed to switch to configured display devices\n");
}
#endif
return TRUE;
}
static int
I830DetectMemory(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
PCITAG bridge;
CARD16 gmch_ctrl;
int memsize = 0;
bridge = pciTag(0, 0, 0);
gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
if (IS_I85X(pI830) || IS_I865G(pI830))
{
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M:
memsize = MB(1) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_4M:
memsize = MB(4) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_8M:
memsize = MB(8) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_16M:
memsize = MB(16) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_32M:
memsize = MB(32) - KB(132);
break;
}
} else
{
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
case I830_GMCH_GMS_STOLEN_512:
memsize = KB(512) - KB(132);
break;
case I830_GMCH_GMS_STOLEN_1024:
memsize = MB(1) - KB(132);
break;
case I830_GMCH_GMS_STOLEN_8192:
memsize = MB(8) - KB(132);
break;
case I830_GMCH_GMS_LOCAL:
memsize = 0;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Local memory found, but won't be used.\n");
break;
}
}
if (memsize > 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"detected %d kB stolen memory.\n", memsize / 1024);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "no video memory detected.\n");
}
return memsize;
}
static Bool
I830MapMMIO(ScrnInfoPtr pScrn)
{
int mmioFlags;
I830Ptr pI830 = I830PTR(pScrn);
#if !defined(__alpha__)
mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
#else
mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
#endif
pI830->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
pI830->PciTag,
pI830->MMIOAddr, I810_REG_SIZE);
if (!pI830->MMIOBase)
return FALSE;
return TRUE;
}
static Bool
I830MapMem(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
unsigned i;
for (i = 2; i < pI830->FbMapSize; i <<= 1) ;
pI830->FbMapSize = i;
if (!I830MapMMIO(pScrn))
return FALSE;
pI830->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
pI830->PciTag,
pI830->LinearAddr, pI830->FbMapSize);
if (!pI830->FbBase)
return FALSE;
pI830->LpRing.virtual_start = pI830->FbBase + pI830->LpRing.mem.Start;
return TRUE;
}
static void
I830UnmapMMIO(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->MMIOBase,
I810_REG_SIZE);
pI830->MMIOBase = 0;
}
static Bool
I830UnmapMem(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pI830->FbBase,
pI830->FbMapSize);
pI830->FbBase = 0;
I830UnmapMMIO(pScrn);
return TRUE;
}
#ifndef HAVE_GET_PUT_BIOSMEMSIZE
#define HAVE_GET_PUT_BIOSMEMSIZE 1
#endif
#if HAVE_GET_PUT_BIOSMEMSIZE
static Bool
PutBIOSMemSize(ScrnInfoPtr pScrn, int memSize)
{
vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
DPRINTF(PFX, "PutBIOSMemSize: %d kB\n", memSize / 1024);
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x5f11;
pVbe->pInt10->bx = 0;
pVbe->pInt10->cx = memSize / GTT_PAGE_SIZE;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
return Check5fStatus(pScrn, 0x5f11, pVbe->pInt10->ax);
}
static int
GetBIOSMemSize(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int memSize = KB(pI830->vbeInfo->TotalMemory * 64);
DPRINTF(PFX, "GetBIOSMemSize\n");
if (PutBIOSMemSize(pScrn, memSize))
return memSize;
else
return -1;
}
#endif
static Bool
SaveBIOSMemSize(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "SaveBIOSMemSize\n");
pI830->useSWF1 = FALSE;
#if HAVE_GET_PUT_BIOSMEMSIZE
if ((pI830->saveBIOSMemSize = GetBIOSMemSize(pScrn)) != -1)
return TRUE;
#endif
if (IS_I830(pI830) || IS_845G(pI830)) {
pI830->useSWF1 = TRUE;
pI830->saveSWF1 = INREG(SWF1) & 0x0f;
switch (pI830->saveSWF1) {
case 0:
pI830->saveBIOSMemSize = KB(320);
break;
case 1:
pI830->saveBIOSMemSize = KB(832);
break;
case 8:
pI830->saveBIOSMemSize = KB(8000);
break;
default:
pI830->saveBIOSMemSize = 0;
break;
}
return TRUE;
}
return FALSE;
}
static CARD32
TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit)
{
#define SIZE 0x10000
#define IDOFFSET (-23)
const char *MAGICstring = "Total time for VGA POST:";
const int len = strlen(MAGICstring);
I830Ptr pI830 = I830PTR(pScrn);
char *position;
char *biosAddr;
CARD32 oldsize;
CARD32 oldpermission;
CARD32 ret = 0;
int i,j = 0;
PCITAG tag =pciTag(0,0,0);
if(!pI830->PciInfo
|| !(pI830->PciInfo->chipType == PCI_CHIP_I855_GM
|| pI830->PciInfo->chipType == PCI_CHIP_I865_G))
return 0;
if (!pI830->pVbe)
return 0;
biosAddr = xf86int10Addr(pI830->pVbe->pInt10,
pI830->pVbe->pInt10->BIOSseg << 4);
if (!pI830->BIOSMemSizeLoc) {
if (!preinit)
return 0;
for (i = 0; i < SIZE; i++) {
if (biosAddr[i] == MAGICstring[j]) {
if (++j == len)
break;
} else {
i -= j;
j = 0;
}
}
if (j < len) return 0;
pI830->BIOSMemSizeLoc = (i - j + 1 + IDOFFSET);
}
position = biosAddr + pI830->BIOSMemSizeLoc;
oldsize = *(CARD32 *)position;
ret = oldsize - (3 << 16);
if (preinit && ((oldsize) >> 16) - 3 != pI830->vbeInfo->TotalMemory)
return 0;
oldpermission = pciReadLong(tag, DRAM_RW_CONTROL);
pciWriteLong(tag, DRAM_RW_CONTROL, 0x33330000);
*(CARD32 *)position = newsize + (3 << 16);
if (preinit) {
VBEFreeVBEInfo(pI830->vbeInfo);
vbeFree(pI830->pVbe);
pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
if (pI830->vbeInfo->TotalMemory * 64 * 1024 != pI830->newBIOSMemSize) {
ret = 0;
*(CARD32 *)position = oldsize;
} else {
pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Tweak BIOS image to %d kB VideoRAM\n",
(int)(pI830->BIOSMemorySize / 1024));
}
}
pciWriteLong(tag, DRAM_RW_CONTROL, oldpermission);
return ret;
}
static void
RestoreBIOSMemSize(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 swf1;
DPRINTF(PFX, "RestoreBIOSMemSize\n");
if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE))
return;
if (!pI830->overrideBIOSMemSize)
return;
#if HAVE_GET_PUT_BIOSMEMSIZE
if (!pI830->useSWF1) {
PutBIOSMemSize(pScrn, pI830->saveBIOSMemSize);
return;
}
#endif
if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
swf1 = INREG(SWF1);
swf1 &= ~0x0f;
swf1 |= (pI830->saveSWF1 & 0x0f);
OUTREG(SWF1, swf1);
}
}
static void
SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize)
{
I830Ptr pI830 = I830PTR(pScrn);
unsigned long swf1;
Bool mapped;
DPRINTF(PFX, "SetBIOSMemSize: %d kB\n", newSize / 1024);
if (!pI830->overrideBIOSMemSize)
return;
#if HAVE_GET_PUT_BIOSMEMSIZE
if (!pI830->useSWF1) {
PutBIOSMemSize(pScrn, newSize);
return;
}
#endif
if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) {
unsigned long newSWF1;
mapped = (pI830->MMIOBase != NULL);
if (!mapped)
I830MapMMIO(pScrn);
if (newSize <= KB(832))
newSWF1 = 1;
else
newSWF1 = 8;
swf1 = INREG(SWF1);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08lx\n", swf1);
swf1 &= ~0x0f;
swf1 |= (newSWF1 & 0x0f);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08lx\n", swf1);
OUTREG(SWF1, swf1);
if (!mapped)
I830UnmapMMIO(pScrn);
}
}
static void
I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
LOCO * colors, VisualPtr pVisual)
{
I830Ptr pI830;
int i, index;
unsigned char r, g, b;
CARD32 val, temp;
DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
pI830 = I830PTR(pScrn);
if (pI830->pipeEnabled[0]) {
temp = INREG(PALETTE_A);
for (i = 0; i < numColors; i++) {
index = indices[i];
r = colors[index].red;
g = colors[index].green;
b = colors[index].blue;
val = (r << 16) | (g << 8) | b;
OUTREG(PALETTE_A + index * 4, val);
}
}
if (pI830->pipeEnabled[1]) {
temp = INREG(PALETTE_B);
for (i = 0; i < numColors; i++) {
index = indices[i];
r = colors[index].red;
g = colors[index].green;
b = colors[index].blue;
val = (r << 16) | (g << 8) | b;
OUTREG(PALETTE_B + index * 4, val);
}
}
}
static void
PreInitCleanup(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
RestoreBIOSMemSize(pScrn);
if (pI830->swfSaved) {
OUTREG(SWF0, pI830->saveSWF0);
OUTREG(SWF4, pI830->saveSWF4);
}
if (pI830->MMIOBase)
I830UnmapMMIO(pScrn);
I830BIOSFreeRec(pScrn);
}
static Bool
I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
{
vgaHWPtr hwp;
I830Ptr pI830;
MessageType from;
rgb defaultWeight = { 0, 0, 0 };
vbeInfoPtr pVbe;
EntityInfoPtr pEnt;
int mem, memsize;
int flags24;
int i, n;
pointer pDDCModule, pVBEModule;
Bool enable;
const char *chipname;
if (pScrn->numEntities != 1)
return FALSE;
if (!xf86LoadSubModule(pScrn, "int10"))
return FALSE;
xf86LoaderReqSymLists(I810int10Symbols, NULL);
if (!(pVBEModule = xf86LoadSubModule(pScrn, "vbe")))
return FALSE;
xf86LoaderReqSymLists(I810vbeSymbols, NULL);
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (flags & PROBE_DETECT) {
I830BIOSProbeDDC(pScrn, pEnt->index);
return TRUE;
}
if (!xf86LoadSubModule(pScrn, "vgahw"))
return FALSE;
xf86LoaderReqSymLists(I810vgahwSymbols, NULL);
if (!vgaHWGetHWRec(pScrn))
return FALSE;
if (!I830BIOSGetRec(pScrn))
return FALSE;
pI830 = I830PTR(pScrn);
pI830->SaveGeneration = -1;
pI830->pEnt = pEnt;
if (pI830->pEnt->location.type != BUS_PCI)
return FALSE;
pI830->PciInfo = xf86GetPciInfoForEntity(pI830->pEnt->index);
pI830->PciTag = pciTag(pI830->PciInfo->bus, pI830->PciInfo->device,
pI830->PciInfo->func);
if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) {
PreInitCleanup(pScrn);
return FALSE;
}
pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
pScrn->monitor = pScrn->confScreen->monitor;
pScrn->progClock = TRUE;
pScrn->rgbBits = 8;
flags24 = Support32bppFb | PreferConvert24to32 | SupportConvert24to32;
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24))
return FALSE;
switch (pScrn->depth) {
case 8:
case 15:
case 16:
case 24:
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given depth (%d) is not supported by I830 driver\n",
pScrn->depth);
return FALSE;
}
xf86PrintDepthBpp(pScrn);
if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
return FALSE;
if (!xf86SetDefaultVisual(pScrn, -1))
return FALSE;
hwp = VGAHWPTR(pScrn);
pI830->cpp = pScrn->bitsPerPixel / 8;
xf86CollectOptions(pScrn, NULL);
if (!(pI830->Options = xalloc(sizeof(I830BIOSOptions))))
return FALSE;
memcpy(pI830->Options, I830BIOSOptions, sizeof(I830BIOSOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI830->Options);
I830SetPIOAccess(pI830);
if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n");
return FALSE;
}
switch (pI830->PciInfo->chipType) {
case PCI_CHIP_I830_M:
chipname = "830M";
break;
case PCI_CHIP_845_G:
chipname = "845G";
break;
case PCI_CHIP_I855_GM:
pI830->variant = (pciReadLong(pI830->PciTag, I85X_CAPID)
>> I85X_VARIANT_SHIFT) & I85X_VARIANT_MASK;
switch (pI830->variant) {
case I855_GM:
chipname = "855GM";
break;
case I855_GME:
chipname = "855GME";
break;
case I852_GM:
chipname = "852GM";
break;
case I852_GME:
chipname = "852GME";
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Unknown 852GM/855GM variant: 0x%x)\n", pI830->variant);
chipname = "852GM/855GM (unknown variant)";
break;
}
break;
case PCI_CHIP_I865_G:
chipname = "865G";
break;
default:
chipname = "unknown chipset";
break;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Integrated Graphics Chipset: Intel(R) %s\n", chipname);
pVbe = pI830->pVbe;
pI830->vbeInfo = VBEGetVBEInfo(pVbe);
if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) {
pScrn->chipset = pI830->pEnt->device->chipset;
from = X_CONFIG;
} else if (pI830->pEnt->device->chipID >= 0) {
pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
pI830->pEnt->device->chipID);
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
pI830->pEnt->device->chipID);
} else {
from = X_PROBED;
pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
pI830->PciInfo->chipType);
}
if (pI830->pEnt->device->chipRev >= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
pI830->pEnt->device->chipRev);
}
xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
(pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i8xx");
if (pI830->pEnt->device->MemBase != 0) {
pI830->LinearAddr = pI830->pEnt->device->MemBase;
from = X_CONFIG;
} else {
if (pI830->PciInfo->memBase[1] != 0) {
pI830->LinearAddr = pI830->PciInfo->memBase[0] & 0xFF000000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No valid FB address in PCI config space\n");
PreInitCleanup(pScrn);
return FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
(unsigned long)pI830->LinearAddr);
if (pI830->pEnt->device->IOBase != 0) {
pI830->MMIOAddr = pI830->pEnt->device->IOBase;
from = X_CONFIG;
} else {
if (pI830->PciInfo->memBase[1]) {
pI830->MMIOAddr = pI830->PciInfo->memBase[1] & 0xFFF80000;
from = X_PROBED;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No valid MMIO address in PCI config space\n");
PreInitCleanup(pScrn);
return FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
(unsigned long)pI830->MMIOAddr);
I830MapMMIO(pScrn);
#if 1
pI830->saveSWF0 = INREG(SWF0);
pI830->saveSWF4 = INREG(SWF4);
pI830->swfSaved = TRUE;
OUTREG(SWF0, pI830->saveSWF0 | (1 << 21));
OUTREG(SWF4, (pI830->saveSWF4 & ~((3 << 19) | (7 << 16))) |
(1 << 23) | (2 << 16));
#endif
if (IS_I830(pI830) || IS_845G(pI830)) {
PCITAG bridge;
CARD16 gmch_ctrl;
bridge = pciTag(0, 0, 0);
gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
pI830->FbMapSize = 0x8000000;
} else {
pI830->FbMapSize = 0x4000000;
}
}
else {
pI830->FbMapSize = 0x8000000;
}
pI830->StolenMemory.Size = I830DetectMemory(pScrn);
pI830->StolenMemory.Start = 0;
pI830->StolenMemory.End = pI830->StolenMemory.Size;
if (pI830->vbeInfo->TotalMemory != pI830->StolenMemory.Size / 1024 / 64) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Detected stolen memory (%ld kB) doesn't match what the BIOS"
" reports (%d kB)\n",
ROUND_DOWN_TO(pI830->StolenMemory.Size / 1024, 64),
pI830->vbeInfo->TotalMemory * 64);
}
mem = I830CheckAvailableMemory(pScrn);
pI830->StolenOnly = FALSE;
if (mem <= 0) {
if (pI830->StolenMemory.Size <= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"/dev/agpgart is either not available, or no memory "
"is available\nfor allocation, "
"and no pre-allocated memory is available.\n");
PreInitCleanup(pScrn);
return FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"/dev/agpgart is either not available, or no memory "
"is available\nfor allocation. "
"Using pre-allocated memory only.\n");
mem = 0;
pI830->StolenOnly = TRUE;
}
if (xf86ReturnOptValBool(pI830->Options, OPTION_NOACCEL, FALSE)) {
pI830->noAccel = TRUE;
}
if (xf86ReturnOptValBool(pI830->Options, OPTION_SW_CURSOR, FALSE)) {
pI830->SWCursor = TRUE;
}
pI830->directRenderingDisabled =
!xf86ReturnOptValBool(pI830->Options, OPTION_DRI, TRUE);
#ifdef XF86DRI
if (!pI830->directRenderingDisabled) {
if (pI830->noAccel || pI830->SWCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
"needs HW cursor and 2D acceleration.\n");
pI830->directRenderingDisabled = TRUE;
} else if (pScrn->depth != 16 && pScrn->depth != 24) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DRI is disabled because it "
"runs only at depths 16 and 24.\n");
pI830->directRenderingDisabled = TRUE;
}
}
#endif
if (!pI830->pEnt->device->videoRam) {
from = X_DEFAULT;
#ifdef XF86DRI
if (!pI830->directRenderingDisabled)
pScrn->videoRam = I830_DEFAULT_VIDEOMEM_3D;
else
#endif
pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D;
if (pI830->StolenMemory.Size / 1024 > pScrn->videoRam)
pScrn->videoRam = ROUND_TO(pI830->StolenMemory.Size / 1024, 1024);
} else {
from = X_CONFIG;
pScrn->videoRam = pI830->pEnt->device->videoRam;
}
DPRINTF(PFX,
"Available memory: %dk\n"
"Requested memory: %dk\n", mem, pScrn->videoRam);
if (mem + (pI830->StolenMemory.Size / 1024) < pScrn->videoRam) {
pScrn->videoRam = mem + (pI830->StolenMemory.Size / 1024);
from = X_PROBED;
if (mem + (pI830->StolenMemory.Size / 1024) <
pI830->pEnt->device->videoRam) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"VideoRAM reduced to %d kByte "
"(limited to available sysmem)\n", pScrn->videoRam);
}
}
if (pScrn->videoRam > pI830->FbMapSize / 1024) {
pScrn->videoRam = pI830->FbMapSize / 1024;
if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam)
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"VideoRam reduced to %d kByte (limited to aperture size)\n",
pScrn->videoRam);
}
if (mem > 0) {
int reserve = (HWCURSOR_SIZE + OVERLAY_SIZE) / 1024;
if (pScrn->videoRam - reserve >= I830_MAXIMUM_VBIOS_MEM)
pI830->newBIOSMemSize = KB(I830_MAXIMUM_VBIOS_MEM);
else
pI830->newBIOSMemSize =
KB(ROUND_DOWN_TO(pScrn->videoRam - reserve, 64));
if (pI830->vbeInfo->TotalMemory * 64 < pI830->newBIOSMemSize / 1024) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Will attempt to tell the BIOS that there is "
"%d kB VideoRAM\n", pI830->newBIOSMemSize / 1024);
if (SaveBIOSMemSize(pScrn)) {
pI830->overrideBIOSMemSize = TRUE;
SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
VBEFreeVBEInfo(pI830->vbeInfo);
vbeFree(pI830->pVbe);
pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
pVbe = pI830->pVbe;
pI830->vbeInfo = VBEGetVBEInfo(pVbe);
pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"BIOS now sees %ld kB VideoRAM\n",
pI830->BIOSMemorySize / 1024);
} else if ((pI830->saveBIOSMemSize
= TweakMemorySize(pScrn, pI830->newBIOSMemSize, TRUE)) != 0)
pI830->overrideBIOSMemSize = TRUE;
else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"BIOS view of memory size can't be changed "
"(this is not an error).\n");
}
}
}
pVbe = pI830->pVbe;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Pre-allocated VideoRAM: %ld kByte\n",
pI830->StolenMemory.Size / 1024);
xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", pScrn->videoRam);
pI830->TotalVideoRam = KB(pScrn->videoRam);
if (pI830->StolenMemory.Size > pI830->TotalVideoRam) {
pI830->StolenMemory.Size = pI830->TotalVideoRam;
pI830->StolenMemory.End = pI830->TotalVideoRam;
}
if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
&(pI830->CacheLines))) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
pI830->CacheLines);
} else {
pI830->CacheLines = -1;
}
pI830->XvDisabled =
!xf86ReturnOptValBool(pI830->Options, OPTION_XVIDEO, TRUE);
#ifdef I830_XV
if (xf86GetOptValInteger(pI830->Options, OPTION_VIDEO_KEY,
&(pI830->colorKey))) {
from = X_CONFIG;
} else if (xf86GetOptValInteger(pI830->Options, OPTION_COLOR_KEY,
&(pI830->colorKey))) {
from = X_CONFIG;
} else {
pI830->colorKey = (1 << pScrn->offset.red) |
(1 << pScrn->offset.green) |
(((pScrn->mask.blue >> pScrn->offset.blue) - 1) <<
pScrn->offset.blue);
from = X_DEFAULT;
}
xf86DrvMsg(pScrn->scrnIndex, from, "video overlay key set to 0x%x\n",
pI830->colorKey);
#endif
pI830->allowPageFlip = FALSE;
enable = xf86ReturnOptValBool(pI830->Options, OPTION_PAGEFLIP, FALSE);
#ifdef XF86DRI
if (!pI830->directRenderingDisabled) {
pI830->allowPageFlip = enable;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
enable ? "enabled" : "disabled");
}
#endif
if (IS_MOBILE(pI830))
pI830->CursorNeedsPhysical = TRUE;
else
pI830->CursorNeedsPhysical = FALSE;
if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830))
pI830->NeedRingBufferLow = TRUE;
if (pI830->StolenOnly && pI830->CursorNeedsPhysical && !pI830->SWCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"HW Cursor disabled because it needs agpgart memory.\n");
pI830->SWCursor = TRUE;
}
if (!pI830->SWCursor)
pScrn->videoRam -= (HWCURSOR_SIZE / 1024);
if (!pI830->XvDisabled)
pScrn->videoRam -= (OVERLAY_SIZE / 1024);
if (!pI830->noAccel) {
pScrn->videoRam -= (PRIMARY_RINGBUFFER_SIZE / 1024);
pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024);
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
{
Gamma zeros = { 0.0, 0.0, 0.0 };
if (!xf86SetGamma(pScrn, zeros))
return FALSE;
}
if (IS_MOBILE(pI830))
pI830->availablePipes = 2;
else
pI830->availablePipes = 1;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
pI830->availablePipes, pI830->availablePipes > 1 ? "s" : "");
pI830->displayInfo = TRUE;
from = X_DEFAULT;
if (!xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, TRUE)) {
from = X_CONFIG;
pI830->displayInfo = FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n",
pI830->displayInfo ? "enabled" : "disabled");
if (!I830DetectDisplayDevice(pScrn)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Couldn't detect display devices.\n");
PreInitCleanup(pScrn);
return FALSE;
}
if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) {
PreInitCleanup(pScrn);
return FALSE;
}
if ((pI830->vesa->monitor = vbeDoEDID(pVbe, pDDCModule)) != NULL) {
xf86PrintEDID(pI830->vesa->monitor);
}
if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL)
xf86SetDDCproperties(pScrn, pI830->vesa->monitor);
xf86UnloadSubModule(pDDCModule);
#define VIDEO_BIOS_SCRATCH 0x18
#if 1
{
CARD8 gr18;
gr18 = pI830->readControl(pI830, GRX, VIDEO_BIOS_SCRATCH);
gr18 &= ~0x80;
pI830->writeControl(pI830, GRX, VIDEO_BIOS_SCRATCH, gr18);
}
#endif
for (i = 0; i < pI830->availablePipes; i++) {
int pipe =
(pI830->configuredDevices >> PIPE_SHIFT(i)) & PIPE_ACTIVE_MASK;
if (pipe & ~PIPE_CRT_ACTIVE) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"A non-CRT device is attached to pipe %c.\n"
"\tNo refresh rate overrides will be attempted.\n",
PIPE_NAME(i));
pI830->vesa->useDefaultRefresh = TRUE;
}
if (!pI830->vesa->useDefaultRefresh)
pI830->useExtendedRefresh = TRUE;
}
if (pI830->useExtendedRefresh) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n");
}
pI830->enableDisplays = !IS_I830(pI830) && pI830->useExtendedRefresh;
if (pI830->enableDisplays) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Will use BIOS call 0x5f64 to enable displays.\n");
}
if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64))
memsize = pI830->vbeInfo->TotalMemory * 64;
else
memsize = pScrn->videoRam;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Maximum space available for video modes: %d kByte\n", memsize);
pScrn->modePool = VBEGetModePool(pScrn, pVbe, pI830->vbeInfo,
V_MODETYPE_VGA);
if (!pScrn->modePool) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No Video BIOS modes for chosen depth.\n");
PreInitCleanup(pScrn);
return FALSE;
}
VBESetModeNames(pScrn->modePool);
n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL,
NULL, 0, MAX_DISPLAY_PITCH, 1,
0, MAX_DISPLAY_HEIGHT,
pScrn->display->virtualX,
pScrn->display->virtualY,
memsize, LOOKUP_BEST_REFRESH);
if (n <= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
PreInitCleanup(pScrn);
return FALSE;
}
xf86PruneDriverModes(pScrn);
pScrn->currentMode = pScrn->modes;
if (pScrn->modes == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
PreInitCleanup(pScrn);
return FALSE;
}
#ifndef USE_PITCHES
#define USE_PITCHES 1
#endif
#if defined(XF86DRI)
if (!pI830->directRenderingDisabled) {
int savedDisplayWidth = pScrn->displayWidth;
int memNeeded = 0;
static const int pitches[] = {
128 * 2,
128 * 4,
128 * 8,
128 * 16,
128 * 32,
128 * 64,
0
};
#ifdef I830_XV
pI830->XvEnabled = !pI830->XvDisabled;
#endif
for (i = 0; pitches[i] != 0; i++) {
#if USE_PITCHES
if (pitches[i] >= pScrn->displayWidth) {
pScrn->displayWidth = pitches[i];
break;
}
#else
if (pitches[i] == pScrn->displayWidth)
break;
#endif
}
if (pScrn->displayWidth == pitches[i]) {
I830ResetAllocations(pScrn, 0);
if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN)) {
memNeeded = I830GetExcessMemoryAllocations(pScrn);
if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
if (memNeeded > 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"%d kBytes additional video memory is "
"required to\n\tenable tiling mode for DRI.\n",
(memNeeded + 1023) / 1024);
}
if (pI830->MemoryAperture.Size < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Allocation with DRI tiling enabled would "
"exceed the\n"
"\tmemory aperture size (%ld kB) by %ld kB.\n"
"\tReduce VideoRam amount to avoid this!\n",
pI830->FbMapSize / 1024,
-pI830->MemoryAperture.Size / 1024);
}
pScrn->displayWidth = savedDisplayWidth;
pI830->allowPageFlip = FALSE;
} else if (pScrn->displayWidth != savedDisplayWidth) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Increasing the scanline pitch to allow tiling mode "
"(%d -> %d).\n",
savedDisplayWidth, pScrn->displayWidth);
}
} else {
memNeeded = 0;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Unexpected dry run allocation failure (1).\n");
}
}
if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
pI830->disableTiling = TRUE;
I830ResetAllocations(pScrn, 0);
if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) &&
I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_NO_TILING)) {
memNeeded = I830GetExcessMemoryAllocations(pScrn);
if (memNeeded > 0 || pI830->MemoryAperture.Size < 0) {
if (memNeeded > 0) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"%d kBytes additional video memory is required "
"to enable DRI.\n",
(memNeeded + 1023) / 1024);
}
if (pI830->MemoryAperture.Size < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Allocation with DRI enabled would "
"exceed the\n"
"\tmemory aperture size (%ld kB) by %ld kB.\n"
"\tReduce VideoRam amount to avoid this!\n",
pI830->FbMapSize / 1024,
-pI830->MemoryAperture.Size / 1024);
}
pI830->directRenderingDisabled = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling DRI.\n");
}
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Unexpected dry run allocation failure (2).\n");
}
}
}
#endif
VBEPrintModes(pScrn);
if (!pI830->vesa->useDefaultRefresh) {
VBESetModeParameters(pScrn, pVbe);
}
RestoreBIOSMemSize(pScrn);
if (pI830->swfSaved) {
OUTREG(SWF0, pI830->saveSWF0);
OUTREG(SWF4, pI830->saveSWF4);
}
I830UnmapMMIO(pScrn);
xf86SetDpi(pScrn, 0, 0);
if (!xf86LoadSubModule(pScrn, "fb")) {
PreInitCleanup(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810fbSymbols, NULL);
if (!pI830->noAccel) {
if (!xf86LoadSubModule(pScrn, "xaa")) {
PreInitCleanup(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810xaaSymbols, NULL);
}
if (!pI830->SWCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
PreInitCleanup(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810ramdacSymbols, NULL);
}
I830SetMMIOAccess(pI830);
xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr);
xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr);
VBEFreeVBEInfo(pI830->vbeInfo);
vbeFree(pVbe);
pI830->vbeRestoreWorkaround = TRUE;
from = X_DEFAULT;
if (xf86ReturnOptValBool(pI830->Options, OPTION_VBE_RESTORE, FALSE)) {
pI830->vbeRestoreWorkaround = FALSE;
from = X_CONFIG;
}
xf86DrvMsg(pScrn->scrnIndex, from, "VBE Restore workaround: %s.\n",
pI830->vbeRestoreWorkaround ? "enabled" : "disabled");
#if defined(XF86DRI)
if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) &&
!pI830->directRenderingDisabled) {
if (xf86LoadSubModule(pScrn, "dri")) {
xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
}
}
if (!pI830->directRenderingDisabled) {
if (!xf86LoadSubModule(pScrn, "shadow")) {
PreInitCleanup(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(I810shadowSymbols, NULL);
}
#endif
return TRUE;
}
static Bool
CheckInheritedState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int errors = 0, fatal = 0;
unsigned long temp, head, tail;
temp = INREG(PGE_ERR);
if (temp != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp);
errors++;
}
temp = INREG(PGETBL_CTL);
if (!(temp & 1)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp);
errors++;
}
temp = INREG(LP_RING + RING_LEN);
if (temp & 1) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp);
errors++;
}
head = INREG(LP_RING + RING_HEAD);
tail = INREG(LP_RING + RING_TAIL);
if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate "
"ring buffer not flushed\n", head, tail);
errors++;
}
#if 0
if (errors)
I830PrintErrorState(pScrn);
#endif
if (fatal)
FatalError("CheckInheritedState: can't recover from the above\n");
return (errors != 0);
}
static void
ResetState(ScrnInfoPtr pScrn, Bool flush)
{
I830Ptr pI830 = I830PTR(pScrn);
int i;
unsigned long temp;
DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
for (i = 0; i < 8; i++)
OUTREG(FENCE + i * 4, 0);
if (pI830->AccelInfoRec != NULL && flush) {
temp = INREG(LP_RING + RING_LEN);
if (temp & 1) {
I830RefreshRing(pScrn);
I830Sync(pScrn);
DO_RING_IDLE();
}
}
OUTREG(LP_RING + RING_LEN, 0);
OUTREG(LP_RING + RING_HEAD, 0);
OUTREG(LP_RING + RING_TAIL, 0);
OUTREG(LP_RING + RING_START, 0);
if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
pI830->CursorInfoRec->HideCursor(pScrn);
}
static void
SetFenceRegs(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int i;
DPRINTF(PFX, "SetFenceRegs\n");
for (i = 0; i < 8; i++) {
OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
if (I810_DEBUG & DEBUG_VERBOSE_VGA)
ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]);
}
}
static void
SetRingRegs(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
unsigned int itemp;
DPRINTF(PFX, "SetRingRegs\n");
if (pI830->noAccel)
return;
OUTREG(LP_RING + RING_LEN, 0);
OUTREG(LP_RING + RING_TAIL, 0);
OUTREG(LP_RING + RING_HEAD, 0);
if ((pI830->LpRing.mem.Start & I830_RING_START_MASK) !=
pI830->LpRing.mem.Start) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"I830SetRingRegs: Ring buffer start (%lx) violates its "
"mask (%x)\n", pI830->LpRing.mem.Start, I830_RING_START_MASK);
}
itemp = pI830->LpRing.mem.Start & I830_RING_START_MASK;
OUTREG(LP_RING + RING_START, itemp);
if (((pI830->LpRing.mem.Size - 4096) & I830_RING_NR_PAGES) !=
pI830->LpRing.mem.Size - 4096) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
"mask (%x)\n", pI830->LpRing.mem.Size - 4096,
I830_RING_NR_PAGES);
}
itemp = (pI830->LpRing.mem.Size - 4096) & I830_RING_NR_PAGES;
itemp |= (RING_NO_REPORT | RING_VALID);
OUTREG(LP_RING + RING_LEN, itemp);
I830RefreshRing(pScrn);
}
static void
SetHWOperatingState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "SetHWOperatingState\n");
if (!pI830->noAccel)
SetRingRegs(pScrn);
SetFenceRegs(pScrn);
if (!pI830->SWCursor)
I830InitHWCursor(pScrn);
}
static Bool
SaveHWState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaRegPtr vgaReg = &hwp->SavedReg;
VbeModeInfoBlock *modeInfo;
VESAPtr pVesa;
DPRINTF(PFX, "SaveHWState\n");
pVesa = pI830->vesa;
VBEGetVBEMode(pVbe, &pVesa->stateMode);
modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode);
pVesa->savedScanlinePitch = 0;
if (modeInfo) {
if (VBE_MODE_GRAPHICS(modeInfo)) {
VBEGetLogicalScanline(pVbe, &pVesa->savedScanlinePitch, NULL, NULL);
}
VBEFreeModeInfo(modeInfo);
}
vgaHWUnlock(hwp);
vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
pVesa = pI830->vesa;
if (!pI830->vbeRestoreWorkaround) {
CARD16 imr = INREG16(IMR);
CARD16 ier = INREG16(IER);
CARD16 hwstam = INREG16(HWSTAM);
if (!VBESaveRestore(pVbe, MODE_SAVE, &pVesa->state, &pVesa->stateSize,
&pVesa->statePage)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"SaveHWState: VBESaveRestore(MODE_SAVE) failed.\n");
return FALSE;
}
OUTREG16(IMR, imr);
OUTREG16(IER, ier);
OUTREG16(HWSTAM, hwstam);
}
pVesa->savedPal = VBESetGetPaletteData(pVbe, FALSE, 0, 256,
NULL, FALSE, FALSE);
if (!pVesa->savedPal) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"SaveHWState: VBESetGetPaletteData(GET) failed.\n");
return FALSE;
}
return TRUE;
}
static Bool
RestoreHWState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaRegPtr vgaReg = &hwp->SavedReg;
VESAPtr pVesa;
Bool restored = FALSE;
DPRINTF(PFX, "RestoreHWState\n");
pVesa = pI830->vesa;
if (pVesa->useDefaultRefresh) {
int mode = 0;
switch (pScrn->depth) {
case 8:
mode = 0x30;
break;
case 15:
mode = 0x40;
break;
case 16:
mode = 0x41;
break;
case 24:
mode = 0x50;
break;
}
mode |= (1 << 15) | (1 << 14);
I830VESASetVBEMode(pScrn, mode, NULL);
}
if (pVesa->state && pVesa->stateSize) {
CARD16 imr = INREG16(IMR);
CARD16 ier = INREG16(IER);
CARD16 hwstam = INREG16(HWSTAM);
if (!pVesa->pstate) {
pVesa->pstate = xalloc(pVesa->stateSize);
if (pVesa->pstate)
memcpy(pVesa->pstate, pVesa->state, pVesa->stateSize);
}
restored = VBESaveRestore(pVbe, MODE_RESTORE, &pVesa->state,
&pVesa->stateSize, &pVesa->statePage);
if (!restored) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"RestoreHWState: VBESaveRestore failed.\n");
}
if (pVesa->pstate)
memcpy(pVesa->state, pVesa->pstate, pVesa->stateSize);
OUTREG16(IMR, imr);
OUTREG16(IER, ier);
OUTREG16(HWSTAM, hwstam);
}
if (!restored) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Setting the original video mode instead of restoring\n\t"
"the saved state\n");
I830VESASetVBEMode(pScrn, pVesa->stateMode, NULL);
}
if (pVesa->savedScanlinePitch)
VBESetLogicalScanline(pVbe, pVesa->savedScanlinePitch);
if (pVesa->savedPal)
VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE);
vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
vgaHWLock(hwp);
return TRUE;
}
#ifndef USE_VBE
#define USE_VBE 1
#endif
static Bool
I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block)
{
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
#if USE_VBE
return VBESetVBEMode(pI830->pVbe, mode, block);
#else
{
vbeInfoPtr pVbe = pI830->pVbe;
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x80 | (mode & 0x7f);
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
pVbe->pInt10->ax = 0x0f00;
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
if ((pVbe->pInt10->ax & 0x7f) == (mode & 0x7f))
return TRUE;
else
return FALSE;
}
#endif
}
static Bool
I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
{
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
VbeModeInfoData *data;
int mode, i;
CARD32 planeA, planeB, temp;
int refresh = 60;
#ifdef XF86DRI
Bool didLock = FALSE;
#endif
DPRINTF(PFX, "I830VESASetMode\n");
data = (VbeModeInfoData *) pMode->Private;
mode = data->mode | (1 << 15) | (1 << 14);
#ifdef XF86DRI
if (pI830->directRenderingEnabled && !pI830->LockHeld) {
DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
pI830->LockHeld = 1;
didLock = TRUE;
}
#endif
#ifndef MODESWITCH_RESET_STATE
#define MODESWITCH_RESET_STATE 0
#endif
#if MODESWITCH_RESET_STATE
ResetState(pScrn, TRUE);
#endif
if (pI830->vesa->useDefaultRefresh)
mode &= ~(1 << 11);
if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) {
if ((data->block && (mode & (1 << 11))) &&
I830VESASetVBEMode(pScrn, (mode & ~(1 << 11)), NULL) == TRUE) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Set VBE Mode rejected this modeline.\n\t"
"Trying standard mode instead!\n");
DPRINTF(PFX, "OOPS!\n");
xfree(data->block);
data->block = NULL;
data->mode &= ~(1 << 11);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n");
return FALSE;
}
}
if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
(mode & (1 << 11)) && data && data->data && data->block) {
if (!SetRefreshRate(pScrn, mode, 60)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"BIOS call 0x5f05 not supported, "
"setting refresh with VBE 3 method.\n");
pI830->useExtendedRefresh = FALSE;
pI830->enableDisplays = FALSE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Not using BIOS call 0x5f64 to enable displays.\n");
}
}
if (data->data->XResolution != pScrn->displayWidth)
VBESetLogicalScanline(pVbe, pScrn->displayWidth);
if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01)
VBESetGetDACPaletteFormat(pVbe, 8);
if (pI830->enableDisplays) {
if (!SetDisplayDevices(pScrn, pI830->configuredDevices)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Failed to switch to configured display devices\n");
}
}
if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh &&
(mode & (1 << 11)) && data && data->data && data->block) {
refresh = SetRefreshRate(pScrn, mode, data->block->RefreshRate / 100);
if (!refresh) {
refresh = 60;
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Failed to set refresh rate to %dHz.\n",
data->block->RefreshRate / 100);
}
}
planeA = INREG(DSPACNTR);
planeB = INREG(DSPBCNTR);
pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0);
pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s.\n",
pI830->planeEnabled[0] ? "enabled" : "disabled");
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s.\n",
pI830->planeEnabled[1] ? "enabled" : "disabled");
if (!pI830->planeEnabled[0] && !pI830->planeEnabled[1]) {
if (IS_MOBILE(pI830)) {
if ((pI830->pipeEnabled[0] &&
((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
(pI830->pipeEnabled[1] &&
((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
pI830->planeEnabled[0] = TRUE;
}
if ((pI830->pipeEnabled[0] &&
((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) ||
(pI830->pipeEnabled[1] &&
((planeB & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_B))) {
pI830->planeEnabled[1] = TRUE;
}
} else {
pI830->planeEnabled[0] = TRUE;
}
if (pI830->planeEnabled[0]) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n");
planeA |= DISPLAY_PLANE_ENABLE;
OUTREG(DSPACNTR, planeA);
temp = INREG(DSPABASE);
OUTREG(DSPABASE, temp);
}
if (pI830->planeEnabled[1]) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n");
planeB |= DISPLAY_PLANE_ENABLE;
OUTREG(DSPBCNTR, planeB);
temp = INREG(DSPBADDR);
OUTREG(DSPBADDR, temp);
}
}
temp = INREG(PIPEACONF);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", temp);
if (IS_MOBILE(pI830)) {
temp = INREG(PIPEBCONF);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp);
}
#if PRINT_MODE_INFO
temp = INREG(HTOTAL_A);
ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff,
(temp >> 16) & 0xfff);
temp = INREG(HBLANK_A);
ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff,
(temp >> 16) & 0xfff);
temp = INREG(HSYNC_A);
ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff,
(temp >> 16) & 0xfff);
temp = INREG(VTOTAL_A);
ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff,
(temp >> 16) & 0xfff);
temp = INREG(VBLANK_A);
ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff,
(temp >> 16) & 0xfff);
temp = INREG(VSYNC_A);
ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff,
(temp >> 16) & 0xfff);
temp = INREG(PIPEASRC);
ErrorF("Image size: %dx%d (%dx%d)\n",
(temp >> 16) & 0x7ff, temp & 0x7ff,
(((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1));
ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3);
temp = INREG(DSPABASE);
ErrorF("Plane A start offset is %d\n", temp);
temp = INREG(DSPASTRIDE);
ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp);
#endif
for (i = 0; i < MAX_DISPLAY_PIPES; i++) {
CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE;
CARD32 basereg = i ? DSPBBASE : DSPABASE;
if (!pI830->planeEnabled[i])
continue;
temp = INREG(stridereg);
if (temp / pI830->cpp != pScrn->displayWidth) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
(int)(temp / pI830->cpp), pScrn->displayWidth);
OUTREG(stridereg, pScrn->displayWidth * pI830->cpp);
temp = INREG(basereg);
OUTREG(basereg, temp);
}
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n",
pMode->HDisplay * pMode->VDisplay * refresh / 1000000);
{
int maxBandwidth, bandwidthA, bandwidthB;
if (GetModeSupport(pScrn, 0x80, 0x80, 0x80, 0x80,
&maxBandwidth, &bandwidthA, &bandwidthB)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "maxBandwidth is %d Mbyte/s, "
"pipe bandwidths are %d Mbyte/s, %d Mbyte/s\n",
maxBandwidth, bandwidthA, bandwidthB);
}
}
{
int ret;
ret = GetLFPCompMode(pScrn);
if (ret != -1) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"LFP compensation mode: 0x%x\n", ret);
}
}
#if MODESWITCH_RESET_STATE
ResetState(pScrn, TRUE);
SetHWOperatingState(pScrn);
#endif
#ifdef XF86DRI
if (pI830->directRenderingEnabled && didLock) {
DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
pI830->LockHeld = 0;
}
#endif
pScrn->vtSema = TRUE;
return TRUE;
}
static void
InitRegisterRec(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
I830RegPtr i830Reg = &pI830->ModeReg;
int i;
for (i = 0; i < 8; i++)
i830Reg->Fence[i] = 0;
}
void
I830PrintErrorState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
INREG(PGETBL_CTL), INREG(PGE_ERR));
ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR), INREG(IPEHR));
ErrorF("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));
ErrorF("eir: %x esr: %x emr: %x\n",
INREG16(EIR), INREG16(ESR), INREG16(EMR));
ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS));
ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
}
#ifdef I830DEBUG
static void
dump_DSPACNTR(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
unsigned int tmp;
tmp = INREG(0x70180);
ErrorF("Display A Plane Control Register (0x%.8x)\n", tmp);
if (tmp & BIT(31))
ErrorF(" Display Plane A (Primary) Enable\n");
else
ErrorF(" Display Plane A (Primary) Disabled\n");
if (tmp & BIT(30))
ErrorF(" Display A pixel data is gamma corrected\n");
else
ErrorF(" Display A pixel data bypasses gamma correction logic (default)\n");
switch ((tmp & 0x3c000000) >> 26) {
case 0x00:
case 0x01:
case 0x03:
ErrorF(" Reserved\n");
break;
case 0x02:
ErrorF(" 8-bpp Indexed\n");
break;
case 0x04:
ErrorF(" 15-bit (5-5-5) pixel format (Targa compatible)\n");
break;
case 0x05:
ErrorF(" 16-bit (5-6-5) pixel format (XGA compatible)\n");
break;
case 0x06:
ErrorF(" 32-bit format (X:8:8:8)\n");
break;
case 0x07:
ErrorF(" 32-bit format (8:8:8:8)\n");
break;
default:
ErrorF(" Unknown - Invalid register value maybe?\n");
}
if (tmp & BIT(25))
ErrorF(" Stereo Enable\n");
else
ErrorF(" Stereo Disable\n");
if (tmp & BIT(24))
ErrorF(" Display A, Pipe B Select\n");
else
ErrorF(" Display A, Pipe A Select\n");
if (tmp & BIT(22))
ErrorF(" Source key is enabled\n");
else
ErrorF(" Source key is disabled\n");
switch ((tmp & 0x00300000) >> 20) {
case 0x00:
ErrorF(" No line duplication\n");
break;
case 0x01:
ErrorF(" Line/pixel Doubling\n");
break;
case 0x02:
case 0x03:
ErrorF(" Reserved\n");
break;
}
if (tmp & BIT(18))
ErrorF(" Stereo output is high during second image\n");
else
ErrorF(" Stereo output is high during first image\n");
}
static void
dump_DSPBCNTR(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
unsigned int tmp;
tmp = INREG(0x71180);
ErrorF("Display B/Sprite Plane Control Register (0x%.8x)\n", tmp);
if (tmp & BIT(31))
ErrorF(" Display B/Sprite Enable\n");
else
ErrorF(" Display B/Sprite Disable\n");
if (tmp & BIT(30))
ErrorF(" Display B pixel data is gamma corrected\n");
else
ErrorF(" Display B pixel data bypasses gamma correction logic (default)\n");
switch ((tmp & 0x3c000000) >> 26) {
case 0x00:
case 0x01:
case 0x03:
ErrorF(" Reserved\n");
break;
case 0x02:
ErrorF(" 8-bpp Indexed\n");
break;
case 0x04:
ErrorF(" 15-bit (5-5-5) pixel format (Targa compatible)\n");
break;
case 0x05:
ErrorF(" 16-bit (5-6-5) pixel format (XGA compatible)\n");
break;
case 0x06:
ErrorF(" 32-bit format (X:8:8:8)\n");
break;
case 0x07:
ErrorF(" 32-bit format (8:8:8:8)\n");
break;
default:
ErrorF(" Unknown - Invalid register value maybe?\n");
}
if (tmp & BIT(25))
ErrorF(" Stereo is enabled and both start addresses are used in a two frame sequence\n");
else
ErrorF(" Stereo disable and only a single start address is used\n");
if (tmp & BIT(24))
ErrorF(" Display B/Sprite, Pipe B Select\n");
else
ErrorF(" Display B/Sprite, Pipe A Select\n");
if (tmp & BIT(22))
ErrorF(" Sprite source key is enabled\n");
else
ErrorF(" Sprite source key is disabled (default)\n");
switch ((tmp & 0x00300000) >> 20) {
case 0x00:
ErrorF(" No line duplication\n");
break;
case 0x01:
ErrorF(" Line/pixel Doubling\n");
break;
case 0x02:
case 0x03:
ErrorF(" Reserved\n");
break;
}
if (tmp & BIT(18))
ErrorF(" Stereo output is high during second image\n");
else
ErrorF(" Stereo output is high during first image\n");
if (tmp & BIT(15))
ErrorF(" Alpha transfer mode enabled\n");
else
ErrorF(" Alpha transfer mode disabled\n");
if (tmp & BIT(0))
ErrorF(" Sprite is above overlay\n");
else
ErrorF(" Sprite is above display A (default)\n");
}
void
I830_dump_registers(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
unsigned int i;
ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
dump_DSPACNTR(pScrn);
dump_DSPBCNTR(pScrn);
ErrorF("0x71400 == 0x%.8x\n", INREG(0x71400));
ErrorF("0x70008 == 0x%.8x\n", INREG(0x70008));
for (i = 0x71410; i <= 0x71428; i += 4)
ErrorF("0x%x == 0x%.8x\n", i, INREG(i));
ErrorF("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
}
#endif
static Bool
I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
ScrnInfoPtr pScrn;
vgaHWPtr hwp;
I830Ptr pI830;
VisualPtr visual;
#ifdef XF86DRI
Bool driDisabled;
#endif
pScrn = xf86Screens[pScreen->myNum];
pI830 = I830PTR(pScrn);
hwp = VGAHWPTR(pScrn);
pI830->starting = TRUE;
pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
if (!pI830->pVbe)
return FALSE;
pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
miClearVisualTypes();
if (!xf86SetDefaultVisual(pScrn, -1))
return FALSE;
if (pScrn->bitsPerPixel > 8) {
if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
pScrn->rgbBits, TrueColor))
return FALSE;
} else {
if (!miSetVisualTypes(pScrn->depth,
miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual))
return FALSE;
}
if (!miSetPixmapDepths())
return FALSE;
#ifdef I830_XV
pI830->XvEnabled = !pI830->XvDisabled;
if (pI830->XvEnabled) {
if (pI830->noAccel || pI830->StolenOnly) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it "
"needs 2D accel and AGPGART.\n");
pI830->XvEnabled = FALSE;
}
}
#else
pI830->XvEnabled = FALSE;
#endif
I830ResetAllocations(pScrn, 0);
I830Allocate2DMemory(pScrn, ALLOC_INITIAL);
if (!pI830->noAccel) {
if (pI830->LpRing.mem.Size == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling acceleration because the ring buffer "
"allocation failed.\n");
pI830->noAccel = TRUE;
}
}
if (!pI830->SWCursor) {
if (pI830->CursorMem.Size == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling HW cursor because the cursor memory "
"allocation failed.\n");
pI830->SWCursor = TRUE;
}
}
#ifdef I830_XV
if (pI830->XvEnabled) {
if (pI830->noAccel) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because it "
"needs 2D acceleration.\n");
pI830->XvEnabled = FALSE;
}
if (pI830->OverlayMem.Physical == 0) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling Xv because the overlay register buffer "
"allocation failed.\n");
pI830->XvEnabled = FALSE;
}
}
#endif
InitRegisterRec(pScrn);
#ifdef XF86DRI
pI830->directRenderingEnabled = !pI830->directRenderingDisabled;
if (pI830->directRenderingEnabled) {
if (pI830->noAccel || pI830->SWCursor || pI830->StolenOnly) {
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
"needs HW cursor, 2D accel and AGPGART.\n");
pI830->directRenderingEnabled = FALSE;
}
}
driDisabled = !pI830->directRenderingEnabled;
if (pI830->directRenderingEnabled)
pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
if (pI830->directRenderingEnabled) {
pI830->directRenderingEnabled =
I830Allocate3DMemory(pScrn,
pI830->disableTiling ? ALLOC_NO_TILING : 0);
if (!pI830->directRenderingEnabled)
I830DRICloseScreen(pScreen);
}
#else
pI830->directRenderingEnabled = FALSE;
#endif
I830Allocate2DMemory(pScrn, 0);
DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n");
if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool)))
return FALSE;
DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n");
if (!I830FixupOffsets(pScrn))
return FALSE;
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
I830SetupMemoryTiling(pScrn);
pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
}
#endif
DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
if (!I830MapMem(pScrn))
return FALSE;
pScrn->memPhysBase = (unsigned long)pI830->FbBase;
pScrn->fbOffset = pI830->FrontBuffer.Start;
pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0);
vgaHWGetIOBase(hwp);
DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n");
if (!vgaHWMapMem(pScrn))
return FALSE;
memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg));
DPRINTF(PFX, "assert( if(!I830BIOSEnterVT(scrnIndex, 0)) )\n");
if (!I830BIOSEnterVT(scrnIndex, 0))
return FALSE;
DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi,
pScrn->displayWidth, pScrn->bitsPerPixel))
return FALSE;
if (pScrn->bitsPerPixel > 8) {
visual = pScreen->visuals + pScreen->numVisuals;
while (--visual >= pScreen->visuals) {
if ((visual->class | DynamicClass) == DirectColor) {
visual->offsetRed = pScrn->offset.red;
visual->offsetGreen = pScrn->offset.green;
visual->offsetBlue = pScrn->offset.blue;
visual->redMask = pScrn->mask.red;
visual->greenMask = pScrn->mask.green;
visual->blueMask = pScrn->mask.blue;
}
}
}
fbPictureInit(pScreen, 0, 0);
xf86SetBlackWhitePixels(pScreen);
#if 1
I830DGAInit(pScreen);
#endif
DPRINTF(PFX,
"assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to init memory manager\n");
return FALSE;
}
if (!pI830->noAccel) {
if (!I830AccelInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware acceleration initialization failed\n");
}
}
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
xf86SetSilkenMouse(pScreen);
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
if (!pI830->SWCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
if (!I830CursorInit(pScreen))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware cursor initialization failed\n");
} else
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n");
if (!miCreateDefColormap(pScreen))
return FALSE;
DPRINTF(PFX, "assert( if(!xf86HandleColormaps(pScreen, ...)) )\n");
if (!xf86HandleColormaps(pScreen, 256, 8, I830LoadPalette, 0,
CMAP_RELOAD_ON_MODE_SWITCH)) {
return FALSE;
}
xf86DPMSInit(pScreen, I830DisplayPowerManagementSet, 0);
#ifdef I830_XV
if (pI830->XvEnabled)
I830InitVideo(pScreen);
#endif
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
}
#endif
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
pI830->directRenderingOpen = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n");
I830EmitInvarientState(pScrn);
} else {
if (driDisabled)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n");
else
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n");
}
#else
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Not available\n");
#endif
pScreen->SaveScreen = I830BIOSSaveScreen;
pI830->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = I830BIOSCloseScreen;
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
#if 0
#ifdef I830DEBUG
I830_dump_registers(pScrn);
#endif
#endif
pI830->starting = FALSE;
pI830->closing = FALSE;
pI830->suspended = FALSE;
return TRUE;
}
static void
I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags)
{
ScrnInfoPtr pScrn;
I830Ptr pI830;
vbeInfoPtr pVbe;
pScrn = xf86Screens[scrnIndex];
pI830 = I830PTR(pScrn);
pVbe = pI830->pVbe;
DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
x, pI830->xoffset, y, pI830->yoffset);
VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE);
}
static void
I830BIOSFreeScreen(int scrnIndex, int flags)
{
I830BIOSFreeRec(xf86Screens[scrnIndex]);
if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
vgaHWFreeHWRec(xf86Screens[scrnIndex]);
}
#ifndef SAVERESTORE_HWSTATE
#define SAVERESTORE_HWSTATE 0
#endif
#if SAVERESTORE_HWSTATE
static void
SaveHWOperatingState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
I830RegPtr save = &pI830->SavedReg;
DPRINTF(PFX, "SaveHWOperatingState\n");
return;
}
static void
RestoreHWOperatingState(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
I830RegPtr save = &pI830->SavedReg;
DPRINTF(PFX, "RestoreHWOperatingState\n");
return;
}
#endif
static void
I830BIOSLeaveVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "Leave VT\n");
#ifdef XF86DRI
if (pI830->directRenderingOpen) {
DPRINTF(PFX, "calling dri lock\n");
DRILock(screenInfo.screens[scrnIndex], 0);
pI830->LockHeld = 1;
}
#endif
#if SAVERESTORE_HWSTATE
if (!pI830->closing)
SaveHWOperatingState(pScrn);
#endif
ResetState(pScrn, TRUE);
RestoreHWState(pScrn);
RestoreBIOSMemSize(pScrn);
I830UnbindGARTMemory(pScrn);
if (pI830->AccelInfoRec)
pI830->AccelInfoRec->NeedToSync = FALSE;
}
static Bool
I830BIOSEnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "Enter VT\n");
if (!I830BindGARTMemory(pScrn))
return FALSE;
CheckInheritedState(pScrn);
if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
if (pI830->SaveGeneration != serverGeneration) {
pI830->SaveGeneration = serverGeneration;
SaveHWState(pScrn);
}
ResetState(pScrn, FALSE);
SetHWOperatingState(pScrn);
#if 1
memset(pI830->FbBase + pScrn->fbOffset, 0,
pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
#endif
if (!I830VESASetMode(pScrn, pScrn->currentMode))
return FALSE;
#ifdef I830_XV
I830VideoSwitchModeAfter(pScrn, pScrn->currentMode);
#endif
ResetState(pScrn, TRUE);
SetHWOperatingState(pScrn);
pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
#if SAVERESTORE_HWSTATE
RestoreHWOperatingState(pScrn);
#endif
#ifdef XF86DRI
if (pI830->directRenderingEnabled) {
if (!pI830->starting) {
I830EmitInvarientState(pScrn);
I830RefreshRing(pScrn);
I830Sync(pScrn);
DO_RING_IDLE();
DPRINTF(PFX, "calling dri unlock\n");
DRIUnlock(screenInfo.screens[scrnIndex]);
}
pI830->LockHeld = 0;
}
#endif
return TRUE;
}
static Bool
I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
int _head;
int _tail;
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I830Ptr pI830 = I830PTR(pScrn);
int ret = TRUE;
DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
if (!pI830->noAccel && (1 || IS_845G(pI830))) {
do {
_head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
_tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK;
DELAY(1000);
} while (_head != _tail);
}
#ifndef BINDUNBIND
#define BINDUNBIND 0
#endif
#if BINDUNBIND
I830UnbindGARTMemory(pScrn);
#endif
#ifdef I830_XV
I830VideoSwitchModeBefore(pScrn, mode);
#endif
if (!I830VESASetMode(pScrn, mode))
ret = FALSE;
#ifdef I830_XV
I830VideoSwitchModeAfter(pScrn, mode);
#endif
#if BINDUNBIND
I830BindGARTMemory(pScrn);
#endif
return ret;
}
static Bool
I830BIOSSaveScreen(ScreenPtr pScreen, int mode)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
Bool on = xf86IsUnblank(mode);
CARD32 temp, ctrl, base, i;
DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
if (pScrn->vtSema) {
for (i = 0; i < MAX_DISPLAY_PIPES; i++) {
if (i == 0) {
ctrl = DSPACNTR;
base = DSPABASE;
} else {
ctrl = DSPBCNTR;
base = DSPBADDR;
}
if (pI830->planeEnabled[i]) {
temp = INREG(ctrl);
if (on)
temp |= DISPLAY_PLANE_ENABLE;
else
temp &= ~DISPLAY_PLANE_ENABLE;
OUTREG(ctrl, temp);
temp = INREG(base);
OUTREG(base, temp);
}
}
if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
if (on)
pI830->CursorInfoRec->ShowCursor(pScrn);
else
pI830->CursorInfoRec->HideCursor(pScrn);
pI830->cursorOn = TRUE;
}
}
return TRUE;
}
static void
I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
int flags)
{
I830Ptr pI830 = I830PTR(pScrn);
vbeInfoPtr pVbe = pI830->pVbe;
if (xf86LoaderCheckSymbol("VBEDPMSSet")) {
VBEDPMSSet(pVbe, PowerManagementMode);
} else {
pVbe->pInt10->num = 0x10;
pVbe->pInt10->ax = 0x4f10;
pVbe->pInt10->bx = 0x01;
switch (PowerManagementMode) {
case DPMSModeOn:
break;
case DPMSModeStandby:
pVbe->pInt10->bx |= 0x0100;
break;
case DPMSModeSuspend:
pVbe->pInt10->bx |= 0x0200;
break;
case DPMSModeOff:
pVbe->pInt10->bx |= 0x0400;
break;
}
xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
}
}
static Bool
I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I830Ptr pI830 = I830PTR(pScrn);
XAAInfoRecPtr infoPtr = pI830->AccelInfoRec;
pI830->closing = TRUE;
#ifdef XF86DRI
if (pI830->directRenderingOpen) {
pI830->directRenderingOpen = FALSE;
I830DRICloseScreen(pScreen);
}
#endif
if (pScrn->vtSema == TRUE) {
I830BIOSLeaveVT(scrnIndex, 0);
}
DPRINTF(PFX, "\nUnmapping memory\n");
I830UnmapMem(pScrn);
vgaHWUnmapMem(pScrn);
if (pI830->ScanlineColorExpandBuffers) {
xfree(pI830->ScanlineColorExpandBuffers);
pI830->ScanlineColorExpandBuffers = 0;
}
if (infoPtr) {
if (infoPtr->ScanlineColorExpandBuffers)
xfree(infoPtr->ScanlineColorExpandBuffers);
XAADestroyInfoRec(infoPtr);
pI830->AccelInfoRec = NULL;
}
if (pI830->CursorInfoRec) {
xf86DestroyCursorInfoRec(pI830->CursorInfoRec);
pI830->CursorInfoRec = 0;
}
xf86GARTCloseScreen(scrnIndex);
pScrn->vtSema = FALSE;
pI830->closing = FALSE;
pScreen->CloseScreen = pI830->CloseScreen;
return (*pScreen->CloseScreen) (scrnIndex, pScreen);
}
static ModeStatus
I830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
{
if (mode->Flags & V_INTERLACE) {
if (verbose) {
xf86DrvMsg(scrnIndex, X_PROBED,
"Removing interlaced mode \"%s\"\n", mode->name);
}
return MODE_BAD;
}
return MODE_OK;
}
#ifndef SUSPEND_SLEEP
#define SUSPEND_SLEEP 0
#endif
#ifndef RESUME_SLEEP
#define RESUME_SLEEP 0
#endif
static Bool
I830PMEvent(int scrnIndex, pmEvent event, Bool undo)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
I830Ptr pI830 = I830PTR(pScrn);
DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo));
switch(event) {
case XF86_APM_SYS_SUSPEND:
case XF86_APM_CRITICAL_SUSPEND:
case XF86_APM_USER_SUSPEND:
case XF86_APM_SYS_STANDBY:
case XF86_APM_USER_STANDBY:
if (!undo && !pI830->suspended) {
pScrn->LeaveVT(scrnIndex, 0);
pI830->suspended = TRUE;
sleep(SUSPEND_SLEEP);
} else if (undo && pI830->suspended) {
sleep(RESUME_SLEEP);
pScrn->EnterVT(scrnIndex, 0);
pI830->suspended = FALSE;
}
break;
case XF86_APM_STANDBY_RESUME:
case XF86_APM_NORMAL_RESUME:
case XF86_APM_CRITICAL_RESUME:
if (pI830->suspended) {
sleep(RESUME_SLEEP);
pScrn->EnterVT(scrnIndex, 0);
pI830->suspended = FALSE;
SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
}
break;
default:
ErrorF("I830PMEvent: received APM event %d\n", event);
}
return TRUE;
}
void
I830InitpScrn(ScrnInfoPtr pScrn)
{
pScrn->PreInit = I830BIOSPreInit;
pScrn->ScreenInit = I830BIOSScreenInit;
pScrn->SwitchMode = I830BIOSSwitchMode;
pScrn->AdjustFrame = I830BIOSAdjustFrame;
pScrn->EnterVT = I830BIOSEnterVT;
pScrn->LeaveVT = I830BIOSLeaveVT;
pScrn->FreeScreen = I830BIOSFreeScreen;
pScrn->ValidMode = I830ValidMode;
pScrn->PMEvent = I830PMEvent;
}