From dd6a966e862b774a8e8b9e1a085309219673efad Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 22 Apr 2007 11:36:00 +1000 Subject: radeon: add support for DDC on some laptop chipsets I noticed fglrx has DDC for the panel in the rs480 laptop, however radeon didn't pick it up, so I valgrinded fglrx and spotted 0x1a0/0x1a4 accesses I actually noticed this before from the BIOS but never figured it out. So now I get DDC from the LCD on this laptop. --- src/radeon_bios.c | 5 ++++- src/radeon_display.c | 44 +++++++++++++++++++++++++++++++------------- src/radeon_probe.h | 3 ++- src/radeon_reg.h | 2 ++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/radeon_bios.c b/src/radeon_bios.c index 1d4c9bbb..dd3d0a7a 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -181,6 +181,9 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) case RADEON_GPIO_CRT2_DDC: pRADEONEnt->PortInfo[crtc]->DDCType = DDC_CRT2; break; + case RADEON_LCD_GPIO_MASK: + pRADEONEnt->PortInfo[crtc]->DDCType = DDC_LCD; + break; default: pRADEONEnt->PortInfo[crtc]->DDCType = DDC_NONE_DETECTED; break; @@ -290,7 +293,7 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) { if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) { pRADEONEnt->PortInfo[0]->DDCType = tmp1; - if (pRADEONEnt->PortInfo[0]->DDCType > DDC_CRT2) { + if (pRADEONEnt->PortInfo[0]->DDCType > DDC_LCD) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDCType %d found\n", pRADEONEnt->PortInfo[0]->DDCType); diff --git a/src/radeon_display.c b/src/radeon_display.c index 57e752e3..f3b86e6e 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -75,12 +75,13 @@ const char *TMDSTypeName[3] = { "External" }; -const char *DDCTypeName[5] = { +const char *DDCTypeName[6] = { "NONE", "MONID", "DVI_DDC", "VGA_DDC", - "CRT2_DDC" + "CRT2_DDC", + "LCD_DDC" }; const char *DACTypeName[3] = { @@ -166,10 +167,16 @@ static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) unsigned char *RADEONMMIO = info->MMIO; /* Get the result */ - val = INREG(info->DDCReg); - *Clock = (val & RADEON_GPIO_Y_1) != 0; - *data = (val & RADEON_GPIO_Y_0) != 0; + if (info->DDCReg == RADEON_LCD_GPIO_MASK) { + val = INREG(info->DDCReg+4); + *Clock = (val & (1<<13)) != 0; + *data = (val & (1<<12)) != 0; + } else { + val = INREG(info->DDCReg); + *Clock = (val & RADEON_GPIO_Y_1) != 0; + *data = (val & RADEON_GPIO_Y_0) != 0; + } } static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) @@ -179,11 +186,17 @@ static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) unsigned long val; unsigned char *RADEONMMIO = info->MMIO; - val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); - val |= (Clock ? 0:RADEON_GPIO_EN_1); - val |= (data ? 0:RADEON_GPIO_EN_0); - OUTREG(info->DDCReg, val); - + if (info->DDCReg == RADEON_LCD_GPIO_MASK) { + val = INREG(info->DDCReg) & (CARD32)~((1<<12) | (1<<13)); + val |= (Clock ? 0:(1<<13)); + val |= (data ? 0:(1<<12)); + OUTREG(info->DDCReg, val); + } else { + val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); + val |= (Clock ? 0:RADEON_GPIO_EN_1); + val |= (data ? 0:RADEON_GPIO_EN_0); + OUTREG(info->DDCReg, val); + } /* read back to improve reliability on some cards. */ val = INREG(info->DDCReg); } @@ -562,13 +575,16 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCT case DDC_CRT2: info->DDCReg = RADEON_GPIO_CRT2_DDC; break; + case DDC_LCD: + info->DDCReg = RADEON_LCD_GPIO_MASK; + break; default: info->DDCReg = DDCReg; return MT_NONE; } /* Read and output monitor info using DDC2 over I2C bus */ - if (info->pI2CBus && info->ddc2) { + if (info->pI2CBus && info->ddc2 && (info->DDCReg != RADEON_LCD_GPIO_MASK)) { OUTREG(info->DDCReg, INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); @@ -620,15 +636,17 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCT OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); usleep(15000); - if(*MonInfo) break; + if(*MonInfo) break; } + } else if (info->pI2CBus && info->ddc2 && info->DDCReg == RADEON_LCD_GPIO_MASK) { + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); MonType = MT_NONE; } OUTREG(info->DDCReg, INREG(info->DDCReg) & - ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); + ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); if (*MonInfo) { if ((*MonInfo)->rawData[0x14] & 0x80) { diff --git a/src/radeon_probe.h b/src/radeon_probe.h index f4465163..dc30e2e9 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -48,7 +48,8 @@ typedef enum DDC_MONID, DDC_DVI, DDC_VGA, - DDC_CRT2 + DDC_CRT2, + DDC_LCD, } RADEONDDCType; typedef enum diff --git a/src/radeon_reg.h b/src/radeon_reg.h index b50fcf0a..0d5e5863 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -907,6 +907,8 @@ # define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13) # define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) # define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) +#define RADEON_LCD_GPIO_MASK 0x01a0 +#define RADEON_LCD_GPIO_Y_REG 0x01a4 #define RADEON_MDGPIO_A_REG 0x01ac #define RADEON_MDGPIO_EN_REG 0x01b0 #define RADEON_MDGPIO_MASK 0x0198 -- cgit v1.2.3