diff options
author | Alex Deucher <agd5f@yahoo.com> | 2004-07-27 02:50:41 +0000 |
---|---|---|
committer | Alex Deucher <agd5f@yahoo.com> | 2004-07-27 02:50:41 +0000 |
commit | 9ae7f9446d049a1fad550f5f681bc557de158c10 (patch) | |
tree | 07008f97e27c681bdbe3a537a7e49db105b90ce5 | |
parent | 8b030a847771f6b34bf38913eb6b53543f320f29 (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.h | 44 | ||||
-rw-r--r-- | src/mga_dac3026.c | 19 | ||||
-rw-r--r-- | src/mga_dacG.c | 221 | ||||
-rw-r--r-- | src/mga_driver.c | 163 |
4 files changed, 345 insertions, 102 deletions
@@ -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); + } } |