brintos

brintos / linux-shallow public Read only

0
0
Text · 42.8 KiB · 81d58ef Raw
1371 lines · c
1/*2 * Copyright 2011 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: Alex Deucher23 */24 25#include "radeon.h"26#include "radeon_asic.h"27#include "r600d.h"28#include "r600_dpm.h"29#include "atom.h"30 31const u32 r600_utc[R600_PM_NUMBER_OF_TC] = {32	R600_UTC_DFLT_00,33	R600_UTC_DFLT_01,34	R600_UTC_DFLT_02,35	R600_UTC_DFLT_03,36	R600_UTC_DFLT_04,37	R600_UTC_DFLT_05,38	R600_UTC_DFLT_06,39	R600_UTC_DFLT_07,40	R600_UTC_DFLT_08,41	R600_UTC_DFLT_09,42	R600_UTC_DFLT_10,43	R600_UTC_DFLT_11,44	R600_UTC_DFLT_12,45	R600_UTC_DFLT_13,46	R600_UTC_DFLT_14,47};48 49const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = {50	R600_DTC_DFLT_00,51	R600_DTC_DFLT_01,52	R600_DTC_DFLT_02,53	R600_DTC_DFLT_03,54	R600_DTC_DFLT_04,55	R600_DTC_DFLT_05,56	R600_DTC_DFLT_06,57	R600_DTC_DFLT_07,58	R600_DTC_DFLT_08,59	R600_DTC_DFLT_09,60	R600_DTC_DFLT_10,61	R600_DTC_DFLT_11,62	R600_DTC_DFLT_12,63	R600_DTC_DFLT_13,64	R600_DTC_DFLT_14,65};66 67void r600_dpm_print_class_info(u32 class, u32 class2)68{69	const char *s;70 71	switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {72	case ATOM_PPLIB_CLASSIFICATION_UI_NONE:73	default:74		s = "none";75		break;76	case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:77		s = "battery";78		break;79	case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:80		s = "balanced";81		break;82	case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:83		s = "performance";84		break;85	}86	printk("\tui class: %s\n", s);87 88	printk("\tinternal class:");89	if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&90	    (class2 == 0))91		pr_cont(" none");92	else {93		if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)94			pr_cont(" boot");95		if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)96			pr_cont(" thermal");97		if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)98			pr_cont(" limited_pwr");99		if (class & ATOM_PPLIB_CLASSIFICATION_REST)100			pr_cont(" rest");101		if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)102			pr_cont(" forced");103		if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)104			pr_cont(" 3d_perf");105		if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)106			pr_cont(" ovrdrv");107		if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)108			pr_cont(" uvd");109		if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)110			pr_cont(" 3d_low");111		if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)112			pr_cont(" acpi");113		if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)114			pr_cont(" uvd_hd2");115		if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)116			pr_cont(" uvd_hd");117		if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)118			pr_cont(" uvd_sd");119		if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)120			pr_cont(" limited_pwr2");121		if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)122			pr_cont(" ulv");123		if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)124			pr_cont(" uvd_mvc");125	}126	pr_cont("\n");127}128 129void r600_dpm_print_cap_info(u32 caps)130{131	printk("\tcaps:");132	if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)133		pr_cont(" single_disp");134	if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)135		pr_cont(" video");136	if (caps & ATOM_PPLIB_DISALLOW_ON_DC)137		pr_cont(" no_dc");138	pr_cont("\n");139}140 141void r600_dpm_print_ps_status(struct radeon_device *rdev,142			      struct radeon_ps *rps)143{144	printk("\tstatus:");145	if (rps == rdev->pm.dpm.current_ps)146		pr_cont(" c");147	if (rps == rdev->pm.dpm.requested_ps)148		pr_cont(" r");149	if (rps == rdev->pm.dpm.boot_ps)150		pr_cont(" b");151	pr_cont("\n");152}153 154u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)155{156	struct drm_device *dev = rdev_to_drm(rdev);157	struct drm_crtc *crtc;158	struct radeon_crtc *radeon_crtc;159	u32 vblank_in_pixels;160	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */161 162	if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {163		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {164			radeon_crtc = to_radeon_crtc(crtc);165			if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {166				vblank_in_pixels =167					radeon_crtc->hw_mode.crtc_htotal *168					(radeon_crtc->hw_mode.crtc_vblank_end -169					 radeon_crtc->hw_mode.crtc_vdisplay +170					 (radeon_crtc->v_border * 2));171 172				vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock;173				break;174			}175		}176	}177 178	return vblank_time_us;179}180 181u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)182{183	struct drm_device *dev = rdev_to_drm(rdev);184	struct drm_crtc *crtc;185	struct radeon_crtc *radeon_crtc;186	u32 vrefresh = 0;187 188	if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {189		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {190			radeon_crtc = to_radeon_crtc(crtc);191			if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {192				vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode);193				break;194			}195		}196	}197	return vrefresh;198}199 200void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,201			    u32 *p, u32 *u)202{203	u32 b_c = 0;204	u32 i_c;205	u32 tmp;206 207	i_c = (i * r_c) / 100;208	tmp = i_c >> p_b;209 210	while (tmp) {211		b_c++;212		tmp >>= 1;213	}214 215	*u = (b_c + 1) / 2;216	*p = i_c / (1 << (2 * (*u)));217}218 219int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)220{221	u32 k, a, ah, al;222	u32 t1;223 224	if ((fl == 0) || (fh == 0) || (fl > fh))225		return -EINVAL;226 227	k = (100 * fh) / fl;228	t1 = (t * (k - 100));229	a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100));230	a = (a + 5) / 10;231	ah = ((a * t) + 5000) / 10000;232	al = a - ah;233 234	*th = t - ah;235	*tl = t + al;236 237	return 0;238}239 240void r600_gfx_clockgating_enable(struct radeon_device *rdev, bool enable)241{242	int i;243 244	if (enable) {245		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);246	} else {247		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);248 249		WREG32(CG_RLC_REQ_AND_RSP, 0x2);250 251		for (i = 0; i < rdev->usec_timeout; i++) {252			if (((RREG32(CG_RLC_REQ_AND_RSP) & CG_RLC_RSP_TYPE_MASK) >> CG_RLC_RSP_TYPE_SHIFT) == 1)253				break;254			udelay(1);255		}256 257		WREG32(CG_RLC_REQ_AND_RSP, 0x0);258 259		WREG32(GRBM_PWR_CNTL, 0x1);260		RREG32(GRBM_PWR_CNTL);261	}262}263 264void r600_dynamicpm_enable(struct radeon_device *rdev, bool enable)265{266	if (enable)267		WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);268	else269		WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);270}271 272void r600_enable_thermal_protection(struct radeon_device *rdev, bool enable)273{274	if (enable)275		WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);276	else277		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);278}279 280void r600_enable_acpi_pm(struct radeon_device *rdev)281{282	WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);283}284 285void r600_enable_dynamic_pcie_gen2(struct radeon_device *rdev, bool enable)286{287	if (enable)288		WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE);289	else290		WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE);291}292 293bool r600_dynamicpm_enabled(struct radeon_device *rdev)294{295	if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN)296		return true;297	else298		return false;299}300 301void r600_enable_sclk_control(struct radeon_device *rdev, bool enable)302{303	if (enable)304		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);305	else306		WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);307}308 309void r600_enable_mclk_control(struct radeon_device *rdev, bool enable)310{311	if (enable)312		WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF);313	else314		WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF);315}316 317void r600_enable_spll_bypass(struct radeon_device *rdev, bool enable)318{319	if (enable)320		WREG32_P(CG_SPLL_FUNC_CNTL, SPLL_BYPASS_EN, ~SPLL_BYPASS_EN);321	else322		WREG32_P(CG_SPLL_FUNC_CNTL, 0, ~SPLL_BYPASS_EN);323}324 325void r600_wait_for_spll_change(struct radeon_device *rdev)326{327	int i;328 329	for (i = 0; i < rdev->usec_timeout; i++) {330		if (RREG32(CG_SPLL_FUNC_CNTL) & SPLL_CHG_STATUS)331			break;332		udelay(1);333	}334}335 336void r600_set_bsp(struct radeon_device *rdev, u32 u, u32 p)337{338	WREG32(CG_BSP, BSP(p) | BSU(u));339}340 341void r600_set_at(struct radeon_device *rdev,342		 u32 l_to_m, u32 m_to_h,343		 u32 h_to_m, u32 m_to_l)344{345	WREG32(CG_RT, FLS(l_to_m) | FMS(m_to_h));346	WREG32(CG_LT, FHS(h_to_m) | FMS(m_to_l));347}348 349void r600_set_tc(struct radeon_device *rdev,350		 u32 index, u32 u_t, u32 d_t)351{352	WREG32(CG_FFCT_0 + (index * 4), UTC_0(u_t) | DTC_0(d_t));353}354 355void r600_select_td(struct radeon_device *rdev,356		    enum r600_td td)357{358	if (td == R600_TD_AUTO)359		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);360	else361		WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);362	if (td == R600_TD_UP)363		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);364	if (td == R600_TD_DOWN)365		WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);366}367 368void r600_set_vrc(struct radeon_device *rdev, u32 vrv)369{370	WREG32(CG_FTV, vrv);371}372 373void r600_set_tpu(struct radeon_device *rdev, u32 u)374{375	WREG32_P(CG_TPC, TPU(u), ~TPU_MASK);376}377 378void r600_set_tpc(struct radeon_device *rdev, u32 c)379{380	WREG32_P(CG_TPC, TPCC(c), ~TPCC_MASK);381}382 383void r600_set_sstu(struct radeon_device *rdev, u32 u)384{385	WREG32_P(CG_SSP, CG_SSTU(u), ~CG_SSTU_MASK);386}387 388void r600_set_sst(struct radeon_device *rdev, u32 t)389{390	WREG32_P(CG_SSP, CG_SST(t), ~CG_SST_MASK);391}392 393void r600_set_git(struct radeon_device *rdev, u32 t)394{395	WREG32_P(CG_GIT, CG_GICST(t), ~CG_GICST_MASK);396}397 398void r600_set_fctu(struct radeon_device *rdev, u32 u)399{400	WREG32_P(CG_FC_T, FC_TU(u), ~FC_TU_MASK);401}402 403void r600_set_fct(struct radeon_device *rdev, u32 t)404{405	WREG32_P(CG_FC_T, FC_T(t), ~FC_T_MASK);406}407 408void r600_set_ctxcgtt3d_rphc(struct radeon_device *rdev, u32 p)409{410	WREG32_P(CG_CTX_CGTT3D_R, PHC(p), ~PHC_MASK);411}412 413void r600_set_ctxcgtt3d_rsdc(struct radeon_device *rdev, u32 s)414{415	WREG32_P(CG_CTX_CGTT3D_R, SDC(s), ~SDC_MASK);416}417 418void r600_set_vddc3d_oorsu(struct radeon_device *rdev, u32 u)419{420	WREG32_P(CG_VDDC3D_OOR, SU(u), ~SU_MASK);421}422 423void r600_set_vddc3d_oorphc(struct radeon_device *rdev, u32 p)424{425	WREG32_P(CG_VDDC3D_OOR, PHC(p), ~PHC_MASK);426}427 428void r600_set_vddc3d_oorsdc(struct radeon_device *rdev, u32 s)429{430	WREG32_P(CG_VDDC3D_OOR, SDC(s), ~SDC_MASK);431}432 433void r600_set_mpll_lock_time(struct radeon_device *rdev, u32 lock_time)434{435	WREG32_P(MPLL_TIME, MPLL_LOCK_TIME(lock_time), ~MPLL_LOCK_TIME_MASK);436}437 438void r600_set_mpll_reset_time(struct radeon_device *rdev, u32 reset_time)439{440	WREG32_P(MPLL_TIME, MPLL_RESET_TIME(reset_time), ~MPLL_RESET_TIME_MASK);441}442 443void r600_engine_clock_entry_enable(struct radeon_device *rdev,444				    u32 index, bool enable)445{446	if (enable)447		WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2),448			 STEP_0_SPLL_ENTRY_VALID, ~STEP_0_SPLL_ENTRY_VALID);449	else450		WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2),451			 0, ~STEP_0_SPLL_ENTRY_VALID);452}453 454void r600_engine_clock_entry_enable_pulse_skipping(struct radeon_device *rdev,455						   u32 index, bool enable)456{457	if (enable)458		WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2),459			 STEP_0_SPLL_STEP_ENABLE, ~STEP_0_SPLL_STEP_ENABLE);460	else461		WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2),462			 0, ~STEP_0_SPLL_STEP_ENABLE);463}464 465void r600_engine_clock_entry_enable_post_divider(struct radeon_device *rdev,466						 u32 index, bool enable)467{468	if (enable)469		WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2),470			 STEP_0_POST_DIV_EN, ~STEP_0_POST_DIV_EN);471	else472		WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART2 + (index * 4 * 2),473			 0, ~STEP_0_POST_DIV_EN);474}475 476void r600_engine_clock_entry_set_post_divider(struct radeon_device *rdev,477					      u32 index, u32 divider)478{479	WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2),480		 STEP_0_SPLL_POST_DIV(divider), ~STEP_0_SPLL_POST_DIV_MASK);481}482 483void r600_engine_clock_entry_set_reference_divider(struct radeon_device *rdev,484						   u32 index, u32 divider)485{486	WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2),487		 STEP_0_SPLL_REF_DIV(divider), ~STEP_0_SPLL_REF_DIV_MASK);488}489 490void r600_engine_clock_entry_set_feedback_divider(struct radeon_device *rdev,491						  u32 index, u32 divider)492{493	WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2),494		 STEP_0_SPLL_FB_DIV(divider), ~STEP_0_SPLL_FB_DIV_MASK);495}496 497void r600_engine_clock_entry_set_step_time(struct radeon_device *rdev,498					   u32 index, u32 step_time)499{500	WREG32_P(SCLK_FREQ_SETTING_STEP_0_PART1 + (index * 4 * 2),501		 STEP_0_SPLL_STEP_TIME(step_time), ~STEP_0_SPLL_STEP_TIME_MASK);502}503 504void r600_vid_rt_set_ssu(struct radeon_device *rdev, u32 u)505{506	WREG32_P(VID_RT, SSTU(u), ~SSTU_MASK);507}508 509void r600_vid_rt_set_vru(struct radeon_device *rdev, u32 u)510{511	WREG32_P(VID_RT, VID_CRTU(u), ~VID_CRTU_MASK);512}513 514void r600_vid_rt_set_vrt(struct radeon_device *rdev, u32 rt)515{516	WREG32_P(VID_RT, VID_CRT(rt), ~VID_CRT_MASK);517}518 519void r600_voltage_control_enable_pins(struct radeon_device *rdev,520				      u64 mask)521{522	WREG32(LOWER_GPIO_ENABLE, mask & 0xffffffff);523	WREG32(UPPER_GPIO_ENABLE, upper_32_bits(mask));524}525 526 527void r600_voltage_control_program_voltages(struct radeon_device *rdev,528					   enum r600_power_level index, u64 pins)529{530	u32 tmp, mask;531	u32 ix = 3 - (3 & index);532 533	WREG32(CTXSW_VID_LOWER_GPIO_CNTL + (ix * 4), pins & 0xffffffff);534 535	mask = 7 << (3 * ix);536	tmp = RREG32(VID_UPPER_GPIO_CNTL);537	tmp = (tmp & ~mask) | ((pins >> (32 - (3 * ix))) & mask);538	WREG32(VID_UPPER_GPIO_CNTL, tmp);539}540 541void r600_voltage_control_deactivate_static_control(struct radeon_device *rdev,542						    u64 mask)543{544	u32 gpio;545 546	gpio = RREG32(GPIOPAD_MASK);547	gpio &= ~mask;548	WREG32(GPIOPAD_MASK, gpio);549 550	gpio = RREG32(GPIOPAD_EN);551	gpio &= ~mask;552	WREG32(GPIOPAD_EN, gpio);553 554	gpio = RREG32(GPIOPAD_A);555	gpio &= ~mask;556	WREG32(GPIOPAD_A, gpio);557}558 559void r600_power_level_enable(struct radeon_device *rdev,560			     enum r600_power_level index, bool enable)561{562	u32 ix = 3 - (3 & index);563 564	if (enable)565		WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), CTXSW_FREQ_STATE_ENABLE,566			 ~CTXSW_FREQ_STATE_ENABLE);567	else568		WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), 0,569			 ~CTXSW_FREQ_STATE_ENABLE);570}571 572void r600_power_level_set_voltage_index(struct radeon_device *rdev,573					enum r600_power_level index, u32 voltage_index)574{575	u32 ix = 3 - (3 & index);576 577	WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4),578		 CTXSW_FREQ_VIDS_CFG_INDEX(voltage_index), ~CTXSW_FREQ_VIDS_CFG_INDEX_MASK);579}580 581void r600_power_level_set_mem_clock_index(struct radeon_device *rdev,582					  enum r600_power_level index, u32 mem_clock_index)583{584	u32 ix = 3 - (3 & index);585 586	WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4),587		 CTXSW_FREQ_MCLK_CFG_INDEX(mem_clock_index), ~CTXSW_FREQ_MCLK_CFG_INDEX_MASK);588}589 590void r600_power_level_set_eng_clock_index(struct radeon_device *rdev,591					  enum r600_power_level index, u32 eng_clock_index)592{593	u32 ix = 3 - (3 & index);594 595	WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4),596		 CTXSW_FREQ_SCLK_CFG_INDEX(eng_clock_index), ~CTXSW_FREQ_SCLK_CFG_INDEX_MASK);597}598 599void r600_power_level_set_watermark_id(struct radeon_device *rdev,600				       enum r600_power_level index,601				       enum r600_display_watermark watermark_id)602{603	u32 ix = 3 - (3 & index);604	u32 tmp = 0;605 606	if (watermark_id == R600_DISPLAY_WATERMARK_HIGH)607		tmp = CTXSW_FREQ_DISPLAY_WATERMARK;608	WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), tmp, ~CTXSW_FREQ_DISPLAY_WATERMARK);609}610 611void r600_power_level_set_pcie_gen2(struct radeon_device *rdev,612				    enum r600_power_level index, bool compatible)613{614	u32 ix = 3 - (3 & index);615	u32 tmp = 0;616 617	if (compatible)618		tmp = CTXSW_FREQ_GEN2PCIE_VOLT;619	WREG32_P(CTXSW_PROFILE_INDEX + (ix * 4), tmp, ~CTXSW_FREQ_GEN2PCIE_VOLT);620}621 622enum r600_power_level r600_power_level_get_current_index(struct radeon_device *rdev)623{624	u32 tmp;625 626	tmp = RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK;627	tmp >>= CURRENT_PROFILE_INDEX_SHIFT;628	return tmp;629}630 631enum r600_power_level r600_power_level_get_target_index(struct radeon_device *rdev)632{633	u32 tmp;634 635	tmp = RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_PROFILE_INDEX_MASK;636	tmp >>= TARGET_PROFILE_INDEX_SHIFT;637	return tmp;638}639 640void r600_power_level_set_enter_index(struct radeon_device *rdev,641				      enum r600_power_level index)642{643	WREG32_P(TARGET_AND_CURRENT_PROFILE_INDEX, DYN_PWR_ENTER_INDEX(index),644		 ~DYN_PWR_ENTER_INDEX_MASK);645}646 647void r600_wait_for_power_level_unequal(struct radeon_device *rdev,648				       enum r600_power_level index)649{650	int i;651 652	for (i = 0; i < rdev->usec_timeout; i++) {653		if (r600_power_level_get_target_index(rdev) != index)654			break;655		udelay(1);656	}657 658	for (i = 0; i < rdev->usec_timeout; i++) {659		if (r600_power_level_get_current_index(rdev) != index)660			break;661		udelay(1);662	}663}664 665void r600_wait_for_power_level(struct radeon_device *rdev,666			       enum r600_power_level index)667{668	int i;669 670	for (i = 0; i < rdev->usec_timeout; i++) {671		if (r600_power_level_get_target_index(rdev) == index)672			break;673		udelay(1);674	}675 676	for (i = 0; i < rdev->usec_timeout; i++) {677		if (r600_power_level_get_current_index(rdev) == index)678			break;679		udelay(1);680	}681}682 683void r600_start_dpm(struct radeon_device *rdev)684{685	r600_enable_sclk_control(rdev, false);686	r600_enable_mclk_control(rdev, false);687 688	r600_dynamicpm_enable(rdev, true);689 690	radeon_wait_for_vblank(rdev, 0);691	radeon_wait_for_vblank(rdev, 1);692 693	r600_enable_spll_bypass(rdev, true);694	r600_wait_for_spll_change(rdev);695	r600_enable_spll_bypass(rdev, false);696	r600_wait_for_spll_change(rdev);697 698	r600_enable_spll_bypass(rdev, true);699	r600_wait_for_spll_change(rdev);700	r600_enable_spll_bypass(rdev, false);701	r600_wait_for_spll_change(rdev);702 703	r600_enable_sclk_control(rdev, true);704	r600_enable_mclk_control(rdev, true);705}706 707void r600_stop_dpm(struct radeon_device *rdev)708{709	r600_dynamicpm_enable(rdev, false);710}711 712int r600_dpm_pre_set_power_state(struct radeon_device *rdev)713{714	return 0;715}716 717void r600_dpm_post_set_power_state(struct radeon_device *rdev)718{719 720}721 722bool r600_is_uvd_state(u32 class, u32 class2)723{724	if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)725		return true;726	if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)727		return true;728	if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)729		return true;730	if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)731		return true;732	if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)733		return true;734	return false;735}736 737static int r600_set_thermal_temperature_range(struct radeon_device *rdev,738					      int min_temp, int max_temp)739{740	int low_temp = 0 * 1000;741	int high_temp = 255 * 1000;742 743	if (low_temp < min_temp)744		low_temp = min_temp;745	if (high_temp > max_temp)746		high_temp = max_temp;747	if (high_temp < low_temp) {748		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);749		return -EINVAL;750	}751 752	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK);753	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK);754	WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK);755 756	rdev->pm.dpm.thermal.min_temp = low_temp;757	rdev->pm.dpm.thermal.max_temp = high_temp;758 759	return 0;760}761 762bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor)763{764	switch (sensor) {765	case THERMAL_TYPE_RV6XX:766	case THERMAL_TYPE_RV770:767	case THERMAL_TYPE_EVERGREEN:768	case THERMAL_TYPE_SUMO:769	case THERMAL_TYPE_NI:770	case THERMAL_TYPE_SI:771	case THERMAL_TYPE_CI:772	case THERMAL_TYPE_KV:773		return true;774	case THERMAL_TYPE_ADT7473_WITH_INTERNAL:775	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:776		return false; /* need special handling */777	case THERMAL_TYPE_NONE:778	case THERMAL_TYPE_EXTERNAL:779	case THERMAL_TYPE_EXTERNAL_GPIO:780	default:781		return false;782	}783}784 785int r600_dpm_late_enable(struct radeon_device *rdev)786{787	int ret;788 789	if (rdev->irq.installed &&790	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {791		ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);792		if (ret)793			return ret;794		rdev->irq.dpm_thermal = true;795		radeon_irq_set(rdev);796	}797 798	return 0;799}800 801union power_info {802	struct _ATOM_POWERPLAY_INFO info;803	struct _ATOM_POWERPLAY_INFO_V2 info_2;804	struct _ATOM_POWERPLAY_INFO_V3 info_3;805	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;806	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;807	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;808	struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;809	struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;810};811 812union fan_info {813	struct _ATOM_PPLIB_FANTABLE fan;814	struct _ATOM_PPLIB_FANTABLE2 fan2;815	struct _ATOM_PPLIB_FANTABLE3 fan3;816};817 818static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependency_table *radeon_table,819					    ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)820{821	int i;822	ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;823 824	radeon_table->entries = kcalloc(atom_table->ucNumEntries,825					sizeof(struct radeon_clock_voltage_dependency_entry),826					GFP_KERNEL);827	if (!radeon_table->entries)828		return -ENOMEM;829 830	entry = &atom_table->entries[0];831	for (i = 0; i < atom_table->ucNumEntries; i++) {832		radeon_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |833			(entry->ucClockHigh << 16);834		radeon_table->entries[i].v = le16_to_cpu(entry->usVoltage);835		entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)836			((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));837	}838	radeon_table->count = atom_table->ucNumEntries;839 840	return 0;841}842 843int r600_get_platform_caps(struct radeon_device *rdev)844{845	struct radeon_mode_info *mode_info = &rdev->mode_info;846	union power_info *power_info;847	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);848	u16 data_offset;849	u8 frev, crev;850 851	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,852				   &frev, &crev, &data_offset))853		return -EINVAL;854	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);855 856	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);857	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);858	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);859 860	return 0;861}862 863/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */864#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12865#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14866#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16867#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18868#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20869#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22870 871int r600_parse_extended_power_table(struct radeon_device *rdev)872{873	struct radeon_mode_info *mode_info = &rdev->mode_info;874	union power_info *power_info;875	union fan_info *fan_info;876	ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;877	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);878	u16 data_offset;879	u8 frev, crev;880	int ret, i;881 882	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,883				   &frev, &crev, &data_offset))884		return -EINVAL;885	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);886 887	/* fan table */888	if (le16_to_cpu(power_info->pplib.usTableSize) >=889	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {890		if (power_info->pplib3.usFanTableOffset) {891			fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +892						      le16_to_cpu(power_info->pplib3.usFanTableOffset));893			rdev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;894			rdev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);895			rdev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);896			rdev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);897			rdev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);898			rdev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);899			rdev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);900			if (fan_info->fan.ucFanTableFormat >= 2)901				rdev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);902			else903				rdev->pm.dpm.fan.t_max = 10900;904			rdev->pm.dpm.fan.cycle_delay = 100000;905			if (fan_info->fan.ucFanTableFormat >= 3) {906				rdev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;907				rdev->pm.dpm.fan.default_max_fan_pwm =908					le16_to_cpu(fan_info->fan3.usFanPWMMax);909				rdev->pm.dpm.fan.default_fan_output_sensitivity = 4836;910				rdev->pm.dpm.fan.fan_output_sensitivity =911					le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);912			}913			rdev->pm.dpm.fan.ucode_fan_control = true;914		}915	}916 917	/* clock dependancy tables, shedding tables */918	if (le16_to_cpu(power_info->pplib.usTableSize) >=919	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {920		if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {921			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)922				(mode_info->atom_context->bios + data_offset +923				 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));924			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,925							       dep_table);926			if (ret)927				return ret;928		}929		if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {930			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)931				(mode_info->atom_context->bios + data_offset +932				 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));933			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,934							       dep_table);935			if (ret) {936				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);937				return ret;938			}939		}940		if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {941			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)942				(mode_info->atom_context->bios + data_offset +943				 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));944			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,945							       dep_table);946			if (ret) {947				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);948				kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);949				return ret;950			}951		}952		if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {953			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)954				(mode_info->atom_context->bios + data_offset +955				 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));956			ret = r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,957							       dep_table);958			if (ret) {959				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);960				kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);961				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries);962				return ret;963			}964		}965		if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {966			ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =967				(ATOM_PPLIB_Clock_Voltage_Limit_Table *)968				(mode_info->atom_context->bios + data_offset +969				 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));970			if (clk_v->ucNumEntries) {971				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =972					le16_to_cpu(clk_v->entries[0].usSclkLow) |973					(clk_v->entries[0].ucSclkHigh << 16);974				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =975					le16_to_cpu(clk_v->entries[0].usMclkLow) |976					(clk_v->entries[0].ucMclkHigh << 16);977				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =978					le16_to_cpu(clk_v->entries[0].usVddc);979				rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =980					le16_to_cpu(clk_v->entries[0].usVddci);981			}982		}983		if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {984			ATOM_PPLIB_PhaseSheddingLimits_Table *psl =985				(ATOM_PPLIB_PhaseSheddingLimits_Table *)986				(mode_info->atom_context->bios + data_offset +987				 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));988			ATOM_PPLIB_PhaseSheddingLimits_Record *entry;989 990			rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =991				kcalloc(psl->ucNumEntries,992					sizeof(struct radeon_phase_shedding_limits_entry),993					GFP_KERNEL);994			if (!rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {995				r600_free_extended_power_table(rdev);996				return -ENOMEM;997			}998 999			entry = &psl->entries[0];1000			for (i = 0; i < psl->ucNumEntries; i++) {1001				rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =1002					le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);1003				rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =1004					le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);1005				rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =1006					le16_to_cpu(entry->usVoltage);1007				entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)1008					((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));1009			}1010			rdev->pm.dpm.dyn_state.phase_shedding_limits_table.count =1011				psl->ucNumEntries;1012		}1013	}1014 1015	/* cac data */1016	if (le16_to_cpu(power_info->pplib.usTableSize) >=1017	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {1018		rdev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);1019		rdev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);1020		rdev->pm.dpm.near_tdp_limit_adjusted = rdev->pm.dpm.near_tdp_limit;1021		rdev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);1022		if (rdev->pm.dpm.tdp_od_limit)1023			rdev->pm.dpm.power_control = true;1024		else1025			rdev->pm.dpm.power_control = false;1026		rdev->pm.dpm.tdp_adjustment = 0;1027		rdev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);1028		rdev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);1029		rdev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);1030		if (power_info->pplib5.usCACLeakageTableOffset) {1031			ATOM_PPLIB_CAC_Leakage_Table *cac_table =1032				(ATOM_PPLIB_CAC_Leakage_Table *)1033				(mode_info->atom_context->bios + data_offset +1034				 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));1035			ATOM_PPLIB_CAC_Leakage_Record *entry;1036			u32 size = cac_table->ucNumEntries * sizeof(struct radeon_cac_leakage_table);1037			rdev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);1038			if (!rdev->pm.dpm.dyn_state.cac_leakage_table.entries) {1039				r600_free_extended_power_table(rdev);1040				return -ENOMEM;1041			}1042			entry = &cac_table->entries[0];1043			for (i = 0; i < cac_table->ucNumEntries; i++) {1044				if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {1045					rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =1046						le16_to_cpu(entry->usVddc1);1047					rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =1048						le16_to_cpu(entry->usVddc2);1049					rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =1050						le16_to_cpu(entry->usVddc3);1051				} else {1052					rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =1053						le16_to_cpu(entry->usVddc);1054					rdev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =1055						le32_to_cpu(entry->ulLeakageValue);1056				}1057				entry = (ATOM_PPLIB_CAC_Leakage_Record *)1058					((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));1059			}1060			rdev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;1061		}1062	}1063 1064	/* ext tables */1065	if (le16_to_cpu(power_info->pplib.usTableSize) >=1066	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {1067		ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)1068			(mode_info->atom_context->bios + data_offset +1069			 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));1070		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&1071			ext_hdr->usVCETableOffset) {1072			VCEClockInfoArray *array = (VCEClockInfoArray *)1073				(mode_info->atom_context->bios + data_offset +1074				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1);1075			ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =1076				(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)1077				(mode_info->atom_context->bios + data_offset +1078				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +1079				 1 + array->ucNumEntries * sizeof(VCEClockInfo));1080			ATOM_PPLIB_VCE_State_Table *states =1081				(ATOM_PPLIB_VCE_State_Table *)1082				(mode_info->atom_context->bios + data_offset +1083				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +1084				 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +1085				 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));1086			ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;1087			ATOM_PPLIB_VCE_State_Record *state_entry;1088			VCEClockInfo *vce_clk;1089			u32 size = limits->numEntries *1090				sizeof(struct radeon_vce_clock_voltage_dependency_entry);1091			rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =1092				kzalloc(size, GFP_KERNEL);1093			if (!rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {1094				r600_free_extended_power_table(rdev);1095				return -ENOMEM;1096			}1097			rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =1098				limits->numEntries;1099			entry = &limits->entries[0];1100			state_entry = &states->entries[0];1101			for (i = 0; i < limits->numEntries; i++) {1102				vce_clk = (VCEClockInfo *)1103					((u8 *)&array->entries[0] +1104					 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));1105				rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =1106					le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);1107				rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =1108					le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);1109				rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =1110					le16_to_cpu(entry->usVoltage);1111				entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)1112					((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));1113			}1114			for (i = 0; i < states->numEntries; i++) {1115				if (i >= RADEON_MAX_VCE_LEVELS)1116					break;1117				vce_clk = (VCEClockInfo *)1118					((u8 *)&array->entries[0] +1119					 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));1120				rdev->pm.dpm.vce_states[i].evclk =1121					le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);1122				rdev->pm.dpm.vce_states[i].ecclk =1123					le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);1124				rdev->pm.dpm.vce_states[i].clk_idx =1125					state_entry->ucClockInfoIndex & 0x3f;1126				rdev->pm.dpm.vce_states[i].pstate =1127					(state_entry->ucClockInfoIndex & 0xc0) >> 6;1128				state_entry = (ATOM_PPLIB_VCE_State_Record *)1129					((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));1130			}1131		}1132		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&1133			ext_hdr->usUVDTableOffset) {1134			UVDClockInfoArray *array = (UVDClockInfoArray *)1135				(mode_info->atom_context->bios + data_offset +1136				 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);1137			ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =1138				(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)1139				(mode_info->atom_context->bios + data_offset +1140				 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +1141				 1 + (array->ucNumEntries * sizeof (UVDClockInfo)));1142			ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;1143			u32 size = limits->numEntries *1144				sizeof(struct radeon_uvd_clock_voltage_dependency_entry);1145			rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =1146				kzalloc(size, GFP_KERNEL);1147			if (!rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {1148				r600_free_extended_power_table(rdev);1149				return -ENOMEM;1150			}1151			rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =1152				limits->numEntries;1153			entry = &limits->entries[0];1154			for (i = 0; i < limits->numEntries; i++) {1155				UVDClockInfo *uvd_clk = (UVDClockInfo *)1156					((u8 *)&array->entries[0] +1157					 (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));1158				rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =1159					le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);1160				rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =1161					le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);1162				rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =1163					le16_to_cpu(entry->usVoltage);1164				entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)1165					((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));1166			}1167		}1168		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&1169			ext_hdr->usSAMUTableOffset) {1170			ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =1171				(ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)1172				(mode_info->atom_context->bios + data_offset +1173				 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);1174			ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;1175			u32 size = limits->numEntries *1176				sizeof(struct radeon_clock_voltage_dependency_entry);1177			rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =1178				kzalloc(size, GFP_KERNEL);1179			if (!rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {1180				r600_free_extended_power_table(rdev);1181				return -ENOMEM;1182			}1183			rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =1184				limits->numEntries;1185			entry = &limits->entries[0];1186			for (i = 0; i < limits->numEntries; i++) {1187				rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =1188					le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);1189				rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =1190					le16_to_cpu(entry->usVoltage);1191				entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)1192					((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));1193			}1194		}1195		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&1196		    ext_hdr->usPPMTableOffset) {1197			ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)1198				(mode_info->atom_context->bios + data_offset +1199				 le16_to_cpu(ext_hdr->usPPMTableOffset));1200			rdev->pm.dpm.dyn_state.ppm_table =1201				kzalloc(sizeof(struct radeon_ppm_table), GFP_KERNEL);1202			if (!rdev->pm.dpm.dyn_state.ppm_table) {1203				r600_free_extended_power_table(rdev);1204				return -ENOMEM;1205			}1206			rdev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;1207			rdev->pm.dpm.dyn_state.ppm_table->cpu_core_number =1208				le16_to_cpu(ppm->usCpuCoreNumber);1209			rdev->pm.dpm.dyn_state.ppm_table->platform_tdp =1210				le32_to_cpu(ppm->ulPlatformTDP);1211			rdev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =1212				le32_to_cpu(ppm->ulSmallACPlatformTDP);1213			rdev->pm.dpm.dyn_state.ppm_table->platform_tdc =1214				le32_to_cpu(ppm->ulPlatformTDC);1215			rdev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =1216				le32_to_cpu(ppm->ulSmallACPlatformTDC);1217			rdev->pm.dpm.dyn_state.ppm_table->apu_tdp =1218				le32_to_cpu(ppm->ulApuTDP);1219			rdev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =1220				le32_to_cpu(ppm->ulDGpuTDP);1221			rdev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =1222				le32_to_cpu(ppm->ulDGpuUlvPower);1223			rdev->pm.dpm.dyn_state.ppm_table->tj_max =1224				le32_to_cpu(ppm->ulTjmax);1225		}1226		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&1227			ext_hdr->usACPTableOffset) {1228			ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =1229				(ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)1230				(mode_info->atom_context->bios + data_offset +1231				 le16_to_cpu(ext_hdr->usACPTableOffset) + 1);1232			ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;1233			u32 size = limits->numEntries *1234				sizeof(struct radeon_clock_voltage_dependency_entry);1235			rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =1236				kzalloc(size, GFP_KERNEL);1237			if (!rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {1238				r600_free_extended_power_table(rdev);1239				return -ENOMEM;1240			}1241			rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =1242				limits->numEntries;1243			entry = &limits->entries[0];1244			for (i = 0; i < limits->numEntries; i++) {1245				rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =1246					le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);1247				rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =1248					le16_to_cpu(entry->usVoltage);1249				entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)1250					((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));1251			}1252		}1253		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&1254			ext_hdr->usPowerTuneTableOffset) {1255			u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +1256					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));1257			ATOM_PowerTune_Table *pt;1258			rdev->pm.dpm.dyn_state.cac_tdp_table =1259				kzalloc(sizeof(struct radeon_cac_tdp_table), GFP_KERNEL);1260			if (!rdev->pm.dpm.dyn_state.cac_tdp_table) {1261				r600_free_extended_power_table(rdev);1262				return -ENOMEM;1263			}1264			if (rev > 0) {1265				ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)1266					(mode_info->atom_context->bios + data_offset +1267					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));1268				rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =1269					le16_to_cpu(ppt->usMaximumPowerDeliveryLimit);1270				pt = &ppt->power_tune_table;1271			} else {1272				ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)1273					(mode_info->atom_context->bios + data_offset +1274					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));1275				rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;1276				pt = &ppt->power_tune_table;1277			}1278			rdev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);1279			rdev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =1280				le16_to_cpu(pt->usConfigurableTDP);1281			rdev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);1282			rdev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =1283				le16_to_cpu(pt->usBatteryPowerLimit);1284			rdev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =1285				le16_to_cpu(pt->usSmallPowerLimit);1286			rdev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =1287				le16_to_cpu(pt->usLowCACLeakage);1288			rdev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =1289				le16_to_cpu(pt->usHighCACLeakage);1290		}1291	}1292 1293	return 0;1294}1295 1296void r600_free_extended_power_table(struct radeon_device *rdev)1297{1298	struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state;1299 1300	kfree(dyn_state->vddc_dependency_on_sclk.entries);1301	kfree(dyn_state->vddci_dependency_on_mclk.entries);1302	kfree(dyn_state->vddc_dependency_on_mclk.entries);1303	kfree(dyn_state->mvdd_dependency_on_mclk.entries);1304	kfree(dyn_state->cac_leakage_table.entries);1305	kfree(dyn_state->phase_shedding_limits_table.entries);1306	kfree(dyn_state->ppm_table);1307	kfree(dyn_state->cac_tdp_table);1308	kfree(dyn_state->vce_clock_voltage_dependency_table.entries);1309	kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);1310	kfree(dyn_state->samu_clock_voltage_dependency_table.entries);1311	kfree(dyn_state->acp_clock_voltage_dependency_table.entries);1312}1313 1314enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev,1315					       u32 sys_mask,1316					       enum radeon_pcie_gen asic_gen,1317					       enum radeon_pcie_gen default_gen)1318{1319	switch (asic_gen) {1320	case RADEON_PCIE_GEN1:1321		return RADEON_PCIE_GEN1;1322	case RADEON_PCIE_GEN2:1323		return RADEON_PCIE_GEN2;1324	case RADEON_PCIE_GEN3:1325		return RADEON_PCIE_GEN3;1326	default:1327		if ((sys_mask & RADEON_PCIE_SPEED_80) && (default_gen == RADEON_PCIE_GEN3))1328			return RADEON_PCIE_GEN3;1329		else if ((sys_mask & RADEON_PCIE_SPEED_50) && (default_gen == RADEON_PCIE_GEN2))1330			return RADEON_PCIE_GEN2;1331		else1332			return RADEON_PCIE_GEN1;1333	}1334	return RADEON_PCIE_GEN1;1335}1336 1337u16 r600_get_pcie_lane_support(struct radeon_device *rdev,1338			       u16 asic_lanes,1339			       u16 default_lanes)1340{1341	switch (asic_lanes) {1342	case 0:1343	default:1344		return default_lanes;1345	case 1:1346		return 1;1347	case 2:1348		return 2;1349	case 4:1350		return 4;1351	case 8:1352		return 8;1353	case 12:1354		return 12;1355	case 16:1356		return 16;1357	}1358}1359 1360u8 r600_encode_pci_lane_width(u32 lanes)1361{1362	static const u8 encoded_lanes[] = {1363		0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 61364	};1365 1366	if (lanes > 16)1367		return 0;1368 1369	return encoded_lanes[lanes];1370}1371