summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/radeon_atombios.c58
-rw-r--r--src/radeon_atombios.h3
-rw-r--r--src/radeon_driver.c2
-rw-r--r--src/radeon_output.c19
-rw-r--r--src/radeon_probe.h2
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 {