summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@nx6125b.(none)>2007-04-22 11:36:00 +1000
committerDave Airlie <airlied@nx6125b.(none)>2007-04-22 11:36:00 +1000
commitdd6a966e862b774a8e8b9e1a085309219673efad (patch)
treeb7b59fdf393911798eeb83dca59758f0f67ff861
parentc81ed9bd7b37c9d02141d10f6c7bad3d0c57032f (diff)
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.
-rw-r--r--src/radeon_bios.c5
-rw-r--r--src/radeon_display.c44
-rw-r--r--src/radeon_probe.h3
-rw-r--r--src/radeon_reg.h2
4 files changed, 39 insertions, 15 deletions
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index 1d4c9bb..dd3d0a7 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 57e752e..f3b86e6 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 f446516..dc30e2e 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 b50fcf0..0d5e586 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