From a5c5ce96279d01eb519bfb92b94c06a58acb7f07 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 6 Oct 2008 15:07:31 -0400 Subject: Refactor atom LCD/DFP output setup Simplify the code, properly handle dithering, coherent mode, encoding, etc. Should fix bug 17897. --- src/atombios_output.c | 201 ++++++++++++++++++++++++-------------------------- src/radeon_atombios.c | 65 ++++++++++++++++ src/radeon_atombios.h | 3 + src/radeon_bios.c | 29 +------- src/radeon_output.c | 3 +- src/radeon_probe.h | 4 +- 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 @@ -1667,6 +1667,71 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn) return TRUE; } +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) { 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 */ -- cgit v1.2.3