diff options
-rw-r--r-- | src/radeon_atombios.c | 58 | ||||
-rw-r--r-- | src/radeon_atombios.h | 3 | ||||
-rw-r--r-- | src/radeon_driver.c | 2 | ||||
-rw-r--r-- | src/radeon_output.c | 19 | ||||
-rw-r--r-- | src/radeon_probe.h | 2 |
5 files changed, 80 insertions, 4 deletions
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index b81d2cbd..12aeecae 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -1386,6 +1386,58 @@ const int object_connector_convert[] = CONNECTOR_DISPLAY_PORT, }; +xf86MonPtr radeon_atom_get_edid(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONInfoPtr info = RADEONPTR(output->scrn); + READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION edid_data; + AtomBiosArgRec data; + unsigned char *space; + int i2c_clock = 50; + int engine_clk = info->sclk * 100; + int prescale; + unsigned char *edid; + xf86MonPtr mon = NULL; + + if (!radeon_output->ddc_i2c.hw_capable) + return mon; + + if (info->atomBIOS->fbBase) + edid = (unsigned char *)info->FB + info->atomBIOS->fbBase; + else if (info->atomBIOS->scratchBase) + edid = (unsigned char *)info->atomBIOS->scratchBase; + else + return mon; + + memset(edid, 0, ATOM_EDID_RAW_DATASIZE); + + if (info->ChipFamily == CHIP_FAMILY_R520) + prescale = (127 << 8) + (engine_clk * 10) / (4 * 127 * i2c_clock); + else if (info->ChipFamily < CHIP_FAMILY_R600) + prescale = (((engine_clk * 10)/(4 * 128 * 100) + 1) << 8) + 128; + else + prescale = (info->pll.reference_freq * 10) / i2c_clock; + + edid_data.usPrescale = prescale; + edid_data.usVRAMAddress = 0; + edid_data.ucSlaveAddr = 0xa0; + edid_data.ucLineNumber = radeon_output->ddc_i2c.hw_line; + + data.exec.index = GetIndexIntoMasterTable(COMMAND, ReadEDIDFromHWAssistedI2C); + data.exec.dataSpace = (void *)&space; + data.exec.pspace = &edid_data; + + if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) + ErrorF("Atom Get EDID success\n"); + else + ErrorF("Atom Get EDID failed\n"); + + if (edid[1] == 0xff) + mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); + + return mon; + +} static RADEONI2CBusRec RADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id) @@ -1425,9 +1477,15 @@ RADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id) i2c.get_data_mask = (1 << gpio.ucDataY_Shift); i2c.a_clk_mask = (1 << gpio.ucClkA_Shift); i2c.a_data_mask = (1 << gpio.ucDataA_Shift); + i2c.hw_line = gpio.sucI2cId.sbfAccess.bfI2C_LineMux; + i2c.hw_capable = gpio.sucI2cId.sbfAccess.bfHW_Capable; i2c.valid = TRUE; #if 0 + ErrorF("id: %d\n", id); + ErrorF("hw capable: %d\n", gpio.sucI2cId.sbfAccess.bfHW_Capable); + ErrorF("hw engine id: %d\n", gpio.sucI2cId.sbfAccess.bfHW_EngineID); + ErrorF("line mux %d\n", gpio.sucI2cId.sbfAccess.bfI2C_LineMux); ErrorF("mask_clk_reg: 0x%x\n", gpio.usClkMaskRegisterIndex * 4); ErrorF("mask_data_reg: 0x%x\n", gpio.usDataMaskRegisterIndex * 4); ErrorF("put_clk_reg: 0x%x\n", gpio.usClkEnRegisterIndex * 4); diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h index fe7044d0..1ec0e2d7 100644 --- a/src/radeon_atombios.h +++ b/src/radeon_atombios.h @@ -131,6 +131,9 @@ atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode); extern void atombios_get_command_table_version(atomBiosHandlePtr atomBIOS, int index, int *major, int *minor); +extern xf86MonPtr +radeon_atom_get_edid(xf86OutputPtr output); + Bool rhdAtomASICInit(atomBiosHandlePtr handle); diff --git a/src/radeon_driver.c b/src/radeon_driver.c index eac07d0e..c759bd6a 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -498,7 +498,7 @@ static Bool RADEONUnmapMem(ScrnInfoPtr pScrn) void RADEONPllErrataAfterIndex(RADEONInfoPtr info) { unsigned char *RADEONMMIO = info->MMIO; - + if (!(info->ChipErrata & CHIP_ERRATA_PLL_DUMMYREADS)) return; diff --git a/src/radeon_output.c b/src/radeon_output.c index 2cc38a5a..4947478f 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -222,9 +222,18 @@ radeon_ddc_connected(xf86OutputPtr output) RADEONOutputPrivatePtr radeon_output = output->driver_private; if (radeon_output->pI2CBus) { - RADEONI2CDoLock(output, TRUE); - MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus); - RADEONI2CDoLock(output, FALSE); + /* RV410 RADEON_GPIO_VGA_DDC seems to only work via hw i2c + * We may want to extend this to other cases if the need arises... + */ + if ((info->ChipFamily == CHIP_FAMILY_RV410) && + (radeon_output->ddc_i2c.mask_clk_reg == RADEON_GPIO_VGA_DDC) && + info->IsAtomBios) + MonInfo = radeon_atom_get_edid(output); + else { + RADEONI2CDoLock(output, TRUE); + MonInfo = xf86OutputGetEDID(output, radeon_output->pI2CBus); + RADEONI2CDoLock(output, FALSE); + } } if (MonInfo) { if (!xf86ReturnOptValBool(info->Options, OPTION_IGNORE_EDID, FALSE)) @@ -1732,6 +1741,8 @@ legacy_setup_i2c_bus(int ddc_line) { RADEONI2CBusRec i2c; + i2c.hw_line = 0; + i2c.hw_capable = FALSE; i2c.mask_clk_mask = RADEON_GPIO_EN_1; i2c.mask_data_mask = RADEON_GPIO_EN_0; i2c.a_clk_mask = RADEON_GPIO_A_1; @@ -1774,6 +1785,8 @@ atom_setup_i2c_bus(int ddc_line) { RADEONI2CBusRec i2c; + i2c.hw_line = 0; + i2c.hw_capable = FALSE; if (ddc_line == AVIVO_GPIO_0) { i2c.put_clk_mask = (1 << 19); i2c.put_data_mask = (1 << 18); diff --git a/src/radeon_probe.h b/src/radeon_probe.h index ce4ba931..83b34284 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -180,6 +180,8 @@ typedef struct uint32_t get_data_mask; uint32_t a_clk_mask; uint32_t a_data_mask; + int hw_line; + Bool hw_capable; } RADEONI2CBusRec, *RADEONI2CBusPtr; typedef struct _RADEONCrtcPrivateRec { |