diff options
-rw-r--r-- | src/radeon.h | 9 | ||||
-rw-r--r-- | src/radeon_bios.c | 133 | ||||
-rw-r--r-- | src/radeon_driver.c | 8 | ||||
-rw-r--r-- | src/radeon_output.c | 111 | ||||
-rw-r--r-- | src/radeon_probe.h | 5 |
5 files changed, 261 insertions, 5 deletions
diff --git a/src/radeon.h b/src/radeon.h index cec06e97..288fe00e 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -950,6 +950,15 @@ extern Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, DisplayModePtr crtc2, int crtc_mask, RADEONSavePtr save, RADEONMonitorType montype); +extern Bool +RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch); +extern Bool +RADEONDVOWriteByte(I2CDevPtr dvo, int addr, CARD8 ch); +extern Bool +RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output); +extern Bool +RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output); + void radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y); void diff --git a/src/radeon_bios.c b/src/radeon_bios.c index e106a168..cfa5d2bc 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -672,6 +672,139 @@ Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output) return FALSE; } +Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int offset, table_start, max_freq, gpio_reg, flags; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + return FALSE; + } else { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); + if (offset) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "External TMDS Table revision: %d\n", + RADEON_BIOS8(offset)); + table_start = offset+4; + max_freq = RADEON_BIOS16(table_start); + radeon_output->dvo_i2c_slave_addr = RADEON_BIOS8(table_start+2); + gpio_reg = RADEON_BIOS8(table_start+3); + if (gpio_reg == 1) + radeon_output->dvo_i2c_reg = RADEON_GPIO_MONID; + else if (gpio_reg == 2) + radeon_output->dvo_i2c_reg = RADEON_GPIO_DVI_DDC; + else if (gpio_reg == 3) + radeon_output->dvo_i2c_reg = RADEON_GPIO_VGA_DDC; + else if (gpio_reg == 4) + radeon_output->dvo_i2c_reg = RADEON_GPIO_CRT2_DDC; + else if (gpio_reg == 5) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "unsupported MM gpio_reg\n"); + /*radeon_output->i2c_reg = RADEON_GPIO_MM;*/ + else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unknown gpio reg: %d\n", gpio_reg); + return FALSE; + } + flags = RADEON_BIOS8(table_start+5); + radeon_output->dvo_duallink = flags & 0x01; + if (radeon_output->dvo_duallink) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Duallink TMDS detected\n"); + } + return TRUE; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No External TMDS Table found\n"); + + return FALSE; +} + +Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int offset, index, id; + CARD32 val, reg, andmask, ormask; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + return FALSE; + } else { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); + if (offset) { + index = offset+10; + id = RADEON_BIOS16(index); + while (id != 0xffff) { + index += 2; + switch(id >> 13) { + case 0: + reg = id & 0x1fff; + val = RADEON_BIOS32(index); + index += 4; + ErrorF("WRITE INDEXED: 0x%x 0x%x\n", + reg, (unsigned)val); + /*OUTREG(reg, val);*/ + break; + case 2: + reg = id & 0x1fff; + andmask = RADEON_BIOS32(index); + index += 4; + ormask = RADEON_BIOS32(index); + index += 4; + val = INREG(reg); + val = (val & andmask) | ormask; + ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n", + reg, (unsigned)andmask, (unsigned)ormask); + /*OUTREG(reg, val);*/ + break; + case 4: + val = RADEON_BIOS16(index); + index += 2; + ErrorF("delay: %d\n", val); + usleep(val); + break; + case 5: + reg = id & 0x1fff; + andmask = RADEON_BIOS32(index); + index += 4; + ormask = RADEON_BIOS32(index); + index += 4; + ErrorF("MASK PLL: 0x%x 0x%x 0x%x\n", + reg, (unsigned)andmask, (unsigned)ormask); + /*val = INPLL(pScrn, reg); + val = (val & andmask) | ormask; + OUTPLL(pScrn, reg, val);*/ + break; + case 6: + reg = id & 0x1fff; + val = RADEON_BIOS8(index); + index += 1; + ErrorF("i2c write: 0x%x, 0x%x\n", reg, val); + RADEONDVOWriteByte(radeon_output->DVOChip, reg, val); + break; + default: + ErrorF("unknown id %d\n", id>>13); + return FALSE; + }; + id = RADEON_BIOS16(index); + } + return TRUE; + } + } + + return FALSE; +} + /* support for init from bios tables * * Based heavily on the netbsd radeonfb driver diff --git a/src/radeon_driver.c b/src/radeon_driver.c index a8a3d39e..b7e2684b 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -2755,10 +2755,10 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) } /* Free the video bios (if applicable) */ - if (info->VBIOS) { - xfree(info->VBIOS); - info->VBIOS = NULL; - } + //if (info->VBIOS) { + //xfree(info->VBIOS); + //info->VBIOS = NULL; + //} /* Free int10 info */ if (pInt10) diff --git a/src/radeon_output.c b/src/radeon_output.c index fd94266c..6d46a98e 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -154,6 +154,87 @@ static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color); static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn); static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output); +Bool +RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch) +{ + if (!xf86I2CReadByte(dvo, addr, ch)) { + xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", + dvo->pI2CBus->BusName, dvo->SlaveAddr); + return FALSE; + } + return TRUE; +} + +Bool +RADEONDVOWriteByte(I2CDevPtr dvo, int addr, CARD8 ch) +{ + if (!xf86I2CWriteByte(dvo, addr, ch)) { + xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + dvo->pI2CBus->BusName, dvo->SlaveAddr); + return FALSE; + } + return TRUE; +} + +static I2CDevPtr +RADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr) +{ + I2CDevPtr dvo; + + dvo = xcalloc(1, sizeof(I2CDevRec)); + if (dvo == NULL) + return NULL; + + dvo->DevName = "RADEON DVO Controller"; + dvo->SlaveAddr = addr; + dvo->pI2CBus = b; + dvo->StartTimeout = b->StartTimeout; + dvo->BitTimeout = b->BitTimeout; + dvo->AcknTimeout = b->AcknTimeout; + dvo->ByteTimeout = b->ByteTimeout; + + if (xf86I2CDevInit(dvo)) { + return dvo; + } + + xfree(dvo); + return NULL; +} + +void +RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (!radeon_output->DVOChip) + return; + + OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) & + (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); + + if (!RADEONInitExtTMDSInfoFromBIOS(output)) { + /* do mac stuff here */ +#if defined(__powerpc__) + if (radeon_output->DVOChip) { + switch(info->MacModel) { + case RADEON_MAC_POWERBOOK_DL: + RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x30); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x00); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x90); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0x89); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x3b); + break; + default: + } + } +#endif + } +} + void RADEONPrintPortMap(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -796,6 +877,14 @@ static void RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save, RADEON_FP2_DVO_EN | RADEON_FP2_DVO_RATE_SEL_SDR); +#if 0 + /* XXX: these may be chip specific */ + save->fp2_gen_cntl |= (1 << 22) | R200_FP2_DVO_CLOCK_MODE_SINGLE; + + if (mode->Clock > 165000) + save->fp2_gen_cntl |= R200_FP2_DVO_DUAL_CHANNEL_EN; +#endif + if (IsPrimary) { if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; @@ -1062,6 +1151,7 @@ radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, RADEONRestoreFPRegisters(pScrn, &info->ModeReg); } else { ErrorF("restore FP2\n"); + RADEONRestoreDVOChip(pScrn, output); RADEONRestoreFP2Registers(pScrn, &info->ModeReg); } break; @@ -2489,8 +2579,27 @@ void RADEONInitConnector(xf86OutputPtr output) } if (radeon_output->type == OUTPUT_DVI) { + I2CBusPtr pDVOBus; radeon_output->rmx_type = RMX_OFF; - RADEONGetTMDSInfo(output); + if (radeon_output->TMDSType == TMDS_EXT) { +#if defined(__powerpc__) + radeon_output->dvo_i2c_reg = RADEON_GPIO_MONID; + radeon_output->dvo_i2c_slave_addr = 0x70; +#else + if (!RADEONGetExtTMDSInfoFromBIOS(output)) { + radeon_output->dvo_i2c_reg = RADEON_GPIO_CRT2_DDC; + radeon_output->dvo_i2c_slave_addr = 0x70; + } +#endif + if (RADEONI2CInit(pScrn, &pDVOBus, radeon_output->dvo_i2c_reg, "DVO")) { + radeon_output->DVOChip = + RADEONDVODeviceInit(pDVOBus, + radeon_output->dvo_i2c_slave_addr); + if (!radeon_output->DVOChip) + xfree(pDVOBus); + } + } else + RADEONGetTMDSInfo(output); } if (radeon_output->type == OUTPUT_STV || diff --git a/src/radeon_probe.h b/src/radeon_probe.h index ec895e49..dbd50d74 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -205,6 +205,11 @@ typedef struct _RADEONOutputPrivateRec { int DotClock; RADEONTMDSPll tmds_pll[4]; RADEONRMXType rmx_type; + /* dvo */ + I2CDevPtr DVOChip; + int dvo_i2c_reg; + int dvo_i2c_slave_addr; + Bool dvo_duallink; /* TV out */ TVStd default_tvStd; TVStd tvStd; |