summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2008-10-06 15:07:31 -0400
committerAlex Deucher <alexdeucher@gmail.com>2008-10-06 15:07:31 -0400
commita5c5ce96279d01eb519bfb92b94c06a58acb7f07 (patch)
tree3864acfc0b5979f7b55b97a7579b02f428b28bbf
parentf9826a5694b7adb6920eb5bdf45d840d8fb14d53 (diff)
Refactor atom LCD/DFP output setup
Simplify the code, properly handle dithering, coherent mode, encoding, etc. Should fix bug 17897.
-rw-r--r--src/atombios_output.c201
-rw-r--r--src/radeon_atombios.c65
-rw-r--r--src/radeon_atombios.h3
-rw-r--r--src/radeon_bios.c29
-rw-r--r--src/radeon_output.c3
-rw-r--r--src/radeon_probe.h4
6 files changed, 171 insertions, 134 deletions
diff --git a/src/atombios_output.c b/src/atombios_output.c
index 83b86a79..50e36817 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -206,7 +206,8 @@ atombios_output_tv1_setup(xf86OutputPtr output, DisplayModePtr mode)
int
atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode)
{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
+ ScrnInfoPtr pScrn = output->scrn;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION disp_data;
AtomBiosArgRec data;
unsigned char *space;
@@ -218,7 +219,7 @@ atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode)
else
disp_data.sXTmdsEncoder.ucMisc = 0;
- if (!info->dac6bits)
+ if (pScrn->rgbBits == 8)
disp_data.sXTmdsEncoder.ucMisc |= (1 << 1);
data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
@@ -264,84 +265,107 @@ atombios_output_ddia_setup(xf86OutputPtr output, DisplayModePtr mode)
}
static int
-atombios_output_tmds1_setup(xf86OutputPtr output, DisplayModePtr mode)
+atombios_output_digital_setup(xf86OutputPtr output, int device, DisplayModePtr mode)
{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- TMDS1_ENCODER_CONTROL_PS_ALLOCATION disp_data;
+ RADEONOutputPrivatePtr radeon_output = output->driver_private;
+ ScrnInfoPtr pScrn = output->scrn;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data;
+ LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 disp_data2;
AtomBiosArgRec data;
unsigned char *space;
+ int index;
+ int major, minor;
- disp_data.ucAction = 1;
- if (mode->Clock > 165000)
- disp_data.ucMisc = 1;
- else
- disp_data.ucMisc = 0;
- disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
- data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
-
- if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output TMDS1 setup success\n");
- return ATOM_SUCCESS;
+ switch (device) {
+ case ATOM_DEVICE_DFP1_SUPPORT:
+ index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
+ break;
+ case ATOM_DEVICE_LCD1_SUPPORT:
+ index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+ break;
+ case ATOM_DEVICE_DFP3_SUPPORT:
+ index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
+ break;
+ default:
+ return ATOM_NOT_IMPLEMENTED;
+ break;
}
- ErrorF("Output TMDS1 setup failed\n");
- return ATOM_NOT_IMPLEMENTED;
-
-}
-
-static int
-atombios_output_tmds2_setup(xf86OutputPtr output, DisplayModePtr mode)
-{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- TMDS2_ENCODER_CONTROL_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
-
- disp_data.ucAction = 1;
- if (mode->Clock > 165000)
- disp_data.ucMisc = 1;
- else
- disp_data.ucMisc = 0;
- disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
- data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
- data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
+ atombios_get_command_table_version(info->atomBIOS, index, &major, &minor);
- if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output TMDS2 setup success\n");
- return ATOM_SUCCESS;
+ /*ErrorF("table is %d %d\n", major, minor);*/
+ switch (major) {
+ case 0:
+ case 1:
+ switch (minor) {
+ case 1:
+ disp_data.ucMisc = 0;
+ disp_data.ucAction = PANEL_ENCODER_ACTION_ENABLE;
+ if (radeon_output->type == OUTPUT_HDMI)
+ disp_data.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+ disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
+ if (device == ATOM_DEVICE_DFP1_SUPPORT) {
+ if (radeon_output->lvds_misc & (1 << 0))
+ disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+ if (radeon_output->lvds_misc & (1 << 1))
+ disp_data.ucMisc |= (1 << 1);
+ } else {
+ if (mode->Clock > 165000)
+ disp_data.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+ if (pScrn->rgbBits == 8)
+ disp_data.ucMisc |= (1 << 1);
+ }
+ data.exec.pspace = &disp_data;
+ break;
+ case 2:
+ case 3:
+ disp_data2.ucMisc = 0;
+ disp_data2.ucAction = PANEL_ENCODER_ACTION_ENABLE;
+ if (minor == 3) {
+ if (radeon_output->coherent_mode) {
+ disp_data2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Coherent Mode enabled\n");
+ }
+ }
+ if (radeon_output->type == OUTPUT_HDMI)
+ disp_data2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
+ disp_data2.ucTruncate = 0;
+ disp_data2.ucSpatial = 0;
+ disp_data2.ucTemporal = 0;
+ disp_data2.ucFRC = 0;
+ if (device == ATOM_DEVICE_DFP1_SUPPORT) {
+ if (radeon_output->lvds_misc & (1 << 0))
+ disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+ if (radeon_output->lvds_misc & (1 << 5)) {
+ disp_data2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
+ if (radeon_output->lvds_misc & (1 << 1))
+ disp_data2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
+ }
+ if (radeon_output->lvds_misc & (1 << 6)) {
+ disp_data2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
+ if (radeon_output->lvds_misc & (1 << 1))
+ disp_data2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
+ }
+ } else {
+ if (mode->Clock > 165000)
+ disp_data2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
+ }
+ data.exec.pspace = &disp_data2;
+ break;
+ }
+ break;
}
- ErrorF("Output TMDS2 setup failed\n");
- return ATOM_NOT_IMPLEMENTED;
-}
-
-static int
-atombios_output_lvds_setup(xf86OutputPtr output, DisplayModePtr mode)
-{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- LVDS_ENCODER_CONTROL_PS_ALLOCATION disp_data;
- AtomBiosArgRec data;
- unsigned char *space;
-
- disp_data.ucAction = 1;
- if (mode->Clock > 165000)
- disp_data.ucMisc = 1;
- else
- disp_data.ucMisc = 0;
- disp_data.usPixelClock = cpu_to_le16(mode->Clock / 10);
- data.exec.index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
+ data.exec.index = index;
data.exec.dataSpace = (void *)&space;
- data.exec.pspace = &disp_data;
if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
- ErrorF("Output LVDS setup success\n");
+ ErrorF("Output digital setup success\n");
return ATOM_SUCCESS;
}
- ErrorF("Output LVDS setup failed\n");
+ ErrorF("Output digital setup failed\n");
return ATOM_NOT_IMPLEMENTED;
}
@@ -600,34 +624,6 @@ atombios_output_scaler_setup(xf86OutputPtr output, DisplayModePtr mode)
}
-static void
-dfp_disable_dither(xf86OutputPtr output, int device)
-{
- RADEONInfoPtr info = RADEONPTR(output->scrn);
- unsigned char *RADEONMMIO = info->MMIO;
-
- switch (device) {
- case ATOM_DEVICE_DFP1_SUPPORT:
- OUTREG(AVIVO_TMDSA_BIT_DEPTH_CONTROL, 0); /* TMDSA */
- break;
- case ATOM_DEVICE_DFP2_SUPPORT:
- if ((info->ChipFamily == CHIP_FAMILY_RS600) ||
- (info->ChipFamily == CHIP_FAMILY_RS690) ||
- (info->ChipFamily == CHIP_FAMILY_RS740))
- OUTREG(AVIVO_DDIA_BIT_DEPTH_CONTROL, 0); /* DDIA */
- else
- OUTREG(AVIVO_DVOA_BIT_DEPTH_CONTROL, 0); /* DVO */
- break;
- /*case ATOM_DEVICE_LCD1_SUPPORT:*/ /* LVDS panels need dither enabled */
- case ATOM_DEVICE_DFP3_SUPPORT:
- OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, 0); /* LVTMA */
- break;
- default:
- break;
- }
-
-}
-
static AtomBiosResult
atombios_display_device_control(atomBiosHandlePtr atomBIOS, int device, Bool state)
{
@@ -920,10 +916,8 @@ atombios_output_mode_set(xf86OutputPtr output,
if (IS_DCE3_VARIANT) {
atombios_output_dig1_setup(output, adjusted_mode);
atombios_output_dig1_transmitter_setup(output, adjusted_mode);
- } else {
- atombios_output_tmds1_setup(output, adjusted_mode);
- dfp_disable_dither(output, ATOM_DEVICE_DFP1_SUPPORT);
- }
+ } else
+ atombios_output_digital_setup(output, ATOM_DEVICE_DFP1_SUPPORT, adjusted_mode);
} else if (radeon_output->devices & ATOM_DEVICE_DFP2_SUPPORT) {
if (IS_DCE3_VARIANT) {
// fix me
@@ -934,26 +928,21 @@ atombios_output_mode_set(xf86OutputPtr output,
atombios_output_ddia_setup(output, adjusted_mode);
else
atombios_external_tmds_setup(output, adjusted_mode);
- dfp_disable_dither(output, ATOM_DEVICE_DFP2_SUPPORT);
}
} else if (radeon_output->devices & ATOM_DEVICE_DFP3_SUPPORT) {
if (IS_DCE3_VARIANT) {
atombios_output_dig2_setup(output, adjusted_mode);
atombios_output_dig2_transmitter_setup(output, adjusted_mode);
- } else {
- atombios_output_tmds2_setup(output, adjusted_mode);
- dfp_disable_dither(output, ATOM_DEVICE_DFP3_SUPPORT);
- }
+ } else
+ atombios_output_digital_setup(output, ATOM_DEVICE_DFP3_SUPPORT, adjusted_mode);
}
} else if (radeon_output->MonType == MT_LCD) {
if (radeon_output->devices & ATOM_DEVICE_LCD1_SUPPORT) {
if (IS_DCE3_VARIANT) {
atombios_output_dig2_setup(output, adjusted_mode);
atombios_output_dig2_transmitter_setup(output, adjusted_mode);
- } else {
- atombios_output_lvds_setup(output, adjusted_mode);
- dfp_disable_dither(output, ATOM_DEVICE_LCD1_SUPPORT);
- }
+ } else
+ atombios_output_digital_setup(output, ATOM_DEVICE_LCD1_SUPPORT, adjusted_mode);
}
} else if ((radeon_output->MonType == MT_CTV) ||
(radeon_output->MonType == MT_STV) ||
diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c
index 12aeecae..13eb1fc8 100644
--- a/src/radeon_atombios.c
+++ b/src/radeon_atombios.c
@@ -1668,6 +1668,71 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn)
}
Bool
+RADEONGetATOMLVDSInfo(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONOutputPrivatePtr radeon_output = output->driver_private;
+ atomDataTablesPtr atomDataPtr;
+ uint8_t crev, frev;
+
+ atomDataPtr = info->atomBIOS->atomDataPtr;
+
+ if (!rhdAtomGetTableRevisionAndSize(
+ (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base),
+ &frev,&crev,NULL)) {
+ return FALSE;
+ }
+
+ switch (crev) {
+ case 1:
+ radeon_output->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHActive);
+ radeon_output->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVActive);
+ radeon_output->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usPixClk) * 10;
+ radeon_output->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHBlanking_Time);
+ radeon_output->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncOffset);
+ radeon_output->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncWidth);
+ radeon_output->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVBlanking_Time);
+ radeon_output->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncOffset);
+ radeon_output->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncWidth);
+ radeon_output->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->usOffDelayInMs);
+ radeon_output->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info->ucLVDS_Misc;
+ radeon_output->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info->ucSS_Id;
+ break;
+ case 2:
+ radeon_output->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHActive);
+ radeon_output->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVActive);
+ radeon_output->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usPixClk) * 10;
+ radeon_output->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHBlanking_Time);
+ radeon_output->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncOffset);
+ radeon_output->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncWidth);
+ radeon_output->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVBlanking_Time);
+ radeon_output->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncOffset);
+ radeon_output->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncWidth);
+ radeon_output->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->usOffDelayInMs);
+ radeon_output->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucLVDS_Misc;
+ radeon_output->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucSS_Id;
+ break;
+ }
+
+ if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0)
+ radeon_output->PanelPwrDly = 2000;
+
+ radeon_output->Flags = 0;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "LVDS Info:\n"
+ "XRes: %d, YRes: %d, DotClock: %d\n"
+ "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n"
+ "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n",
+ radeon_output->PanelXRes, radeon_output->PanelYRes, radeon_output->DotClock,
+ radeon_output->HBlank, radeon_output->HOverPlus, radeon_output->HSyncWidth,
+ radeon_output->VBlank, radeon_output->VOverPlus, radeon_output->VSyncWidth);
+
+ return TRUE;
+}
+
+Bool
RADEONGetATOMTVInfo(xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h
index 1ec0e2d7..fbe8dd58 100644
--- a/src/radeon_atombios.h
+++ b/src/radeon_atombios.h
@@ -125,6 +125,9 @@ atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, int enable);
extern Bool
RADEONGetATOMTVInfo(xf86OutputPtr output);
+extern Bool
+RADEONGetATOMLVDSInfo(xf86OutputPtr output);
+
extern int
atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode);
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index b34a4217..22bb5ed8 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -975,30 +975,9 @@ Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output)
if (!info->VBIOS) return FALSE;
- if (info->IsAtomBios) {
- if((tmp = RADEON_BIOS16 (info->MasterDataStart + 16))) {
-
- radeon_output->PanelXRes = RADEON_BIOS16(tmp+6);
- radeon_output->PanelYRes = RADEON_BIOS16(tmp+10);
- radeon_output->DotClock = RADEON_BIOS16(tmp+4)*10;
- radeon_output->HBlank = RADEON_BIOS16(tmp+8);
- radeon_output->HOverPlus = RADEON_BIOS16(tmp+14);
- radeon_output->HSyncWidth = RADEON_BIOS16(tmp+16);
- radeon_output->VBlank = RADEON_BIOS16(tmp+12);
- radeon_output->VOverPlus = RADEON_BIOS16(tmp+18);
- radeon_output->VSyncWidth = RADEON_BIOS16(tmp+20);
- radeon_output->PanelPwrDly = RADEON_BIOS16(tmp+40);
-
- if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0)
- radeon_output->PanelPwrDly = 2000;
-
- radeon_output->Flags = 0;
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "No LVDS Info Table found in BIOS!\n");
- return FALSE;
- }
- } else {
+ if (info->IsAtomBios)
+ return RADEONGetATOMLVDSInfo(output);
+ else {
tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x40);
@@ -1021,7 +1000,7 @@ Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output)
radeon_output->PanelYRes = RADEON_BIOS16(tmp+27);
xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n",
radeon_output->PanelXRes, radeon_output->PanelYRes);
-
+
radeon_output->PanelPwrDly = RADEON_BIOS16(tmp+44);
if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0)
radeon_output->PanelPwrDly = 2000;
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 4947478f..3416edfe 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -1146,8 +1146,7 @@ radeon_create_resources(xf86OutputPtr output)
}
}
- if (IS_DCE3_VARIANT &&
- (OUTPUT_IS_DVI || (radeon_output->type == OUTPUT_HDMI))) {
+ if (OUTPUT_IS_DVI || (radeon_output->type == OUTPUT_HDMI)) {
coherent_mode_atom = MAKE_ATOM("coherent_mode");
range[0] = 0; /* off */
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 83b34284..c14241eb 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -237,8 +237,10 @@ typedef struct _RADEONOutputPrivateRec {
int VSyncWidth;
int VBlank;
int Flags; /* Saved copy of mode flags */
- int PanelPwrDly;
int DotClock;
+ int PanelPwrDly;
+ int lvds_misc;
+ int lvds_ss_id;
RADEONTMDSPll tmds_pll[4];
RADEONRMXType rmx_type;
/* dvo */