Haiku S3 Virge driver adapted from the X.org Virge driver.
Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
Copyright 2007-2008 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2007-2008
*/
#include "accel.h"
#include "virge.h"
static void
VirgeWaitFifoGX2(uint32 slots )
{
while (((ReadReg32(SUBSYS_STAT_REG) >> 9) & 0x60) < slots) {}
}
static void
VirgeWaitFifoMain(uint32 slots )
{
while (((ReadReg32(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots) {}
}
static void
VirgeWaitIdleEmpty()
{
if(gInfo.sharedInfo->chipType == S3_TRIO_3D)
while ((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000);
else
while ((IN_SUBSYS_STAT() & 0x3f00) != 0x3000);
}
static bool
Virge_GetColorSpaceParams(int colorSpace, uint32& bitsPerPixel, uint32& maxPixelClock)
{
switch (colorSpace) {
case B_RGB16:
bitsPerPixel = 16;
maxPixelClock = 270000;
break;
case B_CMAP8:
bitsPerPixel = 8;
maxPixelClock = 270000;
break;
default:
TRACE("Unsupported color space: 0x%X\n", colorSpace);
return false;
}
return true;
}
status_t
Virge_Init(void)
{
TRACE("Virge_Init()\n");
SharedInfo& si = *gInfo.sharedInfo;
WritePIO_8(VGA_ENABLE, ReadPIO_8(VGA_ENABLE) | 0x01);
WritePIO_8(MISC_OUT_W, ReadPIO_8(MISC_OUT_R) | 0x01);
WritePIO_8(CRTC_INDEX, 0x59);
WritePIO_8(CRTC_DATA, (uint8)((uint32)(si.videoMemPCI) >> 24));
WritePIO_8(CRTC_INDEX, 0x5A);
WritePIO_8(CRTC_DATA, (uint8)((uint32)(si.videoMemPCI) >> 16));
WritePIO_8(CRTC_INDEX, 0x53);
WritePIO_8(CRTC_DATA, ReadPIO_8(CRTC_DATA) | 0x8);
if (si.chipType == S3_TRIO_3D)
WriteCrtcReg(0x40, 0x01, 0x01);
uint8 config1 = ReadCrtcReg(0x36);
uint8 config2 = ReadCrtcReg(0x37);
int ramOffScreenMB = 0;
int ramSizeMB = 0;
if (si.chipType == S3_VIRGE_VX) {
switch ((config2 & 0x60) >> 5) {
case 1:
ramOffScreenMB = 4;
break;
case 2:
ramOffScreenMB = 2;
break;
}
switch ((config1 & 0x60) >> 5) {
case 0:
ramSizeMB = 2;
break;
case 1:
ramSizeMB = 4;
break;
case 2:
ramSizeMB = 6;
break;
case 3:
ramSizeMB = 8;
break;
}
ramSizeMB -= ramOffScreenMB;
} else if (si.chipType == S3_TRIO_3D_2X) {
switch ((config1 & 0xE0) >> 5) {
case 0:
ramSizeMB = 4;
ramOffScreenMB = 4;
break;
case 1:
TRACE("Undefined video memory size on S3 Trio 3D/2X\n");
case 2:
ramSizeMB = 4;
break;
case 6:
ramSizeMB = 2;
break;
}
} else if (si.chipType == S3_TRIO_3D) {
switch ((config1 & 0xE0) >> 5) {
case 0:
case 2:
ramSizeMB = 4;
break;
case 4:
ramSizeMB = 2;
break;
}
} else if (si.chipType == S3_VIRGE_GX2 || S3_VIRGE_MX_SERIES(si.chipType)) {
switch ((config1 & 0xC0) >> 6) {
case 1:
ramSizeMB = 4;
break;
case 3:
ramSizeMB = 2;
break;
}
} else {
switch ((config1 & 0xE0) >> 5) {
case 0:
ramSizeMB = 4;
break;
case 4:
ramSizeMB = 2;
break;
case 6:
ramSizeMB = 1;
break;
}
}
TRACE("usable memory: %d MB, off-screen memory: %d MB\n", ramSizeMB, ramOffScreenMB);
if (ramSizeMB <= 0)
return B_ERROR;
si.videoMemSize = ramSizeMB * 1024 * 1024;
si.cursorOffset = si.videoMemSize - CURSOR_BYTES;
si.frameBufferOffset = 0;
si.maxFrameBufferSize = si.videoMemSize - CURSOR_BYTES;
WriteSeqReg(0x08, 0x06);
uint8 m = ReadSeqReg(0x11) & 0x7f;
uint8 n = ReadSeqReg(0x10);
uint8 n1 = n & 0x1f;
uint8 n2 = (n >> 5) & 0x03;
si.mclk = ((1431818 * (m + 2)) / (n1 + 2) / (1 << n2) + 50) / 100;
TRACE("Detected current MCLK value of %1.3f MHz\n", si.mclk / 1000.0);
if (S3_VIRGE_MX_SERIES(si.chipType)) {
si.displayType = ((ReadSeqReg(0x31) & 0x10) ? MT_LCD : MT_CRT);
si.panelX = (ReadSeqReg(0x61) + ((ReadSeqReg(0x66) & 0x02) << 7) + 1) * 8;
si.panelY = ReadSeqReg(0x69) + ((ReadSeqReg(0x6e) & 0x70) << 4) + 1;
TRACE("%dx%d LCD panel detected %s\n", si.panelX, si.panelY,
si.displayType == MT_LCD ? "and active" : "but not active");
} else {
si.displayType = MT_CRT;
si.panelX = 0;
si.panelY = 0;
}
si.colorSpaces[0] = B_CMAP8;
si.colorSpaces[1] = B_RGB16;
si.colorSpaceCount = 2;
si.bDisableHdwCursor = false;
si.bDisableAccelDraw = false;
return CreateModeList(IsModeUsable, Virge_GetEdidInfo);
}
void
Virge_SetFunctionPointers(void)
{
if (S3_VIRGE_GX2_SERIES(gInfo.sharedInfo->chipType)) {
gInfo.WaitQueue = VirgeWaitFifoGX2;
} else {
gInfo.WaitQueue = VirgeWaitFifoMain;
}
gInfo.WaitIdleEmpty = VirgeWaitIdleEmpty;
gInfo.DPMSCapabilities = Virge_DPMSCapabilities;
gInfo.GetDPMSMode = Virge_GetDPMSMode;
gInfo.SetDPMSMode = Virge_SetDPMSMode;
gInfo.LoadCursorImage = Virge_LoadCursorImage;
gInfo.SetCursorPosition = Virge_SetCursorPosition;
gInfo.ShowCursor = Virge_ShowCursor;
gInfo.FillRectangle = Virge_FillRectangle;
gInfo.FillSpan = Virge_FillSpan;
gInfo.InvertRectangle = Virge_InvertRectangle;
gInfo.ScreenToScreenBlit = Virge_ScreenToScreenBlit;
gInfo.AdjustFrame = Virge_AdjustFrame;
gInfo.ChipInit = Virge_Init;
gInfo.GetColorSpaceParams = Virge_GetColorSpaceParams;
gInfo.SetDisplayMode = Virge_SetDisplayMode;
gInfo.SetIndexedColors = Virge_SetIndexedColors;
}