diff options
author | Alex Deucher <alex@botch2.(none)> | 2008-01-20 18:33:22 -0500 |
---|---|---|
committer | Alex Deucher <alex@botch2.(none)> | 2008-01-20 18:33:22 -0500 |
commit | b2db8657fb888cff6d64c6dcb182caac389776ce (patch) | |
tree | 8aae5a5c3e5c66811ae9ac5dda73c45a488e9f70 | |
parent | a43003b24022a833e604f41b2873c0350b34181c (diff) |
RADEON: re-work i2c for DDC
Unify the radeon/avivo paths and grab the data/clk masks from bios
if available
-rw-r--r-- | src/radeon_bios.c | 10 | ||||
-rw-r--r-- | src/radeon_output.c | 220 | ||||
-rw-r--r-- | src/radeon_probe.h | 16 |
3 files changed, 113 insertions, 133 deletions
diff --git a/src/radeon_bios.c b/src/radeon_bios.c index 829a641e..46f4a3b8 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -274,12 +274,6 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) case DDC_CRT2: info->BiosConnector[i].ddc_line = RADEON_GPIO_CRT2_DDC; break; - case DDC_LCD: - info->BiosConnector[i].ddc_line = RADEON_LCD_GPIO_MASK; - break; - case DDC_GPIO: - info->BiosConnector[i].ddc_line = RADEON_MDGPIO_EN_REG; - break; default: xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); break; @@ -371,9 +365,13 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) break; case DDC_LCD: info->BiosConnector[4].ddc_line = RADEON_LCD_GPIO_MASK; + info->BiosConnector[4].ddc_clk_mask = RADEON_BIOS32(tmp0 + 0x03); + info->BiosConnector[4].ddc_data_mask = RADEON_BIOS32(tmp0 + 0x07); break; case DDC_GPIO: info->BiosConnector[4].ddc_line = RADEON_MDGPIO_EN_REG; + info->BiosConnector[4].ddc_clk_mask = RADEON_BIOS32(tmp0 + 0x03); + info->BiosConnector[4].ddc_data_mask = RADEON_BIOS32(tmp0 + 0x07); break; default: xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); diff --git a/src/radeon_output.c b/src/radeon_output.c index 8fc6bc67..42477b65 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -172,7 +172,7 @@ static void RADEONUpdatePanelSize(xf86OutputPtr output); static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output); #define AVIVO_I2C_DISABLE 0 #define AVIVO_I2C_ENABLE 1 -static Bool AVIVOI2CDoLock(ScrnInfoPtr pScrn, int lock_state, int gpio); +static Bool AVIVOI2CDoLock(xf86OutputPtr output, int lock_state); extern void atombios_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, @@ -220,9 +220,9 @@ avivo_display_ddc_connected(ScrnInfoPtr pScrn, xf86OutputPtr output) RADEONOutputPrivatePtr radeon_output = output->driver_private; if (radeon_output->pI2CBus) { - AVIVOI2CDoLock(pScrn, AVIVO_I2C_ENABLE, radeon_output->ddc_line); + AVIVOI2CDoLock(output, AVIVO_I2C_ENABLE); MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus); - AVIVOI2CDoLock(pScrn, AVIVO_I2C_DISABLE, radeon_output->ddc_line); + AVIVOI2CDoLock(output, AVIVO_I2C_DISABLE); } if (MonInfo) { if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE)) @@ -1267,91 +1267,23 @@ Bool AVIVOI2CReset(ScrnInfoPtr pScrn) #endif static -Bool AVIVOI2CDoLock(ScrnInfoPtr pScrn, int lock_state, int gpio_reg) +Bool AVIVOI2CDoLock(xf86OutputPtr output, int lock_state) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONI2CBusPtr pRADEONI2CBus = radeon_output->pI2CBus->DriverPrivate.ptr; unsigned char *RADEONMMIO = info->MMIO; CARD32 temp; - temp = INREG(gpio_reg); - if (gpio_reg == AVIVO_GPIO_0) { - if (lock_state == AVIVO_I2C_ENABLE) - temp |= (1 << 19) | (1 << 18); - else - temp &= ~((1 << 19) | (1 << 18)); - } else { - if (lock_state == AVIVO_I2C_ENABLE) - temp |= (1 << 0) | (1 << 8); - else - temp &= ~((1 << 0) | (1 << 8)); - } - OUTREG(gpio_reg, temp); - temp = INREG(gpio_reg); - - return TRUE; -} - -void -avivo_i2c_gpio_get_bits(I2CBusPtr b, int *Clock, int *data) -{ - ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(screen_info); - unsigned char *RADEONMMIO = info->MMIO; - unsigned long val; - - /* Get the result */ - if (b->DriverPrivate.uval == AVIVO_GPIO_0) { - val = INREG(b->DriverPrivate.uval + 0xc); - *Clock = (val & (1<<19)) != 0; - *data = (val & (1<<18)) != 0; - } else { - val = INREG(b->DriverPrivate.uval + 0xc); - *Clock = (val & (1<<0)) != 0; - *data = (val & (1<<8)) != 0; - } -} - -static void -avivo_i2c_gpio_put_bits(I2CBusPtr b, int Clock, int data) -{ - ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(screen_info); - unsigned char *RADEONMMIO = info->MMIO; - unsigned long val; - - val = 0; - if (b->DriverPrivate.uval == AVIVO_GPIO_0) { - val |= (Clock ? 0:(1<<19)); - val |= (data ? 0:(1<<18)); - } else { - val |= (Clock ? 0:(1<<0)); - val |= (data ? 0:(1<<8)); - - } - - OUTREG(b->DriverPrivate.uval + 0x8, val); - /* read back to improve reliability on some cards. */ - val = INREG(b->DriverPrivate.uval + 0x8); -} - -static Bool -avivo_i2c_init(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) -{ - I2CBusPtr pI2CBus; - - pI2CBus = xf86CreateI2CBusRec(); - if (!pI2CBus) return FALSE; - - pI2CBus->BusName = name; - pI2CBus->scrnIndex = pScrn->scrnIndex; - pI2CBus->I2CPutBits = avivo_i2c_gpio_put_bits; - pI2CBus->I2CGetBits = avivo_i2c_gpio_get_bits; - pI2CBus->AcknTimeout = 5; - pI2CBus->DriverPrivate.uval = i2c_reg; - - if (!xf86I2CBusInit(pI2CBus)) return FALSE; + temp = INREG(pRADEONI2CBus->gpio_reg); + if (lock_state == AVIVO_I2C_ENABLE) + temp |= (pRADEONI2CBus->put_clk_mask | pRADEONI2CBus->put_data_mask); + else + temp &= ~(pRADEONI2CBus->put_clk_mask | pRADEONI2CBus->put_data_mask);; + OUTREG(pRADEONI2CBus->gpio_reg, temp); + temp = INREG(pRADEONI2CBus->gpio_reg); - *bus_ptr = pI2CBus; return TRUE; } @@ -1361,22 +1293,12 @@ static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned long val; unsigned char *RADEONMMIO = info->MMIO; + RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr; /* Get the result */ - - if (b->DriverPrivate.uval == RADEON_LCD_GPIO_MASK) { - val = INREG(b->DriverPrivate.uval+4); - *Clock = (val & (1<<13)) != 0; - *data = (val & (1<<12)) != 0; - } else if (b->DriverPrivate.uval == RADEON_MDGPIO_EN_REG) { - val = INREG(b->DriverPrivate.uval+4); - *Clock = (val & (1<<19)) != 0; - *data = (val & (1<<18)) != 0; - } else { - val = INREG(b->DriverPrivate.uval); - *Clock = (val & RADEON_GPIO_Y_1) != 0; - *data = (val & RADEON_GPIO_Y_0) != 0; - } + val = INREG(pRADEONI2CBus->get_reg); + *Clock = (val & pRADEONI2CBus->get_clk_mask) != 0; + *data = (val & pRADEONI2CBus->get_data_mask) != 0; } static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) @@ -1385,31 +1307,25 @@ static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned long val; unsigned char *RADEONMMIO = info->MMIO; + RADEONI2CBusPtr pRADEONI2CBus = b->DriverPrivate.ptr; + + val = INREG(pRADEONI2CBus->put_reg) & (CARD32)~(pRADEONI2CBus->put_clk_mask | pRADEONI2CBus->put_data_mask); + val |= (Clock ? 0:pRADEONI2CBus->put_clk_mask); + val |= (data ? 0:pRADEONI2CBus->put_data_mask); + OUTREG(pRADEONI2CBus->put_reg, val); - if (b->DriverPrivate.uval == RADEON_LCD_GPIO_MASK) { - val = INREG(b->DriverPrivate.uval) & (CARD32)~((1<<12) | (1<<13)); - val |= (Clock ? 0:(1<<13)); - val |= (data ? 0:(1<<12)); - OUTREG(b->DriverPrivate.uval, val); - } else if (b->DriverPrivate.uval == RADEON_MDGPIO_EN_REG) { - val = INREG(b->DriverPrivate.uval) & (CARD32)~((1<<18) | (1<<19)); - val |= (Clock ? 0:(1<<19)); - val |= (data ? 0:(1<<18)); - OUTREG(b->DriverPrivate.uval, val); - } else { - val = INREG(b->DriverPrivate.uval) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); - val |= (Clock ? 0:RADEON_GPIO_EN_1); - val |= (data ? 0:RADEON_GPIO_EN_0); - OUTREG(b->DriverPrivate.uval, val); - } /* read back to improve reliability on some cards. */ - val = INREG(b->DriverPrivate.uval); + val = INREG(pRADEONI2CBus->put_reg); } static Bool -RADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) +RADEONI2CInit(xf86OutputPtr output, I2CBusPtr *bus_ptr, char *name, Bool dvo) { + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; I2CBusPtr pI2CBus; + RADEONI2CBusPtr pRADEONI2CBus; pI2CBus = xf86CreateI2CBusRec(); if (!pI2CBus) return FALSE; @@ -1419,9 +1335,62 @@ RADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) pI2CBus->I2CPutBits = RADEONI2CPutBits; pI2CBus->I2CGetBits = RADEONI2CGetBits; pI2CBus->AcknTimeout = 5; - pI2CBus->DriverPrivate.uval = i2c_reg; - if (!xf86I2CBusInit(pI2CBus)) return FALSE; + pRADEONI2CBus = xcalloc(sizeof(RADEONI2CBusRec), 1); + if (!pRADEONI2CBus) { + xf86DrvMsg(pScrn->scrnIndex,X_ERROR, "Failed to allocate radeon i2c bus info\n"); + return FALSE; + } + + if (dvo) { + /* these only seem to work properly on MACs */ + pRADEONI2CBus->gpio_reg = radeon_output->dvo_i2c_reg; + pRADEONI2CBus->put_reg = radeon_output->dvo_i2c_reg; + pRADEONI2CBus->get_reg = radeon_output->dvo_i2c_reg; + pRADEONI2CBus->put_clk_mask = RADEON_GPIO_EN_1; + pRADEONI2CBus->put_data_mask = RADEON_GPIO_EN_0; + pRADEONI2CBus->get_clk_mask = RADEON_GPIO_Y_1; + pRADEONI2CBus->get_data_mask = RADEON_GPIO_Y_0; + } else { + if (IS_AVIVO_VARIANT) { + pRADEONI2CBus->gpio_reg = radeon_output->ddc_line; + pRADEONI2CBus->put_reg = radeon_output->ddc_line + 0x8; + pRADEONI2CBus->get_reg = radeon_output->ddc_line + 0xc; + /* FIXME: get these from the BIOS */ + if (radeon_output->ddc_line == AVIVO_GPIO_0) { + pRADEONI2CBus->put_clk_mask = (1 << 19); + pRADEONI2CBus->put_data_mask = (1 << 18); + pRADEONI2CBus->get_clk_mask = (1 << 19); + pRADEONI2CBus->get_data_mask = (1 << 18); + } else { + pRADEONI2CBus->put_clk_mask = (1 << 0); + pRADEONI2CBus->put_data_mask = (1 << 8); + pRADEONI2CBus->get_clk_mask = (1 << 0); + pRADEONI2CBus->get_data_mask = (1 << 8); + } + } else { + pRADEONI2CBus->gpio_reg = radeon_output->ddc_line; + pRADEONI2CBus->put_reg = radeon_output->ddc_line; + pRADEONI2CBus->get_reg = radeon_output->ddc_line; + if ((radeon_output->ddc_line == RADEON_LCD_GPIO_MASK) || + (radeon_output->ddc_line == RADEON_MDGPIO_EN_REG)) { + pRADEONI2CBus->put_clk_mask = radeon_output->ddc_clk_mask; + pRADEONI2CBus->put_data_mask = radeon_output->ddc_data_mask; + pRADEONI2CBus->get_clk_mask = radeon_output->ddc_clk_mask; + pRADEONI2CBus->get_data_mask = radeon_output->ddc_data_mask; + } else { + pRADEONI2CBus->put_clk_mask = RADEON_GPIO_EN_1; + pRADEONI2CBus->put_data_mask = RADEON_GPIO_EN_0; + pRADEONI2CBus->get_clk_mask = RADEON_GPIO_Y_1; + pRADEONI2CBus->get_data_mask = RADEON_GPIO_Y_0; + } + } + } + + pI2CBus->DriverPrivate.ptr = (pointer)pRADEONI2CBus; + + if (!xf86I2CBusInit(pI2CBus)) + return FALSE; *bus_ptr = pI2CBus; return TRUE; @@ -1757,14 +1726,6 @@ void RADEONInitConnector(xf86OutputPtr output) name = xnfalloc(strlen(stmp) + 1); strcpy(name, stmp); - if (IS_AVIVO_VARIANT) { - if (radeon_output->ddc_line) - avivo_i2c_init(pScrn, &radeon_output->pI2CBus, radeon_output->ddc_line, name); - } else { - if (radeon_output->ddc_line) - RADEONI2CInit(pScrn, &radeon_output->pI2CBus, radeon_output->ddc_line, name); - } - if (radeon_output->DACType == DAC_PRIMARY) radeon_output->load_detection = 1; /* primary dac, only drives vga */ /*else if (radeon_output->DACType == DAC_TVDAC && @@ -1784,7 +1745,7 @@ void RADEONInitConnector(xf86OutputPtr output) if (OUTPUT_IS_DVI) { I2CBusPtr pDVOBus; radeon_output->rmx_type = RMX_OFF; - if ((!IS_AVIVO_VARIANT) && radeon_output->TMDSType == TMDS_EXT) { + if ((!info->IsAtomBios) && radeon_output->TMDSType == TMDS_EXT) { #if defined(__powerpc__) radeon_output->dvo_i2c_reg = RADEON_GPIO_MONID; radeon_output->dvo_i2c_slave_addr = 0x70; @@ -1794,7 +1755,7 @@ void RADEONInitConnector(xf86OutputPtr output) radeon_output->dvo_i2c_slave_addr = 0x70; } #endif - if (RADEONI2CInit(pScrn, &pDVOBus, radeon_output->dvo_i2c_reg, "DVO")) { + if (RADEONI2CInit(output, &pDVOBus, "DVO", TRUE)) { radeon_output->DVOChip = RADEONDVODeviceInit(pDVOBus, radeon_output->dvo_i2c_slave_addr); @@ -1815,6 +1776,9 @@ void RADEONInitConnector(xf86OutputPtr output) RADEONGetTVDacAdjInfo(output); } + if (radeon_output->ddc_line) + RADEONI2CInit(output, &radeon_output->pI2CBus, name, FALSE); + } #if defined(__powerpc__) @@ -2365,6 +2329,8 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) radeon_output->ddc_line = info->BiosConnector[i].ddc_line; radeon_output->devices = info->BiosConnector[i].devices; radeon_output->output_id = info->BiosConnector[i].output_id; + radeon_output->ddc_clk_mask = info->BiosConnector[i].ddc_clk_mask; + radeon_output->ddc_data_mask = info->BiosConnector[i].ddc_data_mask; if (radeon_output->ConnectorType == CONNECTOR_DVI_D) radeon_output->DACType = DAC_NONE; diff --git a/src/radeon_probe.h b/src/radeon_probe.h index dd75d2c4..d24d8ed2 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -160,6 +160,17 @@ typedef enum TV_STD_PAL_CN = 128, } TVStd; +typedef struct +{ + CARD32 gpio_reg; + CARD32 put_reg; + CARD32 get_reg; + CARD32 put_clk_mask; + CARD32 put_data_mask; + CARD32 get_clk_mask; + CARD32 get_data_mask; +} RADEONI2CBusRec, *RADEONI2CBusPtr; + typedef struct _RADEONCrtcPrivateRec { #ifdef USE_XAA FBLinearPtr rotate_mem_xaa; @@ -191,6 +202,8 @@ typedef struct { int output_id; int devices; int hpd_mask; + CARD32 ddc_clk_mask; + CARD32 ddc_data_mask; } RADEONBIOSConnector; typedef struct _RADEONOutputPrivateRec { @@ -239,6 +252,9 @@ typedef struct _RADEONOutputPrivateRec { Bool tv_on; int load_detection; + CARD32 ddc_clk_mask; + CARD32 ddc_data_mask; + char *name; int output_id; int devices; |