summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <agd5f@yahoo.com>2004-07-27 02:50:41 +0000
committerAlex Deucher <agd5f@yahoo.com>2004-07-27 02:50:41 +0000
commit9ae7f9446d049a1fad550f5f681bc557de158c10 (patch)
tree07008f97e27c681bdbe3a537a7e49db105b90ce5
parent8b030a847771f6b34bf38913eb6b53543f320f29 (diff)
- enable maven support for TV detection, DPMS, and DDC on crtc2 on G400
(Ryan Underwood) (http://bugs.xfree86.org/show_bug.cgi?id=1098) - expose I2CStart; needed for mga maven support (Ryan Underwood)
-rw-r--r--src/mga.h44
-rw-r--r--src/mga_dac3026.c19
-rw-r--r--src/mga_dacG.c221
-rw-r--r--src/mga_driver.c163
4 files changed, 345 insertions, 102 deletions
diff --git a/src/mga.h b/src/mga.h
index b61c501..4823c63 100644
--- a/src/mga.h
+++ b/src/mga.h
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga.h,v 1.86 2003/04/24 20:05:34 eich Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga.h,v 1.87tsi Exp $ */
/*
* MGA Millennium (MGA2064W) functions
*
@@ -99,18 +99,23 @@ typedef enum {
#define OUTREG16(addr, val) MMIO_OUT16(pMga->IOBase, addr, val)
#define OUTREG(addr, val) MMIO_OUT32(pMga->IOBase, addr, val)
#else /* !EXTRADEBUG */
-CARD8 dbg_inreg8(ScrnInfoPtr,int,int);
-CARD16 dbg_inreg16(ScrnInfoPtr,int,int);
-CARD32 dbg_inreg32(ScrnInfoPtr,int,int);
-void dbg_outreg8(ScrnInfoPtr,int,int);
-void dbg_outreg16(ScrnInfoPtr,int,int);
-void dbg_outreg32(ScrnInfoPtr,int,int);
-#define INREG8(addr) dbg_inreg8(pScrn,addr,1)
-#define INREG16(addr) dbg_inreg16(pScrn,addr,1)
-#define INREG(addr) dbg_inreg32(pScrn,addr,1)
-#define OUTREG8(addr,val) dbg_outreg8(pScrn,addr,val)
-#define OUTREG16(addr,val) dbg_outreg16(pScrn,addr,val)
-#define OUTREG(addr,val) dbg_outreg32(pScrn,addr,val)
+CARD8 MGAdbg_inreg8(ScrnInfoPtr, int, int, char*);
+CARD16 MGAdbg_inreg16(ScrnInfoPtr, int, int, char*);
+CARD32 MGAdbg_inreg32(ScrnInfoPtr, int, int, char*);
+void MGAdbg_outreg8(ScrnInfoPtr, int, int, char*);
+void MGAdbg_outreg16(ScrnInfoPtr, int,int, char*);
+void MGAdbg_outreg32(ScrnInfoPtr, int,int, char*);
+#ifndef __GNUC__
+# define MGA_STRINGIZE(x) #x
+# define MGA_STRINGIFY(x) MGA_STRINGIZE(x)
+# define __FUNCTION__ MGA_STRINGIFY(__FILE__) ", line " MGA_STRINGIFY(__LINE__)
+#endif
+#define INREG8(addr) MGAdbg_inreg8(pScrn, addr, 1, __FUNCTION__)
+#define INREG16(addr) MGAdbg_inreg16(pScrn, addr, 1, __FUNCTION__)
+#define INREG(addr) MGAdbg_inreg32(pScrn, addr, 1, __FUNCTION__)
+#define OUTREG8(addr,val) MGAdbg_outreg8(pScrn, addr, val, __FUNCTION__)
+#define OUTREG16(addr,val) MGAdbg_outreg16(pScrn, addr, val, __FUNCTION__)
+#define OUTREG(addr,val) MGAdbg_outreg32(pScrn, addr, val, __FUNCTION__)
#endif /* EXTRADEBUG */
/*
@@ -212,6 +217,7 @@ typedef struct {
MessageType MemClkFrom;
Bool SetMemClk;
void (*LoadPalette)(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
+ void (*RestorePalette)(ScrnInfoPtr, unsigned char *);
void (*PreInit)(ScrnInfoPtr);
void (*Save)(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
void (*Restore)(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
@@ -368,7 +374,13 @@ typedef struct {
unsigned int (*ddc1Read)(ScrnInfoPtr);
void (*DDC1SetSpeed)(ScrnInfoPtr, xf86ddcSpeed);
Bool (*i2cInit)(ScrnInfoPtr);
- I2CBusPtr I2C;
+ I2CBusPtr DDC_Bus1;
+ I2CBusPtr DDC_Bus2;
+ I2CBusPtr Maven_Bus;
+ I2CDevPtr Maven;
+ char Maven_Version;
+ Bool UseMaven;
+ Bool UseMavenPM;
Bool FBDev;
int colorKey;
int videoKey;
@@ -408,8 +420,10 @@ typedef struct {
#endif
XF86VideoAdaptorPtr adaptor;
Bool DualHeadEnabled;
+ Bool Crtc2IsTV;
Bool SecondCrtc;
Bool SecondOutput;
+
GDevPtr device;
/* The hardware's real SrcOrg */
int realSrcOrg;
@@ -569,6 +583,8 @@ Bool MgaInitDma(ScrnInfoPtr pScrn, int prim_size);
#endif
+Bool MGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val);
+
void MGACRTC2Set(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo);
void MGAEnableSecondOutPut(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo);
void MGACRTC2SetPitch(ScrnInfoPtr pSrcn, xMODEINFO *pModeInfo);
diff --git a/src/mga_dac3026.c b/src/mga_dac3026.c
index 220ef1a..e997eec 100644
--- a/src/mga_dac3026.c
+++ b/src/mga_dac3026.c
@@ -1,4 +1,4 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dac3026.c,v 1.56 2001/04/05 21:29:14 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dac3026.c,v 1.58tsi Exp $ */
/*
* Copyright 1994 by Robin Cutshaw <robin@XFree86.org>
*
@@ -277,16 +277,12 @@ MGATi3026CalcClock (
static void
MGATi3026SetMCLK( ScrnInfoPtr pScrn, long f_out )
{
- double f_pll;
int mclk_m, mclk_n, mclk_p;
int pclk_m, pclk_n, pclk_p;
int mclk_ctl;
MGAPtr pMga = MGAPTR(pScrn);
- f_pll = MGATi3026CalcClock(
- f_out, TI_MAX_MCLK_FREQ,
- & mclk_m, & mclk_n, & mclk_p
- );
+ MGATi3026CalcClock(f_out, TI_MAX_MCLK_FREQ, &mclk_m, &mclk_n, &mclk_p);
/* Save PCLK settings */
outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
@@ -988,7 +984,8 @@ MGA3026_ddc1Read(ScrnInfoPtr pScrn)
static void
MGA3026_I2CGetBits(I2CBusPtr b, int *clock, int *data)
{
- MGAPtr pMga = MGAPTR(xf86Screens[b->scrnIndex]);
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ MGAPtr pMga = MGAPTR(pScrn);
unsigned char val;
/* Get the result. */
@@ -1009,7 +1006,8 @@ MGA3026_I2CGetBits(I2CBusPtr b, int *clock, int *data)
static void
MGA3026_I2CPutBits(I2CBusPtr b, int clock, int data)
{
- MGAPtr pMga = MGAPTR(xf86Screens[b->scrnIndex]);
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ MGAPtr pMga = MGAPTR(pScrn);
unsigned char val,drv;
/* Write the values */
@@ -1035,7 +1033,7 @@ MGA3026_i2cInit(ScrnInfoPtr pScrn)
I2CPtr = xf86CreateI2CBusRec();
if(!I2CPtr) return FALSE;
- pMga->I2C = I2CPtr;
+ pMga->DDC_Bus1 = I2CPtr;
I2CPtr->BusName = "DDC";
I2CPtr->scrnIndex = pScrn->scrnIndex;
@@ -1079,7 +1077,8 @@ MGA3026RamdacInit(ScrnInfoPtr pScrn)
HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
MGAdac->LoadPalette = MGA3026LoadPalette;
-
+ MGAdac->RestorePalette = MGA3026RestorePalette;
+
MGAdac->ClockFrom = X_PROBED;
if ( pMga->Chipset == PCI_CHIP_MGA2064 && pMga->Bios2.PinID == 0 )
{
diff --git a/src/mga_dacG.c b/src/mga_dacG.c
index 00e6ce0..7496020 100644
--- a/src/mga_dacG.c
+++ b/src/mga_dacG.c
@@ -2,7 +2,7 @@
* MGA-1064, MGA-G100, MGA-G200, MGA-G400, MGA-G550 RAMDAC driver
*/
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dacG.c,v 1.52 2003/04/24 20:05:34 eich Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dacG.c,v 1.54tsi Exp $ */
/*
* This is a first cut at a non-accelerated version to work with the
@@ -26,6 +26,7 @@
#include "mga_reg.h"
#include "mga.h"
#include "mga_macros.h"
+#include "mga_maven.h"
#include "xf86DDC.h"
@@ -208,16 +209,13 @@ MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
/* Pixel clock values */
int m, n, p, s;
- /* The actual frequency output by the clock */
- double f_pll;
-
if(MGAISGx50(pMga)) {
pReg->Clock = f_out;
return;
}
/* Do the calculations for m, n, p and s */
- f_pll = MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
+ (void) MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
/* Values for the pixel clock PLL registers */
pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F;
@@ -247,7 +245,7 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
/* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0
};
- int i, weight555 = FALSE;
+ int i;
int hd, hs, he, ht, vd, vs, ve, vt, wd;
int BppShift;
MGAPtr pMga;
@@ -411,7 +409,6 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits;
if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5)
&& (pLayout->weight.blue == 5) ) {
- weight555 = TRUE;
pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits;
}
break;
@@ -552,6 +549,14 @@ MGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
MGACRTC2GetPitch(pScrn, &ModeInfo);
MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0);
}
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* Disable byte-swapping for big-endian architectures - the XFree
+ driver seems to like a little-endian framebuffer -ReneR */
+ /* pReg->Option |= 0x80000000; */
+ pReg->Option &= ~0x80000000;
+#endif
+
return(TRUE);
}
@@ -674,6 +679,14 @@ MGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
}
if(!pMga->SecondCrtc) {
+ /* Do not set the memory config for primary cards as it
+ should be correct already. Only on little endian architectures
+ since we need to modify the byteswap bit. -ReneR */
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ optionMask = OPTION1_MASK;
+#else
+ optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK;
+#endif
MGA_NOT_HAL(
/*
@@ -699,10 +712,6 @@ MGA_NOT_HAL(
outMGAdac(i, mgaReg->DacRegs[i]);
}
- /* Do not set the memory config for primary cards as it
- should be correct already */
- optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK;
-
if (!MGAISGx50(pMga)) {
/* restore pci_option register */
pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
@@ -943,6 +952,7 @@ MGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
MGAPtr pMga = MGAPTR(pScrn);
x += 64;
y += 64;
+
#ifdef USEMGAHAL
MGA_HAL(
x += pMga->HALGranularityOffX;
@@ -1011,10 +1021,19 @@ MGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs)
* which VGA line is connected to each DDC pin, so I've had to guess.
*
* DDC1 support only requires DDC_SDA_MASK,
- * DDC2 support reuqiers DDC_SDA_MASK and DDC_SCL_MASK
+ * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
+ *
+ * If we want DDC on second head (P2) then we must use DDC2 protocol (I2C)
+ *
+ * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to
+ * DDC data coming in on which videoport on the card
*/
-static const int DDC_SDA_MASK = 1 << 1;
-static const int DDC_SCL_MASK = 1 << 3;
+static const int DDC_P1_SDA_MASK = (1 << 1);
+static const int DDC_P1_SCL_MASK = (1 << 3);
+static const int DDC_P2_SDA_MASK = (1 << 0);
+static const int DDC_P2_SCL_MASK = (1 << 2);
+static const int MAVEN_SDA_MASK = (1 << 4);
+static const int MAVEN_SCL_MASK = (1 << 5);
static unsigned int
MGAG_ddc1Read(ScrnInfoPtr pScrn)
@@ -1023,28 +1042,29 @@ MGAG_ddc1Read(ScrnInfoPtr pScrn)
unsigned char val;
/* Define the SDA as an input */
- outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_SCL_MASK | DDC_SDA_MASK), 0);
+ outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_P1_SCL_MASK | DDC_P1_SDA_MASK), 0);
/* wait for Vsync */
while( INREG( MGAREG_Status ) & 0x08 );
while( ! (INREG( MGAREG_Status ) & 0x08) );
/* Get the result */
- val = (inMGAdac(MGA1064_GEN_IO_DATA) & DDC_SDA_MASK);
+ val = (inMGAdac(MGA1064_GEN_IO_DATA) & DDC_P1_SDA_MASK);
return val;
}
static void
-MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data, int my_scl_mask, int my_sda_mask)
{
- MGAPtr pMga = MGAPTR(xf86Screens[b->scrnIndex]);
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ MGAPtr pMga = MGAPTR(pScrn);
unsigned char val;
/* Get the result. */
val = inMGAdac(MGA1064_GEN_IO_DATA);
- *clock = (val & DDC_SCL_MASK) != 0;
- *data = (val & DDC_SDA_MASK) != 0;
+ *clock = (val & my_scl_mask) != 0;
+ *data = (val & my_sda_mask) != 0;
#ifdef DEBUG
ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data);
#endif
@@ -1053,25 +1073,59 @@ MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data)
/*
* ATTENTION! - the DATA and CLOCK lines need to be tri-stated when
* high. Therefore turn off output driver for the line to set line
- * to high. High signal is maintained by a 15k Ohm pll-up resistor.
+ * to high. High signal is maintained by a 15k Ohm pull-up resistor.
*/
static void
-MGAG_I2CPutBits(I2CBusPtr b, int clock, int data)
+MGAG_I2CPutBits(I2CBusPtr b, int clock, int data, int my_scl_mask, int my_sda_mask)
{
- MGAPtr pMga = MGAPTR(xf86Screens[b->scrnIndex]);
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ MGAPtr pMga = MGAPTR(pScrn);
unsigned char drv, val;
- val = (clock ? DDC_SCL_MASK : 0) | (data ? DDC_SDA_MASK : 0);
- drv = ((!clock) ? DDC_SCL_MASK : 0) | ((!data) ? DDC_SDA_MASK : 0);
+ val = (clock ? my_scl_mask : 0) | (data ? my_sda_mask : 0);
+ drv = ((!clock) ? my_scl_mask : 0) | ((!data) ? my_sda_mask : 0);
/* Write the values */
- outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_SCL_MASK | DDC_SDA_MASK) , drv);
- outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(DDC_SCL_MASK | DDC_SDA_MASK) , val);
+ outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(my_scl_mask | my_sda_mask) , drv);
+ outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(my_scl_mask | my_sda_mask) , val);
#ifdef DEBUG
ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val);
#endif
}
+/* FIXME, can we use some neater way besides these silly stubs? */
+
+static void
+MGAG_DDC_P1_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ MGAG_I2CPutBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK);
+}
+static void
+MGAG_DDC_P2_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ MGAG_I2CPutBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK);
+}
+static void
+MGAG_MAVEN_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+ MGAG_I2CPutBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK);
+}
+
+static void
+MGAG_DDC_P1_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ MGAG_I2CGetBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK);
+}
+static void
+MGAG_DDC_P2_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ MGAG_I2CGetBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK);
+}
+static void
+MGAG_MAVEN_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+ MGAG_I2CGetBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK);
+}
Bool
MGAG_i2cInit(ScrnInfoPtr pScrn)
@@ -1079,20 +1133,112 @@ MGAG_i2cInit(ScrnInfoPtr pScrn)
MGAPtr pMga = MGAPTR(pScrn);
I2CBusPtr I2CPtr;
- I2CPtr = xf86CreateI2CBusRec();
- if(!I2CPtr) return FALSE;
+ if (pMga->SecondCrtc == FALSE) {
+ I2CPtr = xf86CreateI2CBusRec();
+ if(!I2CPtr) return FALSE;
+
+ pMga->DDC_Bus1 = I2CPtr;
- pMga->I2C = I2CPtr;
+ I2CPtr->BusName = "DDC P1";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = MGAG_DDC_P1_I2CPutBits;
+ I2CPtr->I2CGetBits = MGAG_DDC_P1_I2CGetBits;
+ I2CPtr->AcknTimeout = 5;
- I2CPtr->BusName = "DDC";
- I2CPtr->scrnIndex = pScrn->scrnIndex;
- I2CPtr->I2CPutBits = MGAG_I2CPutBits;
- I2CPtr->I2CGetBits = MGAG_I2CGetBits;
- I2CPtr->AcknTimeout = 5;
+ if (!xf86I2CBusInit(I2CPtr)) {
+ xf86DestroyI2CBusRec(pMga->DDC_Bus1, TRUE, TRUE);
+ pMga->DDC_Bus1 = NULL;
+ return FALSE;
+ }
+ }
+ else {
+ /* We have a dual head setup on G-series, set up DDC #2. */
+ I2CPtr = xf86CreateI2CBusRec();
+ if(!I2CPtr) return FALSE;
+
+ pMga->DDC_Bus2 = I2CPtr;
+
+ I2CPtr->BusName = "DDC P2";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = MGAG_DDC_P2_I2CPutBits;
+ I2CPtr->I2CGetBits = MGAG_DDC_P2_I2CGetBits;
+ I2CPtr->AcknTimeout = 5;
+
+ if (!xf86I2CBusInit(I2CPtr)) {
+ xf86DestroyI2CBusRec(pMga->DDC_Bus2, TRUE, TRUE);
+ pMga->DDC_Bus2 = NULL;
+ }
+ else {
+ if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) { /* 0xA0 is DDC EEPROM address */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n");
+ pMga->Crtc2IsTV = TRUE; /* assume for now. We need to fix HAL interactions. */
+ }
+ }
+
+ /* Then try to set up MAVEN bus. */
+
+ I2CPtr = xf86CreateI2CBusRec();
+ if(!I2CPtr) return FALSE;
+ pMga->Maven_Bus = I2CPtr;
+
+ I2CPtr->BusName = "MAVEN";
+ I2CPtr->scrnIndex = pScrn->scrnIndex;
+ I2CPtr->I2CPutBits = MGAG_MAVEN_I2CPutBits;
+ I2CPtr->I2CGetBits = MGAG_MAVEN_I2CGetBits;
+ I2CPtr->StartTimeout = 5;
+
+ if (!xf86I2CBusInit(I2CPtr)) {
+ xf86DestroyI2CBusRec(pMga->Maven_Bus, TRUE, TRUE);
+ pMga->Maven_Bus = NULL;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MAVEN I2C bus!\n");
+ }
+ else {
+ Bool failed = FALSE;
+ /* Try to detect the MAVEN. */
+ if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ) == TRUE) {
+ I2CDevPtr dp = xf86CreateI2CDevRec();
+ if (dp) {
+ I2CByte maven_ver;
+
+ pMga->Maven = dp;
+ dp->DevName = "MGA-TVO";
+ dp->SlaveAddr = MAVEN_WRITE;
+ dp->pI2CBus = pMga->Maven_Bus;
+ if (!xf86I2CDevInit(dp)) {
+ xf86DestroyI2CDevRec(dp, TRUE);
+ pMga->Maven = NULL;
+ failed = TRUE;
+ }
+ if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) {
+ if (maven_ver < 0x14) { /* heuristic stolen from matroxfb */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-B detected (0x%x)\n", maven_ver);
+ pMga->Maven_Version = 'B';
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-C detected (0x%x)\n", maven_ver);
+ pMga->Maven_Version = 'C';
+ }
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n");
+ }
+ }
+ else {
+ failed = TRUE;
+ }
+ }
+ else {
+ failed = TRUE;
+ }
- if (!xf86I2CBusInit(I2CPtr)) {
- return FALSE;
+ if (failed) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MGA-TVO I2C device!\n");
+ pMga->Maven = NULL;
+ pMga->Maven_Version = 0;
+ }
+ }
}
+
return TRUE;
}
@@ -1131,6 +1277,7 @@ MGAGRamdacInit(ScrnInfoPtr pScrn)
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
MGAdac->LoadPalette = MGAGLoadPalette;
+ MGAdac->RestorePalette = MGAGRestorePalette;
if ( pMga->Bios2.PinID && pMga->Bios2.PclkMax != 0xFF )
{
diff --git a/src/mga_driver.c b/src/mga_driver.c
index 829cb91..b3126f3 100644
--- a/src/mga_driver.c
+++ b/src/mga_driver.c
@@ -88,6 +88,7 @@
#include "mga_reg.h"
#include "mga.h"
#include "mga_macros.h"
+#include "mga_maven.h"
#include "xaa.h"
#include "xf86cmap.h"
@@ -996,9 +997,8 @@ MGAdoDDC(ScrnInfoPtr pScrn)
} else {
/* ddc module not found, we can do without it */
pMga->ddc1Read = NULL;
-
- /* Without DDC, we have no use for the I2C bus */
- pMga->i2cInit = NULL;
+ pMga->DDC_Bus1 = NULL;
+ pMga->DDC_Bus2 = NULL;
return NULL;
}
} else
@@ -1013,7 +1013,8 @@ MGAdoDDC(ScrnInfoPtr pScrn)
} else {
/* i2c module not found, we can do without it */
pMga->i2cInit = NULL;
- pMga->I2C = NULL;
+ pMga->DDC_Bus1 = NULL;
+ pMga->DDC_Bus2 = NULL;
}
}
#endif /* MGAuseI2C */
@@ -1046,47 +1047,58 @@ MGAdoDDC(ScrnInfoPtr pScrn)
/* It is now safe to talk to the card */
#if MGAuseI2C
- /* Initialize I2C bus - used by DDC if available */
+ /* Initialize I2C buses - used by DDC if available */
if (pMga->i2cInit) {
pMga->i2cInit(pScrn);
}
- /* Read and output monitor info using DDC2 over I2C bus */
- if (pMga->I2C) {
- MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pMga->I2C);
+
+ /* DDC for second head... */
+ if (pMga->SecondCrtc && pMga->DDC_Bus2) {
+ MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pMga->DDC_Bus2);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n",
(void *)MonInfo);
xf86PrintEDID(MonInfo);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n");
- }
- if (!MonInfo)
-#endif /* MGAuseI2C */
- /* Read and output monitor info using DDC1 */
- if (pMga->ddc1Read && pMga->DDC1SetSpeed) {
- MonInfo = xf86DoEDID_DDC1(pScrn->scrnIndex,
- pMga->DDC1SetSpeed,
- pMga->ddc1Read ) ;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n",
- (void *)MonInfo);
- xf86PrintEDID( MonInfo );
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor info\n");
- }
- if (!MonInfo){
- vbeInfoPtr pVbe;
- if (xf86LoadSubModule(pScrn, "vbe")) {
- pVbe = VBEInit(NULL,pMga->pEnt->index);
- MonInfo = vbeDoEDID(pVbe, NULL);
- vbeFree(pVbe);
-
- if (MonInfo){
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBE DDC Monitor info: %p\n",
- (void *)MonInfo);
- xf86PrintEDID( MonInfo );
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of VBE DDC Monitor info\n\n");
- }
- }
+ xf86SetDDCproperties(pScrn, MonInfo);
+ return MonInfo;
}
-
+ else {
+ /* Its the first head... */
+ if (pMga->DDC_Bus1) {
+ MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pMga->DDC_Bus1);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n", MonInfo);
+ xf86PrintEDID(MonInfo);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n");
+ }
+ if (!MonInfo)
+#endif /* MGAuseI2C */
+ /* Read and output monitor info using DDC1 */
+ if (pMga->ddc1Read && pMga->DDC1SetSpeed) {
+ MonInfo = xf86DoEDID_DDC1(pScrn->scrnIndex,
+ pMga->DDC1SetSpeed,
+ pMga->ddc1Read ) ;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", MonInfo);
+ xf86PrintEDID( MonInfo );
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor info\n");
+ }
+ if (!MonInfo){
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL,pMga->pEnt->index);
+ MonInfo = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+
+ if (MonInfo){
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VBE DDC Monitor info: %p\n", MonInfo);
+ xf86PrintEDID( MonInfo );
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of VBE DDC Monitor info\n\n");
+ }
+ }
+ }
+#if MGAuseI2C
+ }
+#endif
/* Restore previous state and unmap MGA memory and MMIO areas */
MGARestore(pScrn);
MGAUnmapMem(pScrn);
@@ -1170,6 +1182,30 @@ MGAProbeDDC(ScrnInfoPtr pScrn, int index)
}
}
+Bool
+MGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ if (!pMga->Maven) return FALSE;
+
+ /* FIXME: Using private interfaces for the moment until a more
+ * flexible xf86I2CWriteRead() variant shows up for us
+ *
+ * MAVEN does _not_ like a start bit in the middle of its transaction
+ * MAVEN does _not_ like ACK at the end of the transaction
+ */
+
+ if (!pMga->Maven_Bus->I2CStart(pMga->Maven_Bus, pMga->Maven->ByteTimeout)) return FALSE;
+ if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, MAVEN_READ)) return FALSE;
+ if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, reg)) return FALSE;
+ pMga->Maven_Bus->I2CStop(pMga->Maven);
+ if (!pMga->Maven_Bus->I2CGetByte(pMga->Maven, val, 0)) return FALSE;
+ pMga->Maven_Bus->I2CStop(pMga->Maven);
+
+ return TRUE;
+}
+
/* Mandatory */
static Bool
MGAPreInit(ScrnInfoPtr pScrn, int flags)
@@ -3974,6 +4010,8 @@ MGASaveScreen(ScreenPtr pScreen, int mode)
* MGADisplayPowerManagementSet --
*
* Sets VESA Display Power Management Signaling (DPMS) Mode.
+ *
+ * XXX This needs fixing for sync-on-green!
*/
void
MGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
@@ -4020,12 +4058,55 @@ MGADisplayPowerManagementSetCrtc2(ScrnInfoPtr pScrn, int PowerManagementMode,
int flags)
{
MGAPtr pMga = MGAPTR(pScrn);
- CARD32 crtc2 = 0;
+ CARD32 val = INREG(MGAREG_C2CTL);
+
+ if (PowerManagementMode==DPMSModeOn) {
+ /* Enable CRTC2 */
+ val |= 0x1;
+ val &= ~(0x8);
+ OUTREG(MGAREG_C2CTL, val);
+ /* Restore normal MAVEN values */
+ if (pMga->Maven) {
+ /* if TV MODE -- for later implementation
+ MAVW(MONEN, 0xb3);
+ MAVW(MONSET, 0x20);
+ MAVW(OUTMODE, 0x08); output: SVideo/Composite
+ MAVW(STABLE, 0x02); makes picture stable?
+ fixme? linux uses 0x14...
+ MAVW(TEST, (MAVR(TEST) & 0x10));
+
+ */
+ /* else monitor mode */
+
+ xf86I2CWriteByte(pMga->Maven, MGAMAV_MONEN, 0xb2);
+ /* must be set to this in monitor mode */
+ xf86I2CWriteByte(pMga->Maven, MGAMAV_MONSET, 0x20);
+ /* output: monitor mode */
+ xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x03);
+ /* makes picture stable? */
+ xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x22);
+ /* turn off test signal */
+ xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x00);
+ }
+ }
+ else {
+ /* Disable CRTC2 video */
+ val |= 0x8;
+ val &= ~(0x1);
+ OUTREG(MGAREG_C2CTL, val);
+
+ /* Disable MAVEN display */
+ if (pMga->Maven) {
+ /* In order to blank the 2nd display, we must set some MAVEN registers.
+ * It seems that not always the same values work on different hardware so
+ * we try a few different (possibly redundant) ones. */
+ /* xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x6a); */
+ /* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x03); */
+ /* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x10); */
+ xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x80);
+ }
- if (PowerManagementMode != DPMSModeOn)
- crtc2 = 0x8; /* c2pixclkdis */
- crtc2 |= INREG(MGAREG_C2CTL) & ~0x8;
- OUTREG(MGAREG_C2CTL, crtc2);
+ }
}