diff options
author | Dave Airlie <airlied@linux.ie> | 2007-12-21 09:36:22 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-12-21 09:36:22 +1000 |
commit | 3c31b96afa20913ad947e68fe0c3a662e5eafbdd (patch) | |
tree | 1db77a5ca5bc88876b3f21d35d3ddce3cff0f900 /src/radeon_bios.c | |
parent | eb99c3c5c9a2249cb84920f0f225e525fc3a4144 (diff) | |
parent | f5e8c185001e62e744310667c2d1bd3fe6542a62 (diff) |
Merge remote branch 'origin/atombios-support'
Conflicts:
src/radeon_display.c
src/radeon_driver.c
Diffstat (limited to 'src/radeon_bios.c')
-rw-r--r-- | src/radeon_bios.c | 313 |
1 files changed, 239 insertions, 74 deletions
diff --git a/src/radeon_bios.c b/src/radeon_bios.c index 7d4d12ad..b4a69a35 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -39,8 +39,32 @@ #include "radeon_reg.h" #include "radeon_macros.h" #include "radeon_probe.h" +#include "radeon_atombios.h" #include "vbe.h" +typedef enum +{ + DDC_NONE_DETECTED, + DDC_MONID, + DDC_DVI, + DDC_VGA, + DDC_CRT2, + DDC_LCD, + DDC_GPIO, +} RADEONLegacyDDCType; + +typedef enum +{ + CONNECTOR_NONE_LEGACY, + CONNECTOR_PROPRIETARY_LEGACY, + CONNECTOR_CRT_LEGACY, + CONNECTOR_DVI_I_LEGACY, + CONNECTOR_DVI_D_LEGACY, + CONNECTOR_CTV_LEGACY, + CONNECTOR_STV_LEGACY, + CONNECTOR_UNSUPPORTED_LEGACY +} RADEONLegacyConnectorType; + /* Read the Video BIOS block and the FP registers (if applicable). */ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) { @@ -130,66 +154,115 @@ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) else info->IsAtomBios = FALSE; - if (info->IsAtomBios) - info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s BIOS detected\n", info->IsAtomBios ? "ATOM":"Legacy"); + if (info->IsAtomBios) { +#if 1 + AtomBiosArgRec atomBiosArg; + + if (RHDAtomBiosFunc(pScrn->scrnIndex, NULL, ATOMBIOS_INIT, &atomBiosArg) + == ATOM_SUCCESS) { + info->atomBIOS = atomBiosArg.atomhandle; + } + + atomBiosArg.fb.start = info->FbFreeStart; + atomBiosArg.fb.size = info->FbFreeSize; + if (RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, ATOMBIOS_ALLOCATE_FB_SCRATCH, + &atomBiosArg) == ATOM_SUCCESS) { + + info->FbFreeStart = atomBiosArg.fb.start; + info->FbFreeSize = atomBiosArg.fb.size; + } + + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_ENGINE_CLOCK, + &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_MEMORY_CLOCK, + &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, + GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, + GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, + GET_MAX_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, + GET_MIN_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, + GET_MAX_PIXEL_CLK, &atomBiosArg); + RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, + GET_REF_CLOCK, &atomBiosArg); + +#endif + info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32); + } + return TRUE; } static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); - int offset, i, tmp, tmp0, crtc, portinfo, gpio; + int offset, i, j, tmp, tmp0, id, portinfo, gpio; if (!info->VBIOS) return FALSE; + + if (RADEONGetATOMConnectorInfoFromBIOSObject(pScrn)) + return TRUE; + + if (RADEONGetATOMConnectorInfoFromBIOSConnectorTable(pScrn)) + return TRUE; offset = RADEON_BIOS16(info->MasterDataStart + 22); if (offset) { tmp = RADEON_BIOS16(offset + 4); - for (i = 0; i < 8; i++) { + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { if (tmp & (1 << i)) { + + if (i == ATOM_DEVICE_CV_INDEX) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping Component Video\n"); + info->BiosConnector[i].valid = FALSE; + continue; + } + info->BiosConnector[i].valid = TRUE; portinfo = RADEON_BIOS16(offset + 6 + i * 2); info->BiosConnector[i].DACType = (portinfo & 0xf) - 1; info->BiosConnector[i].ConnectorType = (portinfo >> 4) & 0xf; - crtc = (portinfo >> 8) & 0xf; + id = (portinfo >> 8) & 0xf; tmp0 = RADEON_BIOS16(info->MasterDataStart + 24); - gpio = RADEON_BIOS16(tmp0 + 4 + 27 * crtc) * 4; - switch(gpio) { - case RADEON_GPIO_MONID: - info->BiosConnector[i].DDCType = DDC_MONID; - break; - case RADEON_GPIO_DVI_DDC: - info->BiosConnector[i].DDCType = DDC_DVI; - break; - case RADEON_GPIO_VGA_DDC: - info->BiosConnector[i].DDCType = DDC_VGA; - break; - case RADEON_GPIO_CRT2_DDC: - info->BiosConnector[i].DDCType = DDC_CRT2; - break; - case RADEON_LCD_GPIO_MASK: - info->BiosConnector[i].DDCType = DDC_LCD; - break; - case RADEON_MDGPIO_EN_REG: - info->BiosConnector[i].DDCType = DDC_GPIO; - break; - default: - info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; - break; - } + gpio = RADEON_BIOS16(tmp0 + 4 + 27 * id) * 4; + /* don't assign a gpio for tv */ + if ((i == ATOM_DEVICE_TV1_INDEX) || + (i == ATOM_DEVICE_TV2_INDEX) || + (i == ATOM_DEVICE_CV_INDEX)) + info->BiosConnector[i].ddc_line = 0; + else + info->BiosConnector[i].ddc_line = gpio; - if (i == 3) + info->BiosConnector[i].output_id = id; + info->BiosConnector[i].devices = (1 << i); + + if (i == ATOM_DEVICE_DFP1_INDEX) info->BiosConnector[i].TMDSType = TMDS_INT; - else if (i == 7) + else if (i == ATOM_DEVICE_DFP2_INDEX) + info->BiosConnector[i].TMDSType = TMDS_EXT; + else if (i == ATOM_DEVICE_DFP3_INDEX) info->BiosConnector[i].TMDSType = TMDS_EXT; else info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + /* Always set the connector type to VGA for CRT1/CRT2. if they are + * shared with a DVI port, we'll pick up the DVI connector below when we + * merge the outputs + */ + if ((i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) && + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I || + info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D || + info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A)) { + info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; + } + } else { info->BiosConnector[i].valid = FALSE; } @@ -199,23 +272,39 @@ static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) return FALSE; } - /* DVI-I ports have 2 entries: one for analog, one for digital. combine them */ - if (info->BiosConnector[0].valid && info->BiosConnector[7].valid) { - info->BiosConnector[7].DACType = info->BiosConnector[0].DACType; - info->BiosConnector[0].valid = FALSE; - } - - if (info->BiosConnector[4].valid && info->BiosConnector[3].valid) { - info->BiosConnector[3].DACType = info->BiosConnector[4].DACType; - info->BiosConnector[4].valid = FALSE; + /* CRTs/DFPs may share a port */ + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + for (j = 0; j < RADEON_MAX_BIOS_CONNECTOR; j++) { + if (info->BiosConnector[j].valid && (i != j) ) { + if (info->BiosConnector[i].output_id == info->BiosConnector[j].output_id) { + if (((i == ATOM_DEVICE_DFP1_INDEX) || + (i == ATOM_DEVICE_DFP2_INDEX) || + (i == ATOM_DEVICE_DFP3_INDEX)) && + ((j == ATOM_DEVICE_CRT1_INDEX) || (j == ATOM_DEVICE_CRT2_INDEX))) { + info->BiosConnector[i].DACType = info->BiosConnector[j].DACType; + info->BiosConnector[i].devices |= info->BiosConnector[j].devices; + info->BiosConnector[j].valid = FALSE; + } else if (((j == ATOM_DEVICE_DFP1_INDEX) || + (j == ATOM_DEVICE_DFP2_INDEX) || + (j == ATOM_DEVICE_DFP3_INDEX)) && + ((i == ATOM_DEVICE_CRT1_INDEX) || (i == ATOM_DEVICE_CRT2_INDEX))) { + info->BiosConnector[j].DACType = info->BiosConnector[i].DACType; + info->BiosConnector[j].devices |= info->BiosConnector[i].devices; + info->BiosConnector[i].valid = FALSE; + } + /* other possible combos? */ + } + } + } + } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { if (info->BiosConnector[i].valid) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-0x%x, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, info->BiosConnector[i].ddc_line, info->BiosConnector[i].DACType, info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); } } @@ -227,6 +316,8 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); int offset, i, entry, tmp, tmp0, tmp1; + RADEONLegacyDDCType DDCType; + RADEONLegacyConnectorType ConnectorType; if (!info->VBIOS) return FALSE; @@ -241,7 +332,55 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) info->BiosConnector[i].valid = TRUE; tmp = RADEON_BIOS16(entry); info->BiosConnector[i].ConnectorType = (tmp >> 12) & 0xf; - info->BiosConnector[i].DDCType = (tmp >> 8) & 0xf; + ConnectorType = (tmp >> 12) & 0xf; + switch (ConnectorType) { + case CONNECTOR_PROPRIETARY_LEGACY: + info->BiosConnector[i].ConnectorType = CONNECTOR_LVDS; + break; + case CONNECTOR_CRT_LEGACY: + info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; + break; + case CONNECTOR_DVI_I_LEGACY: + info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; + break; + case CONNECTOR_DVI_D_LEGACY: + info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D; + break; + case CONNECTOR_CTV_LEGACY: + info->BiosConnector[i].ConnectorType = CONNECTOR_CTV; + break; + case CONNECTOR_STV_LEGACY: + info->BiosConnector[i].ConnectorType = CONNECTOR_STV; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown Connector Type: %d\n", ConnectorType); + info->BiosConnector[i].valid = FALSE; + break; + } + DDCType = (tmp >> 8) & 0xf; + switch (DDCType) { + case DDC_MONID: + info->BiosConnector[i].ddc_line = RADEON_GPIO_MONID; + break; + case DDC_DVI: + info->BiosConnector[i].ddc_line = RADEON_GPIO_DVI_DDC; + break; + case DDC_VGA: + info->BiosConnector[i].ddc_line = RADEON_GPIO_VGA_DDC; + break; + 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; + } info->BiosConnector[i].DACType = tmp & 0x1; info->BiosConnector[i].TMDSType = (tmp >> 4) & 0x1; @@ -251,29 +390,22 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) * lets see what happens with that. */ if (info->ChipFamily == CHIP_FAMILY_RS400 && - info->BiosConnector[i].ConnectorType == CONNECTOR_CRT && - info->BiosConnector[i].DDCType == DDC_CRT2) { - info->BiosConnector[i].DDCType = DDC_MONID; + info->BiosConnector[i].ConnectorType == CONNECTOR_VGA && + info->BiosConnector[i].ddc_line == RADEON_GPIO_CRT2_DDC) { + info->BiosConnector[i].ddc_line = RADEON_GPIO_MONID; } /* XPRESS desktop chips seem to have a proprietary connector listed for * DVI-D, try and do the right thing here. */ if ((!info->IsMobility) && - (info->BiosConnector[i].ConnectorType == CONNECTOR_PROPRIETARY)) { + (info->BiosConnector[i].ConnectorType == CONNECTOR_LVDS)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Proprietary connector found, assuming DVI-D\n"); info->BiosConnector[i].DACType = DAC_NONE; info->BiosConnector[i].TMDSType = TMDS_EXT; info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D; } - - if (info->BiosConnector[i].ConnectorType >= CONNECTOR_UNSUPPORTED) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown connector type: %d!\n", - info->BiosConnector[i].ConnectorType); - info->BiosConnector[i].valid = FALSE; - } - } } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); @@ -299,7 +431,7 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40); if (offset) { info->BiosConnector[4].valid = TRUE; - info->BiosConnector[4].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[4].ConnectorType = CONNECTOR_LVDS; info->BiosConnector[4].DACType = DAC_NONE; info->BiosConnector[4].TMDSType = TMDS_NONE; @@ -308,19 +440,36 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) tmp0 = RADEON_BIOS16(tmp + 0x15); if (tmp0) { tmp1 = RADEON_BIOS8(tmp0+2) & 0x07; - if (tmp1) { - info->BiosConnector[4].DDCType = tmp1; - if (info->BiosConnector[4].DDCType > DDC_GPIO) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Unknown DDCType %d found\n", - info->BiosConnector[4].DDCType); - info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + if (tmp1) { + DDCType = tmp1; + switch (DDCType) { + case DDC_MONID: + info->BiosConnector[4].ddc_line = RADEON_GPIO_MONID; + break; + case DDC_DVI: + info->BiosConnector[4].ddc_line = RADEON_GPIO_DVI_DDC; + break; + case DDC_VGA: + info->BiosConnector[4].ddc_line = RADEON_GPIO_VGA_DDC; + break; + case DDC_CRT2: + info->BiosConnector[4].ddc_line = RADEON_GPIO_CRT2_DDC; + break; + case DDC_LCD: + info->BiosConnector[4].ddc_line = RADEON_LCD_GPIO_MASK; + break; + case DDC_GPIO: + info->BiosConnector[4].ddc_line = RADEON_MDGPIO_EN_REG; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); + break; } xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); } } } else { - info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[4].ddc_line = 0; } } } @@ -335,7 +484,7 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) info->BiosConnector[5].ConnectorType = CONNECTOR_STV; info->BiosConnector[5].DACType = DAC_TVDAC; info->BiosConnector[5].TMDSType = TMDS_NONE; - info->BiosConnector[5].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[5].ddc_line = 0; } } } @@ -343,8 +492,8 @@ static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { if (info->BiosConnector[i].valid) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-0x%x, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, info->BiosConnector[i].ddc_line, info->BiosConnector[i].DACType, info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); } } @@ -476,8 +625,19 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) or use a new algorithm to calculate from min_input and max_input */ - pll->min_pll_freq = RADEON_BIOS16 (pll_info_block + 78); - pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 32); + pll->pll_out_min = RADEON_BIOS16 (pll_info_block + 78); + pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 32); + + if (pll->pll_out_min == 0) { + if (IS_AVIVO_VARIANT) + pll->pll_out_min = 64800; + else + pll->pll_out_min = 20000; + } + + pll->pll_in_min = RADEON_BIOS16 (pll_info_block + 74); + pll->pll_in_max = RADEON_BIOS16 (pll_info_block + 76); + pll->xclk = RADEON_BIOS16 (pll_info_block + 72); info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0; @@ -487,8 +647,13 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e); pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10); - pll->min_pll_freq = RADEON_BIOS32 (pll_info_block + 0x12); - pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 0x16); + pll->pll_out_min = RADEON_BIOS32 (pll_info_block + 0x12); + pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 0x16); + + /* not available in the bios */ + pll->pll_in_min = 40; + pll->pll_in_max = 500; + pll->xclk = RADEON_BIOS16 (pll_info_block + 0x08); info->sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0; @@ -501,8 +666,8 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %u, " "max_pll: %u, xclk: %d, sclk: %f, mclk: %f\n", - pll->reference_freq, (unsigned)pll->min_pll_freq, - (unsigned)pll->max_pll_freq, pll->xclk, info->sclk, + pll->reference_freq, (unsigned)pll->pll_out_min, + (unsigned)pll->pll_out_max, pll->xclk, info->sclk, info->mclk); return TRUE; |