diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c index 3f2e113..4156857 100644 --- a/src/atombios_crtc.c +++ b/src/atombios_crtc.c @@ -199,13 +199,108 @@ atombios_set_crtc_timing(atomBiosHandlePtr atomBIOS, SET_CRTC_TIMING_PARAMETERS_ return ATOM_NOT_IMPLEMENTED; } +static AtomBiosResult +atombios_enable_spread_spectrum(xf86CrtcPtr crtc, Bool enable) +{ + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(crtc->scrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + unsigned char *space; + AtomBiosArgRec data; + int major, minor, i; + int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); + xf86OutputPtr output; + RADEONOutputPrivatePtr radeon_output = NULL; + ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION ss_param; + ENABLE_LVDS_SS_PARAMETERS *ss_ptr; + ENABLE_LVDS_SS_PARAMETERS_V2 *ss2_ptr; + ENABLE_SPREAD_SPECTRUM_ON_PPLL *ss_ppll_ptr; + + memset(&ss_param, 0, sizeof(ss_param)); + + atombios_get_command_table_version(info->atomBIOS, index, &major, &minor); + + /* cloning ??? */ + for (i = 0; i < xf86_config->num_output; i++) { + output = xf86_config->output[i]; + if (output->crtc == crtc) { + radeon_output = output->driver_private; + break; + } + } + + if (radeon_output == NULL) + return ATOM_NOT_IMPLEMENTED; + + /*ErrorF("table is %d %d\n", major, minor);*/ + switch(major) { + case 1: + switch(minor) { + case 1: + ss_ptr = (ENABLE_LVDS_SS_PARAMETERS*)&ss_param.usSpreadSpectrumPercentage; + if (enable) + ss_ptr->ucEnable = ATOM_ENABLE; + else + ss_ptr->ucEnable = ATOM_DISABLE; + if (radeon_output->ss_info.valid) { + ss_ptr->usSpreadSpectrumPercentage = cpu_to_le16(radeon_output->ss_info.ss_precentage); + ss_ptr->ucSpreadSpectrumType = radeon_output->ss_info.ss_type; + ss_ptr->ucSpreadSpectrumStepSize_Delay = (((radeon_output->ss_info.ss_step & 0x3) << 2) | + ((radeon_output->ss_info.ss_delay & 0x7) << 4)); + } + break; + case 2: + ss2_ptr = (ENABLE_LVDS_SS_PARAMETERS_V2*)&ss_param.usSpreadSpectrumPercentage; + if (enable) + ss2_ptr->ucEnable = ATOM_ENABLE; + else + ss2_ptr->ucEnable = ATOM_DISABLE; + if (radeon_output->ss_info.valid) { + ss2_ptr->usSpreadSpectrumPercentage = cpu_to_le16(radeon_output->ss_info.ss_precentage); + ss2_ptr->ucSpreadSpectrumType = radeon_output->ss_info.ss_type; + ss2_ptr->ucSpreadSpectrumStep = radeon_output->ss_info.ss_step; + ss2_ptr->ucSpreadSpectrumDelay = radeon_output->ss_info.ss_delay; + ss2_ptr->ucSpreadSpectrumRange = radeon_output->ss_info.ss_range; + } + break; + default: + ss_ppll_ptr = (ENABLE_SPREAD_SPECTRUM_ON_PPLL*)&ss_param.usSpreadSpectrumPercentage; + if (enable) + ss_ppll_ptr->ucEnable = ATOM_ENABLE; + else + ss_ppll_ptr->ucEnable = ATOM_DISABLE; + ss_ppll_ptr->ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; + if (radeon_output->ss_info.valid) { + ss_ppll_ptr->usSpreadSpectrumPercentage = cpu_to_le16(radeon_output->ss_info.ss_precentage); + ss_ppll_ptr->ucSpreadSpectrumType = radeon_output->ss_info.ss_type; + ss_ppll_ptr->ucSpreadSpectrumStep = radeon_output->ss_info.ss_step; + ss_ppll_ptr->ucSpreadSpectrumDelay = radeon_output->ss_info.ss_delay; + ss_ppll_ptr->ucSpreadSpectrumRange = radeon_output->ss_info.ss_range; + } + break; + } + break; + } + + data.exec.index = index; + data.exec.dataSpace = (void *)&space; + data.exec.pspace = &ss_param; + + if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { + ErrorF("%s spread spectrum success\n", enable? "Enable":"Disable"); + return ATOM_SUCCESS ; + } + + ErrorF("Spread Spectrum setup failed\n"); + return ATOM_NOT_IMPLEMENTED; +} + void atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags) { RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; RADEONInfoPtr info = RADEONPTR(crtc->scrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - unsigned char *RADEONMMIO = info->MMIO; int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); uint32_t sclock = mode->Clock; uint32_t ref_div = 0, fb_div = 0, post_div = 0; @@ -234,13 +329,7 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags) sclock = temp; /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */ - if (radeon_crtc->crtc_id == 0) { - temp = INREG(AVIVO_P1PLL_INT_SS_CNTL); - OUTREG(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1); - } else { - temp = INREG(AVIVO_P2PLL_INT_SS_CNTL); - OUTREG(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1); - } + atombios_enable_spread_spectrum(crtc, FALSE); } else { sclock = save->dot_clock_freq; fb_div = save->feedback_div; @@ -351,6 +440,8 @@ atombios_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode, int pll_flags) if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { ErrorF("Set CRTC PLL success\n"); + if (radeon_output->MonType == MT_LCD) + atombios_enable_spread_spectrum(crtc, TRUE); return; } diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index 13eb1fc..9dadf5c 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -1667,6 +1667,39 @@ RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn) return TRUE; } +static RADEONSSRec +RADEONGetATOMSSInfo(ScrnInfoPtr pScrn, int id) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + atomDataTablesPtr atomDataPtr; + ATOM_SPREAD_SPECTRUM_ASSIGNMENT ss_info; + RADEONSSRec ss; + uint8_t crev, frev; + + memset(&ss, 0, sizeof(RADEONSSRec)); + ss.valid = FALSE; + + atomDataPtr = info->atomBIOS->atomDataPtr; + + if (!rhdAtomGetTableRevisionAndSize( + &(atomDataPtr->PPLL_SS_Info->sHeader), + &crev,&frev,NULL)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No SS Info Table found!\n"); + return ss; + } + + ss_info = atomDataPtr->PPLL_SS_Info->asSS_Info[id]; + ss.ss_precentage = le16_to_cpu(ss_info.usSpreadSpectrumPercentage); + ss.ss_type = ss_info.ucSpreadSpectrumType; + ss.ss_step = ss_info.ucSS_Step; + ss.ss_delay = ss_info.ucSS_Delay; + ss.ss_range = ss_info.ucSS_Range; + ss.ss_refdiv = ss_info.ucRecommandedRef_Div; + ss.valid = TRUE; + + return ss; +} + Bool RADEONGetATOMLVDSInfo(xf86OutputPtr output) { @@ -1720,6 +1753,8 @@ RADEONGetATOMLVDSInfo(xf86OutputPtr output) radeon_output->Flags = 0; + radeon_output->ss_info = RADEONGetATOMSSInfo(pScrn, radeon_output->lvds_ss_id); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LVDS Info:\n" "XRes: %d, YRes: %d, DotClock: %d\n" diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h index fbe8dd5..d0f9793 100644 --- a/src/radeon_atombios.h +++ b/src/radeon_atombios.h @@ -219,7 +219,7 @@ typedef struct _atomDataTables /**/unsigned char *PowerPlayInfo; COMPASSIONATE_DATA *CompassionateData; ATOM_DISPLAY_DEVICE_PRIORITY_INFO *SaveRestoreInfo; -/**/unsigned char *PPLL_SS_Info; + ATOM_SPREAD_SPECTRUM_INFO *PPLL_SS_Info; ATOM_OEM_INFO *OemInfo; ATOM_XTMDS_INFO *XTMDS_Info; ATOM_ASIC_MVDD_INFO *MclkSS_Info; diff --git a/src/radeon_probe.h b/src/radeon_probe.h index c14241e..58d6702 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -184,6 +184,17 @@ typedef struct Bool hw_capable; } RADEONI2CBusRec, *RADEONI2CBusPtr; +typedef struct +{ + Bool valid; + uint16_t ss_precentage; + uint8_t ss_type; + uint8_t ss_step; + uint8_t ss_delay; + uint8_t ss_range; + uint8_t ss_refdiv; +} RADEONSSRec, *RADEONSSPtr; + typedef struct _RADEONCrtcPrivateRec { void *crtc_rotate_mem; void *cursor_mem; @@ -241,6 +252,7 @@ typedef struct _RADEONOutputPrivateRec { int PanelPwrDly; int lvds_misc; int lvds_ss_id; + RADEONSSRec ss_info; RADEONTMDSPll tmds_pll[4]; RADEONRMXType rmx_type; /* dvo */