summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/radeon.man6
-rw-r--r--src/AtomBios/includes/atombios.h11
-rw-r--r--src/atombios_crtc.c2
-rw-r--r--src/atombios_output.c53
-rw-r--r--src/radeon.h3
-rw-r--r--src/radeon_atombios.c109
-rw-r--r--src/radeon_atombios.h6
-rw-r--r--src/radeon_driver.c1
8 files changed, 144 insertions, 47 deletions
diff --git a/man/radeon.man b/man/radeon.man
index f8526dff..19ffb94e 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -550,6 +550,12 @@ controller has passed the destination region. It reduces tearing at the cost
of performance.
The default is
.B off.
+.TP
+.BI "Option \*qATOMTvOut\*q \*q" boolean \*q
+This option enables experimental TV-out support for r500 and r600 atombios chips.
+tv-out is experimental and may not function on these chips as well as hoped for.
+The default is
+.B off.
.SH SEE ALSO
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff --git a/src/AtomBios/includes/atombios.h b/src/AtomBios/includes/atombios.h
index 9932b096..7a3afa8d 100644
--- a/src/AtomBios/includes/atombios.h
+++ b/src/AtomBios/includes/atombios.h
@@ -2495,6 +2495,17 @@ typedef struct _ATOM_ANALOG_TV_INFO
ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING];
}ATOM_ANALOG_TV_INFO;
+#define MAX_SUPPORTED_TV_TIMING_V1_2 3
+
+typedef struct _ATOM_ANALOG_TV_INFO_V1_2
+{
+ ATOM_COMMON_TABLE_HEADER sHeader;
+ UCHAR ucTV_SupportedStandard;
+ UCHAR ucTV_BootUpDefaultStandard;
+ UCHAR ucExt_TV_ASIC_ID;
+ UCHAR ucExt_TV_ASIC_SlaveAddr;
+ ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING];
+}ATOM_ANALOG_TV_INFO_V1_2;
/**************************************************************************/
// VRAM usage and their defintions
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 93bf94fa..9a8594a8 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -325,13 +325,11 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags)
spc3_ptr->ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
else if (radeon_output->DACType == DAC_TVDAC)
spc3_ptr->ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
- spc3_ptr->ucEncoderMode = ATOM_ENCODER_MODE_TV;
} else if (radeon_output->MonType == MT_CV) {
if (radeon_output->DACType == DAC_PRIMARY)
spc3_ptr->ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
else if (radeon_output->DACType == DAC_TVDAC)
spc3_ptr->ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
- spc3_ptr->ucEncoderMode = ATOM_ENCODER_MODE_CV;
}
ptr = &spc_param;
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 396af31d..3030a10c 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -62,11 +62,6 @@ atombios_output_dac1_setup(xf86OutputPtr output, DisplayModePtr mode)
disp_data.ucDacStandard = ATOM_DAC1_CV;
else if (OUTPUT_IS_TV) {
switch (radeon_output->tvStd) {
- case TV_STD_NTSC:
- case TV_STD_NTSC_J:
- case TV_STD_PAL_60:
- disp_data.ucDacStandard = ATOM_DAC1_NTSC;
- break;
case TV_STD_PAL:
case TV_STD_PAL_M:
case TV_STD_SCART_PAL:
@@ -74,6 +69,9 @@ atombios_output_dac1_setup(xf86OutputPtr output, DisplayModePtr mode)
case TV_STD_PAL_CN:
disp_data.ucDacStandard = ATOM_DAC1_PAL;
break;
+ case TV_STD_NTSC:
+ case TV_STD_NTSC_J:
+ case TV_STD_PAL_60:
default:
disp_data.ucDacStandard = ATOM_DAC1_NTSC;
break;
@@ -615,9 +613,44 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode)
AtomBiosArgRec data;
unsigned char *space;
+ memset(&disp_data, 0, sizeof(disp_data));
+
disp_data.ucScaler = radeon_crtc->crtc_id;
- if (radeon_output->Flags & RADEON_USE_RMX) {
+ if (OUTPUT_IS_TV) {
+ switch (radeon_output->tvStd) {
+ case TV_STD_NTSC:
+ disp_data.ucTVStandard = ATOM_TV_NTSC;
+ break;
+ case TV_STD_PAL:
+ disp_data.ucTVStandard = ATOM_TV_PAL;
+ break;
+ case TV_STD_PAL_M:
+ disp_data.ucTVStandard = ATOM_TV_PALM;
+ break;
+ case TV_STD_PAL_60:
+ disp_data.ucTVStandard = ATOM_TV_PAL60;
+ break;
+ case TV_STD_NTSC_J:
+ disp_data.ucTVStandard = ATOM_TV_NTSCJ;
+ break;
+ case TV_STD_SCART_PAL:
+ disp_data.ucTVStandard = ATOM_TV_PAL; /* ??? */
+ break;
+ case TV_STD_SECAM:
+ disp_data.ucTVStandard = ATOM_TV_SECAM;
+ break;
+ case TV_STD_PAL_CN:
+ disp_data.ucTVStandard = ATOM_TV_PALCN;
+ break;
+ default:
+ disp_data.ucTVStandard = ATOM_TV_NTSC;
+ break;
+ }
+ disp_data.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
+ ErrorF("Using TV scaler %x %x\n", disp_data.ucTVStandard, disp_data.ucEnable);
+
+ } else if (radeon_output->Flags & RADEON_USE_RMX) {
ErrorF("Using RMX\n");
if (radeon_output->rmx_type == RMX_FULL)
disp_data.ucEnable = ATOM_SCALER_EXPANSION;
@@ -812,8 +845,8 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
/*ErrorF("AGD: cv dpms\n");*/
if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT)
atombios_device_dpms(output, ATOM_DEVICE_CV_SUPPORT, mode);
- } else if (0 /*radeon_output->MonType == MT_STV ||
- radeon_output->MonType == MT_CTV*/) {
+ } else if (radeon_output->MonType == MT_STV ||
+ radeon_output->MonType == MT_CTV) {
/*ErrorF("AGD: tv dpms\n");*/
if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT)
atombios_device_dpms(output, ATOM_DEVICE_TV1_SUPPORT, mode);
@@ -913,11 +946,11 @@ atombios_set_output_crtc_source(xf86OutputPtr output)
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
} else if (OUTPUT_IS_TV) {
if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT)
- crtc_src_param2.ucEncoderID = ATOM_DEVICE_TV1_INDEX;
+ crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_TV;
} else if (radeon_output->MonType == MT_CV) {
if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT)
- crtc_src_param2.ucEncoderID = ATOM_DEVICE_CV_INDEX;
+ crtc_src_param2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_CV;
}
diff --git a/src/radeon.h b/src/radeon.h
index 9f0e55a9..2a6f150e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -205,7 +205,8 @@ typedef enum {
OPTION_IGNORE_LID_STATUS,
OPTION_DEFAULT_TVDAC_ADJ,
OPTION_INT10,
- OPTION_EXA_VSYNC
+ OPTION_EXA_VSYNC,
+ OPTION_ATOM_TVOUT
} RADEONOpts;
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index d6125721..3cd7eae9 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -321,7 +321,7 @@ rhdAtomAnalyzeMasterDataTable(unsigned char *base,
SET_DATA_TABLE(DAC_Info);
SET_DATA_TABLE_VERS(LVDS_Info);
SET_DATA_TABLE(TMDS_Info);
- SET_DATA_TABLE(AnalogTV_Info);
+ SET_DATA_TABLE_VERS(AnalogTV_Info);
SET_DATA_TABLE_VERS(SupportedDevicesInfo);
SET_DATA_TABLE(GPIO_I2C_Info);
SET_DATA_TABLE(VRAM_UsageByFirmware);
@@ -1572,6 +1572,10 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj = NULL;
int i, j;
+ Bool enable_tv = FALSE;
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE))
+ enable_tv = TRUE;
atomDataPtr = info->atomBIOS->atomDataPtr;
if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->Object_Header), &crev, &frev, &size))
@@ -1702,8 +1706,10 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
if (info->BiosConnector[i].ConnectorType == CONNECTOR_DIN ||
info->BiosConnector[i].ConnectorType == CONNECTOR_STV ||
info->BiosConnector[i].ConnectorType == CONNECTOR_CTV)
- //info->BiosConnector[i].devices |= (1 << ATOM_DEVICE_TV1_INDEX);
- info->BiosConnector[i].valid = FALSE;
+ if (enable_tv)
+ info->BiosConnector[i].devices |= (1 << ATOM_DEVICE_TV1_INDEX);
+ else
+ info->BiosConnector[i].valid = FALSE;
else
info->BiosConnector[i].devices |= (1 << ATOM_DEVICE_CRT1_INDEX);
info->BiosConnector[i].DACType = DAC_PRIMARY;
@@ -1716,8 +1722,10 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
if (info->BiosConnector[i].ConnectorType == CONNECTOR_DIN ||
info->BiosConnector[i].ConnectorType == CONNECTOR_STV ||
info->BiosConnector[i].ConnectorType == CONNECTOR_CTV)
- //info->BiosConnector[i].devices |= (1 << ATOM_DEVICE_TV1_INDEX);
- info->BiosConnector[i].valid = FALSE;
+ if (enable_tv)
+ info->BiosConnector[i].devices |= (1 << ATOM_DEVICE_TV1_INDEX);
+ else
+ info->BiosConnector[i].valid = FALSE;
else
info->BiosConnector[i].devices |= (1 << ATOM_DEVICE_CRT2_INDEX);
info->BiosConnector[i].DACType = DAC_TVDAC;
@@ -1842,16 +1850,12 @@ RADEONGetATOMTVInfo(xf86OutputPtr output)
RADEONOutputPrivatePtr radeon_output = output->driver_private;
ATOM_ANALOG_TV_INFO *tv_info;
- tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info;
+ tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info.AnalogTV_Info;
if (!tv_info)
return FALSE;
switch(tv_info->ucTV_BootUpDefaultStandard) {
- case NTSC_SUPPORT:
- radeon_output->default_tvStd = TV_STD_NTSC;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n");
- break;
case NTSCJ_SUPPORT:
radeon_output->default_tvStd = TV_STD_NTSC_J;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n");
@@ -1868,6 +1872,11 @@ RADEONGetATOMTVInfo(xf86OutputPtr output)
radeon_output->default_tvStd = TV_STD_PAL_60;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n");
break;
+ default:
+ case NTSC_SUPPORT:
+ radeon_output->default_tvStd = TV_STD_NTSC;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n");
+ break;
}
radeon_output->tvStd = radeon_output->default_tvStd;
@@ -1909,29 +1918,63 @@ RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_
{
RADEONInfoPtr info = RADEONPTR(pScrn);
ATOM_ANALOG_TV_INFO *tv_info;
+ ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
+ ATOM_DTD_FORMAT *dtd_timings;
+ atomDataTablesPtr atomDataPtr;
+ uint8_t crev, frev;
- tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info;
-
- if (index > MAX_SUPPORTED_TV_TIMING)
+ atomDataPtr = info->atomBIOS->atomDataPtr;
+ if (!rhdAtomGetTableRevisionAndSize(
+ (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info.base),
+ &crev,&frev,NULL)) {
return FALSE;
+ }
- crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
- crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
- crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
- crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
+ switch(crev) {
+ case 1:
+ tv_info = atomDataPtr->AnalogTV_Info.AnalogTV_Info;
+
+ if (index > MAX_SUPPORTED_TV_TIMING)
+ return FALSE;
+
+ crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
+ crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
+ crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
+ crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
+
+ crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
+ crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
+ crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
+ crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
+
+ crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
+
+ crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
+ crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
+ crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
+ crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
+ *pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
+ break;
+ case 2:
+ tv_info_v1_2 = atomDataPtr->AnalogTV_Info.AnalogTV_Info_v1_2;
+ if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
+ return FALSE;
- crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
- crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
- crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
- crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
+ dtd_timings = &tv_info_v1_2->aModeTimings[index];
+ crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
+ crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive);
+ crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
+ crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth);
- crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
+ crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
+ crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive);
+ crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
+ crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth);
- crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
- crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
- crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
- crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
- *pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
+ crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
+ *pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
+ break;
+ }
return TRUE;
}
@@ -1945,6 +1988,10 @@ RADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn)
atomDataTablesPtr atomDataPtr;
uint8_t crev, frev;
int i, j;
+ Bool enable_tv = FALSE;
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE))
+ enable_tv = TRUE;
atomDataPtr = info->atomBIOS->atomDataPtr;
@@ -1965,20 +2012,16 @@ RADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn)
continue;
}
-#if 1
- if (i == ATOM_DEVICE_CV_INDEX) {
+ if (!enable_tv && (i == ATOM_DEVICE_CV_INDEX)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping Component Video\n");
info->BiosConnector[i].valid = FALSE;
continue;
}
-#endif
-#if 1
- if (i == ATOM_DEVICE_TV1_INDEX) {
+ if (!enable_tv && (i == ATOM_DEVICE_TV1_INDEX)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping TV-Out\n");
info->BiosConnector[i].valid = FALSE;
continue;
}
-#endif
info->BiosConnector[i].valid = TRUE;
info->BiosConnector[i].load_detection = TRUE;
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index fbe8dd58..a0163598 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -199,7 +199,11 @@ typedef struct _atomDataTables
ATOM_LVDS_INFO_V12 *LVDS_Info_v12;
} LVDS_Info;
ATOM_TMDS_INFO *TMDS_Info;
- ATOM_ANALOG_TV_INFO *AnalogTV_Info;
+ union {
+ void *base;
+ ATOM_ANALOG_TV_INFO *AnalogTV_Info;
+ ATOM_ANALOG_TV_INFO_V1_2 *AnalogTV_Info_v1_2;
+ } AnalogTV_Info;
union {
void *base;
ATOM_SUPPORTED_DEVICES_INFO *SupportedDevicesInfo;
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index d4148549..e53edbbe 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -192,6 +192,7 @@ static const OptionInfoRec RADEONOptions[] = {
{ OPTION_DEFAULT_TVDAC_ADJ, "DefaultTVDACAdj", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_INT10, "Int10", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_ATOM_TVOUT, "ATOMTVOut", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};