diff --git a/Makefile.am b/Makefile.am diff --git a/configure.ac b/configure.ac index 16b93e1..c36c8b0 100644 --- a/configure.ac +++ b/configure.ac @@ -218,5 +218,6 @@ XORG_CHECK_LINUXDOC AC_OUTPUT([ Makefile src/Makefile + src/sil164/Makefile man/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index f31c018..7818ddc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ # 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. - +SUBDIRS = sil164 # this is obnoxious: # -module lets us name the module exactly how we want # -avoid-version prevents gratuitous .0.0.0 version numbers on the end diff --git a/src/radeon.h b/src/radeon.h index 37ca67d..61c4fd7 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -819,6 +819,8 @@ typedef struct { CARD32 tv_dac_adj; + Bool extTMDS; + } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ diff --git a/src/radeon_display.c b/src/radeon_display.c index d661c17..381b3b2 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -47,6 +47,20 @@ #include "radeon_version.h" #include "radeon_mergedfb.h" +#include "i2c_vid.h" +#include "sil164/sil164.h" + +static const char *SIL164Symbols[] = { + "Sil164VidOutput", + NULL +}; + +RADEONDVORec radeon_dvo_drivers[] = { + { 0, "sil164", "SIL164VidOutput", (SIL164_ADDR_1<<1), SIL164Symbols, NULL, NULL, NULL, RADEON_GPIO_CRT2_DDC} +}; + +#define RADEON_NUM_DVO_DRIVERS (sizeof(radeon_dvo_drivers)/sizeof(RADEONDVORec)) + extern int getRADEONEntityIndex(void); const char *MonTypeName[7] = { @@ -201,10 +215,187 @@ Bool RADEONI2cInit(ScrnInfoPtr pScrn) info->pI2CBus->I2CGetBits = RADEONI2CGetBits; info->pI2CBus->AcknTimeout = 5; +#if 1 + info->pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + info->pI2CBus->StartTimeout = 550; + info->pI2CBus->BitTimeout = 40; + info->pI2CBus->ByteTimeout = 40; + info->pI2CBus->AcknTimeout = 40; +#endif + if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; return TRUE; } +Bool RADEONFindTMDSController(ScrnInfoPtr pScrn, int port) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONDVOPtr drv; + void *ret_ptr; + int i; + int DDCReg; + CARD32 tmpreg, fp2_gen_cntl; + +ErrorF("start RADEONFindTMDSController\n"); + + /* try messing with DVO before probing ??? */ + /* try with DVO off, try with DVO on */ +/* tmpreg = INREG(RADEON_FP2_GEN_CNTL); + fp2_gen_cntl = RADEON_FP2_ON | RADEON_FP2_DVO_EN | RADEON_FP2_DVO_RATE_SEL_DDR | + RADEON_FP2_PANEL_FORMAT | R200_FP2_SOURCE_SEL_CRTC2; + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);*/ + + for (i = 0; i < RADEON_NUM_DVO_DRIVERS; i++) { + drv = &radeon_dvo_drivers[i]; + + drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename); + + if (!drv->modhandle) + continue; + + xf86LoaderReqSymLists(drv->symbols, NULL); + + DDCReg = info->DDCReg; + info->DDCReg = drv->i2c_reg; + ret_ptr = NULL; + drv->vid_rec = LoaderSymbol(drv->fntablename); + if (drv->vid_rec) + ret_ptr = drv->vid_rec->Detect(info->pI2CBus, drv->address); + info->DDCReg = DDCReg; + if (ret_ptr) { + drv->devpriv = ret_ptr; + pRADEONEnt->PortInfo[port]->ExtChip = drv; + +ErrorF("RADEONFindTMDSController - TRUE\n"); + /*OUTREG(RADEON_FP2_GEN_CNTL, tmpreg);*/ + return TRUE; + } + xf86UnloadSubModule(drv->modhandle); + } + +ErrorF("RADEONFindTMDSController - FALSE\n"); + /*OUTREG(RADEON_FP2_GEN_CNTL, tmpreg);*/ + + return FALSE; +} + +void RADEONTMDSControllerDumpRegs(ScrnInfoPtr pScrn, RADEONConnector *pPort) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int DDCReg; + + DDCReg = info->DDCReg; + info->DDCReg = pPort->ExtChip->i2c_reg; + pPort->ExtChip->vid_rec->PrintRegs(pPort->ExtChip->devpriv); + info->DDCReg = DDCReg; + return; +} + + +void RADEONTMDSPowerSet(ScrnInfoPtr pScrn, RADEONConnector *pPort, Bool power) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int DDCReg; + + DDCReg = info->DDCReg; + info->DDCReg = pPort->ExtChip->i2c_reg; + pPort->ExtChip->vid_rec->PrintRegs(pPort->ExtChip->devpriv); + pPort->ExtChip->vid_rec->Power(pPort->ExtChip->devpriv, power); + info->DDCReg = DDCReg; + return; +} + +static void RADEONTMDSSaveRegs(ScrnInfoPtr pScrn, RADEONConnector *pPort) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int DDCReg; + + DDCReg = info->DDCReg; + info->DDCReg = pPort->ExtChip->i2c_reg; + pPort->ExtChip->vid_rec->PrintRegs(pPort->ExtChip->devpriv); + pPort->ExtChip->vid_rec->SaveRegs(pPort->ExtChip->devpriv); + info->DDCReg = DDCReg; + return; + +} + +static void RADEONTMDSProgramRegs(ScrnInfoPtr pScrn, RADEONConnector *pPort, DisplayModePtr mode) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int DDCReg; + + DDCReg = info->DDCReg; + info->DDCReg = pPort->ExtChip->i2c_reg; + pPort->ExtChip->vid_rec->PrintRegs(pPort->ExtChip->devpriv); + pPort->ExtChip->vid_rec->Mode(pPort->ExtChip->devpriv, mode); + info->DDCReg = DDCReg; + return; + +} + +static void RADEONTMDSRestoreRegs(ScrnInfoPtr pScrn, RADEONConnector *pPort) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int DDCReg; + + DDCReg = info->DDCReg; + info->DDCReg = pPort->ExtChip->i2c_reg; + pPort->ExtChip->vid_rec->PrintRegs(pPort->ExtChip->devpriv); + pPort->ExtChip->vid_rec->RestoreRegs(pPort->ExtChip->devpriv); + info->DDCReg = DDCReg; + return; + +} + +void RADEONSaveExtChipRegs(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + if (info->IsSecondary) + return; + + if (pRADEONEnt->PortInfo[0]->TMDSType == TMDS_EXT) + RADEONTMDSSaveRegs(pScrn, pRADEONEnt->PortInfo[0]); + else if (pRADEONEnt->PortInfo[1]->TMDSType == TMDS_EXT) + RADEONTMDSSaveRegs(pScrn, pRADEONEnt->PortInfo[1]); + return; +} + + +void RADEONProgramExtChipRegs(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + if (info->IsSecondary) + return; + + if (pRADEONEnt->PortInfo[0]->TMDSType == TMDS_EXT) + RADEONTMDSProgramRegs(pScrn, pRADEONEnt->PortInfo[0], mode); + else if (pRADEONEnt->PortInfo[1]->TMDSType == TMDS_EXT) + RADEONTMDSProgramRegs(pScrn, pRADEONEnt->PortInfo[1], mode); + return; +} + + +void RADEONRestoreExtChipRegs(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + if (info->IsSecondary) + return; + + if (pRADEONEnt->PortInfo[0]->TMDSType == TMDS_EXT) + RADEONTMDSRestoreRegs(pScrn, pRADEONEnt->PortInfo[0]); + else if (pRADEONEnt->PortInfo[1]->TMDSType == TMDS_EXT) + RADEONTMDSRestoreRegs(pScrn, pRADEONEnt->PortInfo[1]); + return; +} + void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) { MonPtr mon = pScrn->monitor; @@ -1009,6 +1200,13 @@ void RADEONSetupConnectors(ScrnInfoPtr pScrn) pRADEONEnt->PortInfo[0]->DACType = DAC_PRIMARY; } + /* try to find a TMDS Controller is we have specified external TMDS */ + info->extTMDS = FALSE; + if (pRADEONEnt->PortInfo[0]->TMDSType == TMDS_EXT) + info->extTMDS = RADEONFindTMDSController(pScrn, 0); + else if (pRADEONEnt->PortInfo[1]->TMDSType == TMDS_EXT) + info->extTMDS = RADEONFindTMDSController(pScrn, 1); + /* IgnoreEDID option is different from the NoDDCxx options used by DDC module * When IgnoreEDID is used, monitor detection will still use DDC * detection, but all EDID data will not be used in mode validation. @@ -1596,6 +1794,7 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); OUTREG(RADEON_FP2_GEN_CNTL, tmp); save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + RADEONTMDSPowerSet(pScrn, pPort, TRUE); } } else if (pPort->MonType == MT_LCD) { tmp = INREG(RADEON_LVDS_GEN_CNTL); @@ -1640,6 +1839,7 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); OUTREG(RADEON_FP2_GEN_CNTL, tmp); save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + RADEONTMDSPowerSet(pScrn, pPort, FALSE); } } @@ -2173,6 +2373,7 @@ static void RADEONDPMSSetOn(ScrnInfoPtr pScrn, RADEONConnector *pPort) break; case MT_DFP: if (TmdsType == TMDS_EXT) { + RADEONTMDSPowerSet(pScrn, pPort, TRUE); OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); if (info->ChipFamily >= CHIP_FAMILY_R200) { @@ -2220,6 +2421,7 @@ static void RADEONDPMSSetOff(ScrnInfoPtr pScrn, RADEONConnector *pPort) break; case MT_DFP: if (TmdsType == TMDS_EXT) { + RADEONTMDSPowerSet(pScrn, pPort, FALSE); OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); if (info->ChipFamily >= CHIP_FAMILY_R200) { diff --git a/src/radeon_driver.c b/src/radeon_driver.c index d1cd790..504b1ba 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -3773,8 +3773,12 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->PaletteSavedOnVT = FALSE; +ErrorF("pre RADEONSave\n"); + RADEONSave(pScrn); +ErrorF("post RADEONSave\n"); + if ((!info->IsSecondary) && info->IsMobility) { if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { RADEONSetDynamicClock(pScrn, 1); @@ -5377,6 +5381,11 @@ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONSavePLL2Registers (pScrn, save); /*RADEONSavePalette(pScrn, save);*/ /*memcpy(&info->ModeReg, &info->SavedReg, sizeof(RADEONSaveRec));*/ + if (info->extTMDS) { +ErrorF("pre RADEONSaveExtChipRegs\n"); + RADEONSaveExtChipRegs(pScrn); +ErrorF("post RADEONSaveExtChipRegs\n"); + } } RADEONTRACE(("RADEONSaveMode returns %p\n", save)); @@ -5464,6 +5473,8 @@ static void RADEONRestore(ScrnInfoPtr pScrn) #endif RADEONRestoreMode(pScrn, restore); + if (info->extTMDS) + RADEONRestoreExtChipRegs(pScrn); if (!info->IsSecondary) RADEONRestoreSurfaces(pScrn, restore); @@ -5646,19 +5657,24 @@ static void RADEONInitFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | RADEON_FP2_DVO_EN | + RADEON_FP2_ON | RADEON_FP2_DVO_RATE_SEL_SDR); - if (mode->Flags & RADEON_USE_RMX) - save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + if (mode->Flags & RADEON_USE_RMX) + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; } else { save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_DVO_EN | + RADEON_FP2_ON | RADEON_FP2_DVO_RATE_SEL_SDR); - } + } /*save->fp2_gen_cntl |= ( RADEON_FP2_ON | RADEON_FP2_BLANK_EN | RADEON_FP2_DVO_EN);*/ } else { if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_EN | + RADEON_FP2_ON | RADEON_FP2_DVO_RATE_SEL_SDR); save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 /*| RADEON_FP2_PANEL_FORMAT | @@ -5666,7 +5682,9 @@ static void RADEONInitFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, RADEON_FP2_ON | RADEON_FP2_DVO_EN*/); } else { - save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_EN | + RADEON_FP2_ON | + RADEON_FP2_DVO_RATE_SEL_SDR); save->fp2_gen_cntl |= (RADEON_FP2_SRC_SEL_CRTC2 /*| RADEON_FP2_PANEL_FORMAT | RADEON_FP2_BLANK_EN | @@ -6302,7 +6320,9 @@ static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); - +#if 1 + save->pixclks_cntl |= R300_DVOCLKD_IN_PHASE /*| R300_PIX2CLK_SRC_INVERT*/; +#endif } #if 0 @@ -6463,6 +6483,8 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) pScrn->vtSema = TRUE; RADEONBlank(pScrn); RADEONRestoreMode(pScrn, &info->ModeReg); + if (info->extTMDS) + RADEONProgramExtChipRegs(pScrn, mode); RADEONUnblank(pScrn); info->CurrentLayout.mode = mode; diff --git a/src/radeon_probe.h b/src/radeon_probe.h index b651e7d..3216df1 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -39,6 +39,7 @@ #include "xf86str.h" #include "xf86DDC.h" +#include "i2c_vid.h" #define _XF86MISC_SERVER_ #include @@ -104,6 +105,19 @@ typedef enum typedef struct { + int type; + char *modulename; + char *fntablename; + int address; + const char **symbols; + I830I2CVidOutputPtr vid_rec; + void *devpriv; + pointer modhandle; + int i2c_reg; +} RADEONDVORec, *RADEONDVOPtr; + +typedef struct +{ Bool IsUsed; Bool IsActive; int binding; // which instance of the driver "owns" this controller @@ -121,6 +135,7 @@ typedef struct /* one connector can be bound to one CRTC */ int crtc_num; + RADEONDVOPtr ExtChip; } RADEONConnector; diff --git a/src/radeon_reg.h b/src/radeon_reg.h index a6bbe69..562998c 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -756,7 +756,14 @@ # define RADEON_FP2_CRC_EN (1 << 23) # define RADEON_FP2_CRC_READ_EN (1 << 24) # define RADEON_FP2_DVO_EN (1 << 25) -# define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) +# define RADEON_FP2_DVO_TMDS_CTL3 (1 << 26) +# define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 27) +# define RADEON_FP2_DVO_RATE_SEL_DDR (0 << 27) +# define RADEON_FP2_DVO_CLOCK_MODE_SINGLE_ENDED (1 << 28) +# define RADEON_FP2_DVO_CLOCK_MODE_DIFFERENTIAL (0 << 28) +# define RADEON_FP2_DVO_DUAL_CHANNEL_EN (1 << 29) +# define RADEON_FP2_DVO_TMDS_CTL3_SEL_AUXWIN (1 << 30) +# define RADEON_FP2_DVO_TMDS_CTL3_SEL_STEREOSYNC (2 << 30) #define RADEON_FP_H_SYNC_STRT_WID 0x02c4 #define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 #define RADEON_FP_HORZ_STRETCH 0x028c @@ -845,7 +852,27 @@ #define RADEON_I2C_DATA 0x0098 #define RADEON_DVI_I2C_CNTL_0 0x02e0 -#define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */ +# define RADEON_I2C_DONE (1 << 0) +# define RADEON_I2C_NACK (1 << 1) +# define RADEON_I2C_HALT (1 << 2) +# define RADEON_DVI_I2C_PIN_SEL (1 << 4) +# define RADEON_I2C_SOFT_RST (1 << 5) +# define RADEON_I2C_DRIVE_EN (1 << 6) +# define RADEON_I2C_DRIVE_SEL (1 << 7) +# define RADEON_I2C_START (1 << 8) +# define RADEON_I2C_STOP (1 << 9) +# define RADEON_I2C_RECEIVE (1 << 10) +# define RADEON_I2C_ABORT (1 << 11) +# define RADEON_I2C_GO (1 << 12) +# define RADEON_SW_WANTS_TO_USE_DVI_I2C (1 << 13) /* W */ +# define RADEON_SW_CAN_USE_DVI_I2C (1 << 13) /* R */ +# define RADEON_SW_DONE_USING_DVI_I2C (1 << 14) /* W */ +# define RADEON_HW_NEEDS_DVI_I2C (1 << 14) /* R */ +# define RADEON_ABORT_HW_DVI_I2C (1 << 15) /* W */ +# define RADEON_HW_USING_DVI_I2C (1 << 15) /* R */ +#define RADEON_DVI_I2C_CNTL_1 0x02e4 +# define RADEON_I2C_SEL (1 << 16) +# define RADEON_I2C_EN (1 << 17) #define RADEON_DVI_I2C_DATA 0x02e8 #define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ @@ -1229,7 +1256,10 @@ # define R300_PIXCLK_TVO_ALWAYS_ONb (1 << 17) # define R300_P2G2CLK_ALWAYS_ONb (1 << 18) # define R300_P2G2CLK_DAC_ALWAYS_ONb (1 << 19) +# define R300_DVOCLKC_IN_PHASE (1 << 20) +# define R300_DVOCLKD_IN_PHASE (1 << 22) # define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23) +# define R300_PIX2CLK_SRC_INVERT (1 << 31) #define RADEON_PLANE_3D_MASK_C 0x1d44 #define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ #define RADEON_PMI_CAP_ID 0x0f5c /* PCI */