summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/radeon.h9
-rw-r--r--src/radeon_bios.c133
-rw-r--r--src/radeon_driver.c8
-rw-r--r--src/radeon_output.c111
-rw-r--r--src/radeon_probe.h5
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;