From cc8e1d95f1b90a259beea4e8cc4d7e29af660919 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 5 Aug 2007 01:14:36 -0400 Subject: RADEON: Major rework of BIOS table parsing - greatly simplify ATOM and legacy connector table parsing - use bios tables to detect LVDS and TV outputs - add support for TV table parsing (legacy only) --- src/radeon.h | 1 + src/radeon_bios.c | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/radeon_output.c | 138 ++++++++------------------- src/radeon_probe.h | 18 ++-- 4 files changed, 309 insertions(+), 109 deletions(-) diff --git a/src/radeon.h b/src/radeon.h index 7792f31..432ee89 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -875,6 +875,7 @@ extern Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn); extern Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn); extern Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output); extern Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetTVInfoFromBIOS (xf86OutputPtr output); extern Bool RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output); extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, diff --git a/src/radeon_bios.c b/src/radeon_bios.c index 26019ba..b79fea7 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -141,6 +141,175 @@ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) return TRUE; } +static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, i, tmp, tmp0, crtc, portinfo, gpio; + + if (!info->VBIOS) return FALSE; + + offset = RADEON_BIOS16(info->MasterDataStart + 22); + + if (offset) { + tmp = RADEON_BIOS16(offset + 4); + for (i = 0; i < 8; i++) { + if (tmp & (1 << i)) { + 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; + 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; + default: + info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; + break; + } + + if (i == 3) + info->BiosConnector[i].TMDSType = TMDS_INT; + else if (i == 7) + info->BiosConnector[i].TMDSType = TMDS_EXT; + else + info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + + } else { + info->BiosConnector[i].valid = FALSE; + } + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); + return FALSE; + } + + 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, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); + } + } + + return TRUE; +} + +static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, i, entry, tmp, tmp0, tmp1; + + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x50); + if (offset) { + for (i = 0; i < 4; i++) { + entry = offset + 2 + i*2; + + if (!RADEON_BIOS16(entry)) { + break; + } + info->BiosConnector[i].valid = TRUE; + tmp = RADEON_BIOS16(entry); + info->BiosConnector[i].ConnectorType = (tmp >> 12) & 0xf; + info->BiosConnector[i].DDCType = (tmp >> 8) & 0xf; + info->BiosConnector[i].DACType = tmp & 0x3; + if (tmp & 0x10) + info->BiosConnector[i].TMDSType = TMDS_EXT; + else + info->BiosConnector[i].TMDSType = TMDS_INT; + + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); + return FALSE; + } + + /* check LVDS table */ + if (info->IsMobility) { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40); + if (offset) { + info->BiosConnector[4].valid = TRUE; + info->BiosConnector[4].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[4].DACType = DAC_NONE; + info->BiosConnector[4].TMDSType = TMDS_NONE; + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42); + if (tmp) { + 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_LCD) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unknown DDCType %d found\n", + info->BiosConnector[4].DDCType); + info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); + } + } + } else { + info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + } + } + } + + /* check TV table */ + if (info->InternalTVOut) { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); + if (offset) { + if (RADEON_BIOS8(offset + 6) == 'T') { + info->BiosConnector[5].valid = TRUE; + /* assume s-video for now */ + 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; + } + } + } + + 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, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); + } + } + + return TRUE; +} + +Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + + if(!info->VBIOS) return FALSE; + + if (info->IsAtomBios) + return RADEONGetATOMConnectorInfoFromBIOS(pScrn); + else + return RADEONGetLegacyConnectorInfoFromBIOS(pScrn); +} + +#if 0 Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); @@ -350,6 +519,98 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) } return TRUE; } +#endif + +Bool RADEONGetTVInfoFromBIOS (xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int offset, refclk, stds; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + /* no idea where TV table is on ATOM bios */ + return FALSE; + } else { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); + if (offset) { + if (RADEON_BIOS8(offset + 6) == 'T') { + switch (RADEON_BIOS8(offset + 7) & 0xf) { + case 1: + radeon_output->tvStd = TV_STD_NTSC; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); + break; + case 2: + radeon_output->tvStd = TV_STD_PAL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); + break; + case 3: + radeon_output->tvStd = TV_STD_PAL_M; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); + break; + case 4: + radeon_output->tvStd = TV_STD_PAL_60; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); + break; + case 5: + radeon_output->tvStd = TV_STD_NTSC_J; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); + break; + case 6: + radeon_output->tvStd = TV_STD_SCART_PAL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: SCART-PAL\n"); + break; + default: + radeon_output->tvStd = TV_STD_NTSC; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unknown TV standard; defaulting to NTSC\n"); + break; + } + + refclk = (RADEON_BIOS8(offset + 9) >> 2) & 0x3; + if (refclk == 0) + radeon_output->TVRefClk = 29.498928713; /* MHz */ + else if (refclk == 1) + radeon_output->TVRefClk = 28.636360000; + else if (refclk == 2) + radeon_output->TVRefClk = 14.318180000; + else if (refclk == 3) + radeon_output->TVRefClk = 27.000000000; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); + stds = RADEON_BIOS8(offset + 10) & 0x1f; + if (stds & TV_STD_NTSC) { + radeon_output->SupportedTVStds |= TV_STD_NTSC; + ErrorF("NTSC "); + } + if (stds & TV_STD_PAL) { + radeon_output->SupportedTVStds |= TV_STD_PAL; + ErrorF("PAL "); + } + if (stds & TV_STD_PAL_M) { + radeon_output->SupportedTVStds |= TV_STD_PAL_M; + ErrorF("PAL-M "); + } + if (stds & TV_STD_PAL_60) { + radeon_output->SupportedTVStds |= TV_STD_PAL_60; + ErrorF("PAL-60 "); + } + if (stds & TV_STD_NTSC_J) { + radeon_output->SupportedTVStds |= TV_STD_NTSC_J; + ErrorF("NTSC-J "); + } + if (stds & TV_STD_SCART_PAL) { + radeon_output->SupportedTVStds |= TV_STD_SCART_PAL; + ErrorF("SCART-PAL"); + } + ErrorF("\n"); + + return TRUE; + } else + return FALSE; + } + } +} /* Read PLL parameters from BIOS block. Default to typical values if there is no BIOS. */ diff --git a/src/radeon_output.c b/src/radeon_output.c index fa6fb4f..d0225aa 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -611,6 +611,7 @@ radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) { + /* FIXME: Update when more modes are added */ if (pMode->HDisplay == 800 && pMode->VDisplay == 600) return MODE_OK; else @@ -1630,6 +1631,27 @@ RADEONGetTMDSInfo(xf86OutputPtr output) } } +static void +RADEONGetTVInfo(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + + radeon_output->hPos = 0; + radeon_output->vPos = 0; + radeon_output->hSize = 0; + + if (RADEONGetTVInfoFromBIOS(output)) return; + + /* set some reasonable defaults */ + radeon_output->tvStd = TV_STD_NTSC; + radeon_output->TVRefClk = 27.000000000; + radeon_output->SupportedTVStds = TV_STD_NTSC | TV_STD_PAL; + +} + void RADEONInitConnector(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; @@ -1657,12 +1679,11 @@ void RADEONInitConnector(xf86OutputPtr output) if (radeon_output->type == OUTPUT_DVI) { RADEONGetTMDSInfo(output); + } - // FIXME -- this should be done in detect or getmodes - /*if (i == 0) - RADEONGetHardCodedEDIDFromBIOS(output);*/ - - /*RADEONUpdatePanelSize(output);*/ + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + RADEONGetTVInfo(output); } if (radeon_output->DACType == DAC_TVDAC) { @@ -1688,15 +1709,14 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) * If not, we may have problem -- need to use MonitorLayout option. */ for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].valid = FALSE; info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; info->BiosConnector[i].DACType = DAC_UNKNOWN; info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; info->BiosConnector[i].ConnectorType = CONNECTOR_NONE; } - if (!RADEONGetConnectorInfoFromBIOS(pScrn) || - ((info->BiosConnector[0].DDCType == 0) && - (info->BiosConnector[1].DDCType == 0))) { + if (!RADEONGetConnectorInfoFromBIOS(pScrn)) { if (info->IsMobility) { /* Below is the most common setting, but may not be true */ #if defined(__powerpc__) @@ -1712,6 +1732,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) info->BiosConnector[1].DACType = DAC_PRIMARY; info->BiosConnector[1].TMDSType = TMDS_EXT; info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + } else { /* Below is the most common setting, but may not be true */ info->BiosConnector[0].DDCType = DDC_DVI; @@ -1725,6 +1746,13 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; } + if (info->InternalTVOut) { + info->BiosConnector[2].ConnectorType = CONNECTOR_STV; + info->BiosConnector[2].DACType = DAC_TVDAC; + info->BiosConnector[2].TMDSType = TMDS_NONE; + info->BiosConnector[2].DDCType = DDC_NONE_DETECTED; + } + /* Some cards have the DDC lines swapped and we have no way to * detect it yet (Mac cards) */ @@ -1766,7 +1794,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) } for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) { - if (info->BiosConnector[i].ConnectorType != CONNECTOR_NONE) { + if (info->BiosConnector[i].valid) { RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); if (!radeon_output) { return FALSE; @@ -1851,98 +1879,6 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) } } - /* if it's a mobility make sure we have a LVDS port */ - if (info->IsMobility) { - if (info->IsAtomBios) { - if (info->BiosConnector[0].ConnectorType != CONNECTOR_LVDS_ATOM && - info->BiosConnector[1].ConnectorType != CONNECTOR_LVDS_ATOM) { - /* add LVDS port */ - RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); - if (!radeon_output) { - return FALSE; - } - radeon_output->MonType = MT_UNKNOWN; - radeon_output->DDCType = DDC_LCD; - radeon_output->DACType = DAC_NONE; - radeon_output->TMDSType = TMDS_NONE; - radeon_output->ConnectorType = CONNECTOR_LVDS_ATOM; - RADEONSetOutputType(pScrn, radeon_output); - output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); - if (!output) { - return FALSE; - } - output->driver_private = radeon_output; - output->possible_crtcs = 1; - output->possible_clones = 0; - - RADEONInitConnector(output); - - } - } else { - if (info->BiosConnector[0].ConnectorType != CONNECTOR_PROPRIETARY && - info->BiosConnector[1].ConnectorType != CONNECTOR_PROPRIETARY) { - /* add LVDS port */ - RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); - if (!radeon_output) { - return FALSE; - } - radeon_output->MonType = MT_UNKNOWN; - radeon_output->DDCType = DDC_LCD; - radeon_output->DACType = DAC_NONE; - radeon_output->TMDSType = TMDS_NONE; - radeon_output->ConnectorType = CONNECTOR_PROPRIETARY; - RADEONSetOutputType(pScrn, radeon_output); - output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); - if (!output) { - return FALSE; - } - output->driver_private = radeon_output; - output->possible_crtcs = 1; - output->possible_clones = 0; - - RADEONInitConnector(output); - } - } - } - - /* add TV out */ -#if 0 - if (info->InternalTVOut) { - /* need to check the bios tables to see if we really have tv out and what type we have */ - RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); - if (!radeon_output) { - return FALSE; - } - /* hard code type for now */ - radeon_output->MonType = MT_STV; - radeon_output->DDCType = DDC_NONE_DETECTED; - radeon_output->DACType = DAC_TVDAC; - radeon_output->TMDSType = TMDS_NONE; - - /* hard code type for now */ - if (info->IsAtomBios) - radeon_output->ConnectorType = CONNECTOR_STV_ATOM; - else - radeon_output->ConnectorType = CONNECTOR_STV; - - radeon_output->tvStd = TV_STD_NTSC; - radeon_output->hPos = 0; - radeon_output->vPos = 0; - radeon_output->hSize = 0; - - RADEONSetOutputType(pScrn, radeon_output); - output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); - if (!output) { - return FALSE; - } - output->driver_private = radeon_output; - output->possible_crtcs = 1 | 2; - output->possible_clones = 0; - - RADEONInitConnector(output); - } -#endif - return TRUE; } diff --git a/src/radeon_probe.h b/src/radeon_probe.h index f0df341..27b78cc 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -140,13 +140,12 @@ typedef enum /* standards */ typedef enum { - TV_STD_NTSC, - TV_STD_PAL, - TV_STD_PAL_M, - TV_STD_PAL_60, - TV_STD_NTSC_J, - TV_STD_PAL_CN, - TV_STD_PAL_N + TV_STD_NTSC = 1, + TV_STD_PAL = 2, + TV_STD_PAL_M = 4, + TV_STD_PAL_60 = 8, + TV_STD_NTSC_J = 16, + TV_STD_SCART_PAL = 32, } TVStd; typedef struct _RADEONCrtcPrivateRec { @@ -167,6 +166,7 @@ typedef struct { RADEONDacType DACType; RADEONTmdsType TMDSType; RADEONConnectorType ConnectorType; + Bool valid; } RADEONBIOSConnector; typedef struct _RADEONOutputPrivateRec { @@ -201,10 +201,12 @@ typedef struct _RADEONOutputPrivateRec { int hPos; int vPos; int hSize; + float TVRefClk; + int SupportedTVStds; } RADEONOutputPrivateRec, *RADEONOutputPrivatePtr; #define RADEON_MAX_CRTC 2 -#define RADEON_MAX_BIOS_CONNECTOR 2 +#define RADEON_MAX_BIOS_CONNECTOR 8 typedef struct { -- cgit v1.2.3