diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/legacy_output.c | 9 | ||||
-rw-r--r-- | src/radeon_bios.c | 192 |
2 files changed, 178 insertions, 23 deletions
diff --git a/src/legacy_output.c b/src/legacy_output.c index ccf59ba3..3ca019f4 100644 --- a/src/legacy_output.c +++ b/src/legacy_output.c @@ -285,12 +285,11 @@ RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output) if (!radeon_output->DVOChip) return; - OUTREG(radeon_output->dvo_i2c.mask_clk_reg, - INREG(radeon_output->dvo_i2c.mask_clk_reg) & - (uint32_t)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); - if (!RADEONInitExtTMDSInfoFromBIOS(output)) { if (radeon_output->DVOChip) { + OUTREG(radeon_output->dvo_i2c.mask_clk_reg, + INREG(radeon_output->dvo_i2c.mask_clk_reg) & + (uint32_t)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); switch(info->ext_tmds_chip) { case RADEON_SIL_164: RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x30); @@ -1443,8 +1442,8 @@ legacy_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, } OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); } else { - RADEONRestoreDVOChip(pScrn, output); RADEONRestoreFP2Registers(pScrn, info->ModeReg); + RADEONRestoreDVOChip(pScrn, output); } } break; diff --git a/src/radeon_bios.c b/src/radeon_bios.c index a85ad46d..a4181aa2 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -1164,6 +1164,46 @@ Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output) return FALSE; } +static RADEONI2CBusRec +RADEONLookupI2CBlock(ScrnInfoPtr pScrn, int id) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, blocks, i; + RADEONI2CBusRec i2c; + + memset(&i2c, 0, sizeof(RADEONI2CBusRec)); + i2c.valid = FALSE; + + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x70); + if (offset) { + blocks = RADEON_BIOS8(offset + 2); + for (i = 0; i < blocks; i++) { + int i2c_id = RADEON_BIOS8(offset + 3 + (i * 5) + 0); + if (id == i2c_id) { + int reg = RADEON_BIOS16(offset + 3 + (i * 5) + 1) * 4; + int clock_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 3); + int data_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 4); + + i2c.mask_clk_mask = (1 << clock_shift); + i2c.mask_data_mask = (1 << data_shift); + i2c.put_clk_mask = (1 << clock_shift); + i2c.put_data_mask = (1 << data_shift); + i2c.get_clk_mask = (1 << clock_shift); + i2c.get_data_mask = (1 << data_shift); + i2c.mask_clk_reg = reg; + i2c.mask_data_reg = reg; + i2c.put_clk_reg = reg; + i2c.put_data_reg = reg; + i2c.get_clk_reg = reg; + i2c.get_data_reg = reg; + i2c.valid = TRUE; + break; + } + } + } + return i2c; +} + Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; @@ -1175,6 +1215,52 @@ Bool RADEONGetExtTMDSInfoFromBIOS (xf86OutputPtr output) if (info->IsAtomBios) { return FALSE; + } else if (info->IsIGP) { + /* RS4xx TMDS stuff is in the mobile table */ + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42); + if (offset) { + int rev = RADEON_BIOS8(offset); + if (rev >= 6) { + offset = RADEON_BIOS16(offset + 0x17); + if (offset) { + offset = RADEON_BIOS16(offset + 2); + rev = RADEON_BIOS8(offset); + if (offset && (rev > 1)) { + int blocks = RADEON_BIOS8(offset + 3); + int index = offset + 4; + radeon_output->dvo_i2c.valid = FALSE; + while (blocks > 0) { + int id = RADEON_BIOS16(index); + index += 2; + switch (id >> 13) { + case 0: + index += 6; + break; + case 2: + index += 10; + break; + case 3: + index += 2; + break; + case 4: + index += 2; + break; + case 6: + radeon_output->dvo_i2c_slave_addr = + RADEON_BIOS16(index) & 0xff; + index += 2; + radeon_output->dvo_i2c = + RADEONLookupI2CBlock(pScrn, RADEON_BIOS8(index)); + return TRUE; + default: + break; + } + blocks--; + } + } + } + } + } } else { offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); if (offset) { @@ -1226,12 +1312,82 @@ Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output) unsigned char *RADEONMMIO = info->MMIO; RADEONOutputPrivatePtr radeon_output = output->driver_private; int offset, index, id; - uint32_t val, reg, andmask, ormask; + uint32_t val, reg, and_mask, or_mask; if (!info->VBIOS) return FALSE; if (info->IsAtomBios) { return FALSE; + } else if (info->IsIGP) { + /* RS4xx TMDS stuff is in the mobile table */ + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42); + if (offset) { + int rev = RADEON_BIOS8(offset); + if (rev >= 6) { + offset = RADEON_BIOS16(offset + 0x17); + if (offset) { + offset = RADEON_BIOS16(offset + 2); + rev = RADEON_BIOS8(offset); + if (offset && (rev > 1)) { + int blocks = RADEON_BIOS8(offset + 3); + index = offset + 4; + while (blocks > 0) { + id = RADEON_BIOS16(index); + index += 2; + switch (id >> 13) { + case 0: + reg = (id & 0x1fff) * 4; + val = RADEON_BIOS32(index); + index += 4; + ErrorF("MMIO: 0x%x 0x%x\n", + (unsigned)reg, (unsigned)val); + OUTREG(reg, val); + break; + case 2: + reg = (id & 0x1fff) * 4; + and_mask = RADEON_BIOS32(index); + index += 4; + or_mask = RADEON_BIOS32(index); + index += 4; + ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n", + (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); + val = INREG(reg); + val = (val & and_mask) | or_mask; + OUTREG(reg, val); + break; + case 3: + val = RADEON_BIOS16(index); + index += 2; + ErrorF("delay: %u\n", (unsigned)val); + usleep(val); + break; + case 4: + val = RADEON_BIOS16(index); + index += 2; + ErrorF("delay: %u\n", (unsigned)val * 1000); + usleep(val * 1000); + break; + case 6: + index++; + reg = RADEON_BIOS8(index); + index++; + val = RADEON_BIOS8(index); + index++; + ErrorF("i2c write: 0x%x, 0x%x\n", (unsigned)reg, + (unsigned)val); + RADEONDVOWriteByte(radeon_output->DVOChip, reg, val); + break; + default: + ErrorF("unknown id %d\n", id>>13); + return FALSE; + } + blocks--; + } + return TRUE; + } + } + } + } } else { offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); if (offset) { @@ -1241,24 +1397,24 @@ Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output) index += 2; switch(id >> 13) { case 0: - reg = id & 0x1fff; + reg = (id & 0x1fff) * 4; val = RADEON_BIOS32(index); index += 4; - ErrorF("WRITE INDEXED: 0x%x 0x%x\n", + ErrorF("MMIO: 0x%x 0x%x\n", (unsigned)reg, (unsigned)val); - /*OUTREG(reg, val);*/ + OUTREG(reg, val); break; case 2: - reg = id & 0x1fff; - andmask = RADEON_BIOS32(index); + reg = (id & 0x1fff) * 4; + and_mask = RADEON_BIOS32(index); index += 4; - ormask = RADEON_BIOS32(index); + or_mask = RADEON_BIOS32(index); index += 4; val = INREG(reg); - val = (val & andmask) | ormask; - ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n", - (unsigned)reg, (unsigned)andmask, (unsigned)ormask); - /*OUTREG(reg, val);*/ + val = (val & and_mask) | or_mask; + ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n", + (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); + OUTREG(reg, val); break; case 4: val = RADEON_BIOS16(index); @@ -1268,15 +1424,15 @@ Bool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output) break; case 5: reg = id & 0x1fff; - andmask = RADEON_BIOS32(index); + and_mask = RADEON_BIOS32(index); index += 4; - ormask = RADEON_BIOS32(index); + or_mask = RADEON_BIOS32(index); index += 4; - ErrorF("MASK PLL: 0x%x 0x%x 0x%x\n", - (unsigned)reg, (unsigned)andmask, (unsigned)ormask); - /*val = INPLL(pScrn, reg); - val = (val & andmask) | ormask; - OUTPLL(pScrn, reg, val);*/ + ErrorF("PLL mask: 0x%x 0x%x 0x%x\n", + (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); + val = INPLL(pScrn, reg); + val = (val & and_mask) | or_mask; + OUTPLL(pScrn, reg, val); break; case 6: reg = id & 0x1fff; |