summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alex@botch2.com>2007-08-05 01:14:36 -0400
committerAlex Deucher <alex@botch2.com>2007-08-05 01:14:36 -0400
commitcc8e1d95f1b90a259beea4e8cc4d7e29af660919 (patch)
tree9ad79275874d7fba86e9cd9cc76ab801acc11650
parentb61a49f2a5401560f85e11bcdd005287433cad12 (diff)
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)
-rw-r--r--src/radeon.h1
-rw-r--r--src/radeon_bios.c261
-rw-r--r--src/radeon_output.c138
-rw-r--r--src/radeon_probe.h18
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
{