/*
* Copyright 1996-1997 David J. McKay
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
<jpaana@s2.org> */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "riva_include.h"
/*
* Override VGA I/O routines.
*/
static void RivaWriteCrtc(vgaHWPtr pVga, CARD8 index, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index);
VGA_WR08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET, value);
}
static CARD8 RivaReadCrtc(vgaHWPtr pVga, CARD8 index)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index);
return (VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_CRTC_DATA_OFFSET));
}
static void RivaWriteGr(vgaHWPtr pVga, CARD8 index, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PVIO, VGA_GRAPH_INDEX, index);
VGA_WR08(pRiva->riva.PVIO, VGA_GRAPH_DATA, value);
}
static CARD8 RivaReadGr(vgaHWPtr pVga, CARD8 index)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PVIO, VGA_GRAPH_INDEX, index);
return (VGA_RD08(pRiva->riva.PVIO, VGA_GRAPH_DATA));
}
static void RivaWriteSeq(vgaHWPtr pVga, CARD8 index, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PVIO, VGA_SEQ_INDEX, index);
VGA_WR08(pRiva->riva.PVIO, VGA_SEQ_DATA, value);
}
static CARD8 RivaReadSeq(vgaHWPtr pVga, CARD8 index)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PVIO, VGA_SEQ_INDEX, index);
return (VGA_RD08(pRiva->riva.PVIO, VGA_SEQ_DATA));
}
static void RivaWriteAttr(vgaHWPtr pVga, CARD8 index, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
volatile CARD8 tmp;
tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
if (pVga->paletteEnabled)
index &= ~0x20;
else
index |= 0x20;
VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, index);
VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_DATA_W, value);
}
static CARD8 RivaReadAttr(vgaHWPtr pVga, CARD8 index)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
volatile CARD8 tmp;
tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
if (pVga->paletteEnabled)
index &= ~0x20;
else
index |= 0x20;
VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, index);
return (VGA_RD08(pRiva->riva.PCIO, VGA_ATTR_DATA_R));
}
static void RivaWriteMiscOut(vgaHWPtr pVga, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PVIO, VGA_MISC_OUT_W, value);
}
static CARD8 RivaReadMiscOut(vgaHWPtr pVga)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
return (VGA_RD08(pRiva->riva.PVIO, VGA_MISC_OUT_R));
}
static void RivaEnablePalette(vgaHWPtr pVga)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
volatile CARD8 tmp;
tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, 0x00);
pVga->paletteEnabled = TRUE;
}
static void RivaDisablePalette(vgaHWPtr pVga)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
volatile CARD8 tmp;
tmp = VGA_RD08(pRiva->riva.PCIO, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
VGA_WR08(pRiva->riva.PCIO, VGA_ATTR_INDEX, 0x20);
pVga->paletteEnabled = FALSE;
}
static void RivaWriteDacMask(vgaHWPtr pVga, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PDIO, VGA_DAC_MASK, value);
}
static CARD8 RivaReadDacMask(vgaHWPtr pVga)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
return (VGA_RD08(pRiva->riva.PDIO, VGA_DAC_MASK));
}
static void RivaWriteDacReadAddr(vgaHWPtr pVga, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PDIO, VGA_DAC_READ_ADDR, value);
}
static void RivaWriteDacWriteAddr(vgaHWPtr pVga, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PDIO, VGA_DAC_WRITE_ADDR, value);
}
static void RivaWriteDacData(vgaHWPtr pVga, CARD8 value)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
VGA_WR08(pRiva->riva.PDIO, VGA_DAC_DATA, value);
}
static CARD8 RivaReadDacData(vgaHWPtr pVga)
{
RivaPtr pRiva = (RivaPtr)pVga->MMIOBase;
return (VGA_RD08(pRiva->riva.PDIO, VGA_DAC_DATA));
}
static xf86MonPtr
RivaProbeDDC (ScrnInfoPtr pScrn)
{
RivaPtr pRiva = RivaPTR(pScrn);
xf86MonPtr MonInfo = NULL;
if(!pRiva->I2C) return NULL;
pRiva->DDCBase = 0x3e;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for EDID...\n");
#ifdef EDID_COMPLETE_RAWDATA
MonInfo = xf86DoEEDID(XF86_SCRN_ARG(pScrn), pRiva->I2C, TRUE);
#else
MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pRiva->I2C);
#endif
if (MonInfo) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
" ... found one\n");
xf86PrintEDID( MonInfo );
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
" ... none found\n");
}
return MonInfo;
}
void
Riva3Setup(ScrnInfoPtr pScrn)
{
RivaPtr pRiva = RivaPTR(pScrn);
vgaHWPtr pVga = VGAHWPTR(pScrn);
CARD32 regBase = pRiva->IOAddress;
CARD32 frameBase = pRiva->FbAddress;
xf86MonPtr monitor;
pRiva->Save = RivaDACSave;
pRiva->Restore = RivaDACRestore;
pRiva->ModeInit = RivaDACInit;
pRiva->Dac.LoadPalette = RivaDACLoadPalette;
/*
* Override VGA I/O routines.
*/
pVga->writeCrtc = RivaWriteCrtc;
pVga->readCrtc = RivaReadCrtc;
pVga->writeGr = RivaWriteGr;
pVga->readGr = RivaReadGr;
pVga->writeAttr = RivaWriteAttr;
pVga->readAttr = RivaReadAttr;
pVga->writeSeq = RivaWriteSeq;
pVga->readSeq = RivaReadSeq;
pVga->writeMiscOut = RivaWriteMiscOut;
pVga->readMiscOut = RivaReadMiscOut;
pVga->enablePalette = RivaEnablePalette;
pVga->disablePalette = RivaDisablePalette;
pVga->writeDacMask = RivaWriteDacMask;
pVga->readDacMask = RivaReadDacMask;
pVga->writeDacWriteAddr = RivaWriteDacWriteAddr;
pVga->writeDacReadAddr = RivaWriteDacReadAddr;
pVga->writeDacData = RivaWriteDacData;
pVga->readDacData = RivaReadDacData;
/*
* Note: There are different pointers to the CRTC/AR and GR/SEQ registers.
* Bastardize the intended uses of these to make it work.
*/
pVga->MMIOBase = (CARD8 *)pRiva;
pVga->MMIOOffset = 0;
/*
* No IRQ in use.
*/
pRiva->riva.EnableIRQ = 0;
pRiva->riva.IO = VGA_IOBASE_COLOR;
#if XSERVER_LIBPCIACCESS
#define MAP(ptr, offset, size) { \
void *tmp; \
pci_device_map_range(pRiva->PciInfo, (offset), (size), \
PCI_DEV_MAP_FLAG_WRITABLE, &tmp); \
pRiva->riva.ptr = tmp; \
}
#else
#define MAP(ptr, offset, size) \
pRiva->riva.ptr = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO | \
VIDMEM_READSIDEEFFECT, pRiva->PciTag, \
(offset), (size));
#endif
MAP(PRAMDAC, regBase + 0x00680000, 0x00003000);
MAP(PFB, regBase + 0x00100000, 0x00001000);
MAP(PFIFO, regBase + 0x00002000, 0x00002000);
MAP(PGRAPH, regBase + 0x00400000, 0x00002000);
MAP(PEXTDEV, regBase + 0x00101000, 0x00001000);
MAP(PTIMER, regBase + 0x00009000, 0x00001000);
MAP(PMC, regBase + 0x00000000, 0x00009000);
MAP(FIFO, regBase + 0x00800000, 0x00010000);
MAP(PRAMIN, frameBase+0x00C00000, 0x00008000);
/*
* These registers are read/write as 8 bit values. Probably have to map
* sparse on alpha.
*/
MAP(PCIO, regBase + 0x00601000, 0x00003000);
MAP(PDIO, regBase + 0x00681000, 0x00003000);
MAP(PVIO, regBase + 0x000C0000, 0x00001000);
#undef MAP
pRiva->riva.PCRTC = pRiva->riva.PGRAPH;
RivaGetConfig(pRiva);
pRiva->riva.LockUnlock(&pRiva->riva, 0);
RivaI2CInit(pScrn);
monitor = RivaProbeDDC(pScrn);
if(monitor)
xf86SetDDCproperties(pScrn, monitor);
pRiva->Dac.maxPixelClock = pRiva->riva.MaxVClockFreqKHz;
}