diff options
Diffstat (limited to 'src/mga_dacG.c')
-rw-r--r-- | src/mga_dacG.c | 185 |
1 files changed, 160 insertions, 25 deletions
diff --git a/src/mga_dacG.c b/src/mga_dacG.c index 0a3a7e2..4dc93e4 100644 --- a/src/mga_dacG.c +++ b/src/mga_dacG.c @@ -26,6 +26,7 @@ #include "mga_reg.h" #include "mga.h" #include "mga_macros.h" +#include "mga_maven.h" #include "xf86DDC.h" @@ -1020,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) @@ -1032,19 +1042,19 @@ 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) { ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; MGAPtr pMga = MGAPTR(pScrn); @@ -1053,8 +1063,8 @@ MGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data) /* 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 @@ -1063,26 +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) { 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) @@ -1090,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->I2C = I2CPtr; + pMga->DDC_Bus1 = I2CPtr; - I2CPtr->BusName = "DDC"; - I2CPtr->scrnIndex = pScrn->scrnIndex; - I2CPtr->I2CPutBits = MGAG_I2CPutBits; - I2CPtr->I2CGetBits = MGAG_I2CGetBits; - I2CPtr->AcknTimeout = 5; + I2CPtr->BusName = "DDC P1"; + I2CPtr->scrnIndex = pScrn->scrnIndex; + I2CPtr->I2CPutBits = MGAG_DDC_P1_I2CPutBits; + I2CPtr->I2CGetBits = MGAG_DDC_P1_I2CGetBits; + I2CPtr->AcknTimeout = 5; - if (!xf86I2CBusInit(I2CPtr)) { - return FALSE; + 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 (failed) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MGA-TVO I2C device!\n"); + pMga->Maven = NULL; + pMga->Maven_Version = 0; + } + } + } + return TRUE; } @@ -1196,7 +1331,7 @@ void MGAGSetupFuncs(ScrnInfoPtr pScrn) pMga->ModeInit = MGAGInit; pMga->ddc1Read = MGAG_ddc1Read; /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ - pMga->DDC1SetSpeed = vgaHWddc1SetSpeed; + pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); pMga->i2cInit = MGAG_i2cInit; } |