summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alex@botch2.(none)>2007-09-30 13:11:20 -0400
committerAlex Deucher <alex@botch2.(none)>2007-09-30 13:13:15 -0400
commit22519fde1e002f28d6036d448fcd18452d00f1bb (patch)
tree79bcca5131140677fb758f49fe3e10f55e69e9ff
parentdcc376e2d2a13329dd03f1bc4b471329757a6f5f (diff)
RADEON: add support for ext tmds table and ext tmds chip init
This probably won't work on all chips as the various gpio lines seem to need special magic to to actually talk to the i2c slave chips.
-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;