162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Authors: Alex Deucher
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include "radeon.h"
2662306a36Sopenharmony_ci#include "radeon_asic.h"
2762306a36Sopenharmony_ci#include "rv770.h"
2862306a36Sopenharmony_ci#include "rv770d.h"
2962306a36Sopenharmony_ci#include "r600_dpm.h"
3062306a36Sopenharmony_ci#include "rv770_dpm.h"
3162306a36Sopenharmony_ci#include "cypress_dpm.h"
3262306a36Sopenharmony_ci#include "atom.h"
3362306a36Sopenharmony_ci#include "evergreen.h"
3462306a36Sopenharmony_ci#include <linux/seq_file.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F0           0x0a
3762306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F1           0x0b
3862306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F2           0x0c
3962306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F3           0x0d
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define MC_CG_SEQ_DRAMCONF_S0       0x05
4262306a36Sopenharmony_ci#define MC_CG_SEQ_DRAMCONF_S1       0x06
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define PCIE_BUS_CLK                10000
4562306a36Sopenharmony_ci#define TCLK                        (PCIE_BUS_CLK / 10)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define SMC_RAM_END 0xC000
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistruct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	struct rv7xx_ps *ps = rps->ps_priv;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	return ps;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistruct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rdev->pm.dpm.priv;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return pi;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct evergreen_power_info *pi = rdev->pm.dpm.priv;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return pi;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic void rv770_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
7162306a36Sopenharmony_ci					       bool enable)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
7462306a36Sopenharmony_ci	u32 tmp;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
7762306a36Sopenharmony_ci	if (enable) {
7862306a36Sopenharmony_ci		tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
7962306a36Sopenharmony_ci		tmp |= LC_HW_VOLTAGE_IF_CONTROL(1);
8062306a36Sopenharmony_ci		tmp |= LC_GEN2_EN_STRAP;
8162306a36Sopenharmony_ci	} else {
8262306a36Sopenharmony_ci		if (!pi->boot_in_gen2) {
8362306a36Sopenharmony_ci			tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
8462306a36Sopenharmony_ci			tmp &= ~LC_GEN2_EN_STRAP;
8562306a36Sopenharmony_ci		}
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
8862306a36Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
8962306a36Sopenharmony_ci		WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic void rv770_enable_l0s(struct radeon_device *rdev)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	u32 tmp;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL) & ~LC_L0S_INACTIVITY_MASK;
9862306a36Sopenharmony_ci	tmp |= LC_L0S_INACTIVITY(3);
9962306a36Sopenharmony_ci	WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp);
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic void rv770_enable_l1(struct radeon_device *rdev)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	u32 tmp;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL);
10762306a36Sopenharmony_ci	tmp &= ~LC_L1_INACTIVITY_MASK;
10862306a36Sopenharmony_ci	tmp |= LC_L1_INACTIVITY(4);
10962306a36Sopenharmony_ci	tmp &= ~LC_PMI_TO_L1_DIS;
11062306a36Sopenharmony_ci	tmp &= ~LC_ASPM_TO_L1_DIS;
11162306a36Sopenharmony_ci	WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp);
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic void rv770_enable_pll_sleep_in_l1(struct radeon_device *rdev)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	u32 tmp;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL) & ~LC_L1_INACTIVITY_MASK;
11962306a36Sopenharmony_ci	tmp |= LC_L1_INACTIVITY(8);
12062306a36Sopenharmony_ci	WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	/* NOTE, this is a PCIE indirect reg, not PCIE PORT */
12362306a36Sopenharmony_ci	tmp = RREG32_PCIE(PCIE_P_CNTL);
12462306a36Sopenharmony_ci	tmp |= P_PLL_PWRDN_IN_L1L23;
12562306a36Sopenharmony_ci	tmp &= ~P_PLL_BUF_PDNB;
12662306a36Sopenharmony_ci	tmp &= ~P_PLL_PDNB;
12762306a36Sopenharmony_ci	tmp |= P_ALLOW_PRX_FRONTEND_SHUTOFF;
12862306a36Sopenharmony_ci	WREG32_PCIE(PCIE_P_CNTL, tmp);
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic void rv770_gfx_clock_gating_enable(struct radeon_device *rdev,
13262306a36Sopenharmony_ci					  bool enable)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	if (enable)
13562306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
13662306a36Sopenharmony_ci	else {
13762306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
13862306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
13962306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
14062306a36Sopenharmony_ci		RREG32(GB_TILING_CONFIG);
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic void rv770_mg_clock_gating_enable(struct radeon_device *rdev,
14562306a36Sopenharmony_ci					 bool enable)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (enable) {
15062306a36Sopenharmony_ci		u32 mgcg_cgtt_local0;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci		if (rdev->family == CHIP_RV770)
15362306a36Sopenharmony_ci			mgcg_cgtt_local0 = RV770_MGCGTTLOCAL0_DFLT;
15462306a36Sopenharmony_ci		else
15562306a36Sopenharmony_ci			mgcg_cgtt_local0 = RV7XX_MGCGTTLOCAL0_DFLT;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci		WREG32(CG_CGTT_LOCAL_0, mgcg_cgtt_local0);
15862306a36Sopenharmony_ci		WREG32(CG_CGTT_LOCAL_1, (RV770_MGCGTTLOCAL1_DFLT & 0xFFFFCFFF));
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci		if (pi->mgcgtssm)
16162306a36Sopenharmony_ci			WREG32(CGTS_SM_CTRL_REG, RV770_MGCGCGTSSMCTRL_DFLT);
16262306a36Sopenharmony_ci	} else {
16362306a36Sopenharmony_ci		WREG32(CG_CGTT_LOCAL_0, 0xFFFFFFFF);
16462306a36Sopenharmony_ci		WREG32(CG_CGTT_LOCAL_1, 0xFFFFCFFF);
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_civoid rv770_restore_cgcg(struct radeon_device *rdev)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	bool dpm_en = false, cg_en = false;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN)
17362306a36Sopenharmony_ci		dpm_en = true;
17462306a36Sopenharmony_ci	if (RREG32(SCLK_PWRMGT_CNTL) & DYN_GFX_CLK_OFF_EN)
17562306a36Sopenharmony_ci		cg_en = true;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	if (dpm_en && !cg_en)
17862306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic void rv770_start_dpm(struct radeon_device *rdev)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_civoid rv770_stop_dpm(struct radeon_device *rdev)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	PPSMC_Result result;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (result != PPSMC_Result_OK)
19762306a36Sopenharmony_ci		DRM_DEBUG("Could not force DPM to low.\n");
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF);
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cibool rv770_dpm_enabled(struct radeon_device *rdev)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN)
20962306a36Sopenharmony_ci		return true;
21062306a36Sopenharmony_ci	else
21162306a36Sopenharmony_ci		return false;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_civoid rv770_enable_thermal_protection(struct radeon_device *rdev,
21562306a36Sopenharmony_ci				     bool enable)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	if (enable)
21862306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
21962306a36Sopenharmony_ci	else
22062306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_civoid rv770_enable_acpi_pm(struct radeon_device *rdev)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ciu8 rv770_get_seq_value(struct radeon_device *rdev,
22962306a36Sopenharmony_ci		       struct rv7xx_pl *pl)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	return (pl->flags & ATOM_PPLIB_R600_FLAGS_LOWPOWER) ?
23262306a36Sopenharmony_ci		MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci#if 0
23662306a36Sopenharmony_ciint rv770_read_smc_soft_register(struct radeon_device *rdev,
23762306a36Sopenharmony_ci				 u16 reg_offset, u32 *value)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	return rv770_read_smc_sram_dword(rdev,
24262306a36Sopenharmony_ci					 pi->soft_regs_start + reg_offset,
24362306a36Sopenharmony_ci					 value, pi->sram_end);
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci#endif
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ciint rv770_write_smc_soft_register(struct radeon_device *rdev,
24862306a36Sopenharmony_ci				  u16 reg_offset, u32 value)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	return rv770_write_smc_sram_dword(rdev,
25362306a36Sopenharmony_ci					  pi->soft_regs_start + reg_offset,
25462306a36Sopenharmony_ci					  value, pi->sram_end);
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ciint rv770_populate_smc_t(struct radeon_device *rdev,
25862306a36Sopenharmony_ci			 struct radeon_ps *radeon_state,
25962306a36Sopenharmony_ci			 RV770_SMC_SWSTATE *smc_state)
26062306a36Sopenharmony_ci{
26162306a36Sopenharmony_ci	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
26262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
26362306a36Sopenharmony_ci	int i;
26462306a36Sopenharmony_ci	int a_n;
26562306a36Sopenharmony_ci	int a_d;
26662306a36Sopenharmony_ci	u8 l[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE];
26762306a36Sopenharmony_ci	u8 r[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE];
26862306a36Sopenharmony_ci	u32 a_t;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	l[0] = 0;
27162306a36Sopenharmony_ci	r[2] = 100;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	a_n = (int)state->medium.sclk * pi->lmp +
27462306a36Sopenharmony_ci		(int)state->low.sclk * (R600_AH_DFLT - pi->rlp);
27562306a36Sopenharmony_ci	a_d = (int)state->low.sclk * (100 - (int)pi->rlp) +
27662306a36Sopenharmony_ci		(int)state->medium.sclk * pi->lmp;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	l[1] = (u8)(pi->lmp - (int)pi->lmp * a_n / a_d);
27962306a36Sopenharmony_ci	r[0] = (u8)(pi->rlp + (100 - (int)pi->rlp) * a_n / a_d);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	a_n = (int)state->high.sclk * pi->lhp + (int)state->medium.sclk *
28262306a36Sopenharmony_ci		(R600_AH_DFLT - pi->rmp);
28362306a36Sopenharmony_ci	a_d = (int)state->medium.sclk * (100 - (int)pi->rmp) +
28462306a36Sopenharmony_ci		(int)state->high.sclk * pi->lhp;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	l[2] = (u8)(pi->lhp - (int)pi->lhp * a_n / a_d);
28762306a36Sopenharmony_ci	r[1] = (u8)(pi->rmp + (100 - (int)pi->rmp) * a_n / a_d);
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++) {
29062306a36Sopenharmony_ci		a_t = CG_R(r[i] * pi->bsp / 200) | CG_L(l[i] * pi->bsp / 200);
29162306a36Sopenharmony_ci		smc_state->levels[i].aT = cpu_to_be32(a_t);
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	a_t = CG_R(r[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1] * pi->pbsp / 200) |
29562306a36Sopenharmony_ci		CG_L(l[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1] * pi->pbsp / 200);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	smc_state->levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1].aT =
29862306a36Sopenharmony_ci		cpu_to_be32(a_t);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	return 0;
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ciint rv770_populate_smc_sp(struct radeon_device *rdev,
30462306a36Sopenharmony_ci			  struct radeon_ps *radeon_state,
30562306a36Sopenharmony_ci			  RV770_SMC_SWSTATE *smc_state)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
30862306a36Sopenharmony_ci	int i;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++)
31162306a36Sopenharmony_ci		smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	smc_state->levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1].bSP =
31462306a36Sopenharmony_ci		cpu_to_be32(pi->psp);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	return 0;
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_cistatic void rv770_calculate_fractional_mpll_feedback_divider(u32 memory_clock,
32062306a36Sopenharmony_ci							     u32 reference_clock,
32162306a36Sopenharmony_ci							     bool gddr5,
32262306a36Sopenharmony_ci							     struct atom_clock_dividers *dividers,
32362306a36Sopenharmony_ci							     u32 *clkf,
32462306a36Sopenharmony_ci							     u32 *clkfrac)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	u32 post_divider, reference_divider, feedback_divider8;
32762306a36Sopenharmony_ci	u32 fyclk;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	if (gddr5)
33062306a36Sopenharmony_ci		fyclk = (memory_clock * 8) / 2;
33162306a36Sopenharmony_ci	else
33262306a36Sopenharmony_ci		fyclk = (memory_clock * 4) / 2;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	post_divider = dividers->post_div;
33562306a36Sopenharmony_ci	reference_divider = dividers->ref_div;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	feedback_divider8 =
33862306a36Sopenharmony_ci		(8 * fyclk * reference_divider * post_divider) / reference_clock;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	*clkf = feedback_divider8 / 8;
34162306a36Sopenharmony_ci	*clkfrac = feedback_divider8 % 8;
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cistatic int rv770_encode_yclk_post_div(u32 postdiv, u32 *encoded_postdiv)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	int ret = 0;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	switch (postdiv) {
34962306a36Sopenharmony_ci	case 1:
35062306a36Sopenharmony_ci		*encoded_postdiv = 0;
35162306a36Sopenharmony_ci		break;
35262306a36Sopenharmony_ci	case 2:
35362306a36Sopenharmony_ci		*encoded_postdiv = 1;
35462306a36Sopenharmony_ci		break;
35562306a36Sopenharmony_ci	case 4:
35662306a36Sopenharmony_ci		*encoded_postdiv = 2;
35762306a36Sopenharmony_ci		break;
35862306a36Sopenharmony_ci	case 8:
35962306a36Sopenharmony_ci		*encoded_postdiv = 3;
36062306a36Sopenharmony_ci		break;
36162306a36Sopenharmony_ci	case 16:
36262306a36Sopenharmony_ci		*encoded_postdiv = 4;
36362306a36Sopenharmony_ci		break;
36462306a36Sopenharmony_ci	default:
36562306a36Sopenharmony_ci		ret = -EINVAL;
36662306a36Sopenharmony_ci		break;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	return ret;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ciu32 rv770_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	if (clkf <= 0x10)
37562306a36Sopenharmony_ci		return 0x4B;
37662306a36Sopenharmony_ci	if (clkf <= 0x19)
37762306a36Sopenharmony_ci		return 0x5B;
37862306a36Sopenharmony_ci	if (clkf <= 0x21)
37962306a36Sopenharmony_ci		return 0x2B;
38062306a36Sopenharmony_ci	if (clkf <= 0x27)
38162306a36Sopenharmony_ci		return 0x6C;
38262306a36Sopenharmony_ci	if (clkf <= 0x31)
38362306a36Sopenharmony_ci		return 0x9D;
38462306a36Sopenharmony_ci	return 0xC6;
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic int rv770_populate_mclk_value(struct radeon_device *rdev,
38862306a36Sopenharmony_ci				     u32 engine_clock, u32 memory_clock,
38962306a36Sopenharmony_ci				     RV7XX_SMC_MCLK_VALUE *mclk)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
39262306a36Sopenharmony_ci	u8 encoded_reference_dividers[] = { 0, 16, 17, 20, 21 };
39362306a36Sopenharmony_ci	u32 mpll_ad_func_cntl =
39462306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl;
39562306a36Sopenharmony_ci	u32 mpll_ad_func_cntl_2 =
39662306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl_2;
39762306a36Sopenharmony_ci	u32 mpll_dq_func_cntl =
39862306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl;
39962306a36Sopenharmony_ci	u32 mpll_dq_func_cntl_2 =
40062306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl_2;
40162306a36Sopenharmony_ci	u32 mclk_pwrmgt_cntl =
40262306a36Sopenharmony_ci		pi->clk_regs.rv770.mclk_pwrmgt_cntl;
40362306a36Sopenharmony_ci	u32 dll_cntl = pi->clk_regs.rv770.dll_cntl;
40462306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
40562306a36Sopenharmony_ci	u32 reference_clock = rdev->clock.mpll.reference_freq;
40662306a36Sopenharmony_ci	u32 clkf, clkfrac;
40762306a36Sopenharmony_ci	u32 postdiv_yclk;
40862306a36Sopenharmony_ci	u32 ibias;
40962306a36Sopenharmony_ci	int ret;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
41262306a36Sopenharmony_ci					     memory_clock, false, &dividers);
41362306a36Sopenharmony_ci	if (ret)
41462306a36Sopenharmony_ci		return ret;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if ((dividers.ref_div < 1) || (dividers.ref_div > 5))
41762306a36Sopenharmony_ci		return -EINVAL;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	rv770_calculate_fractional_mpll_feedback_divider(memory_clock, reference_clock,
42062306a36Sopenharmony_ci							 pi->mem_gddr5,
42162306a36Sopenharmony_ci							 &dividers, &clkf, &clkfrac);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	ret = rv770_encode_yclk_post_div(dividers.post_div, &postdiv_yclk);
42462306a36Sopenharmony_ci	if (ret)
42562306a36Sopenharmony_ci		return ret;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	ibias = rv770_map_clkf_to_ibias(rdev, clkf);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	mpll_ad_func_cntl &= ~(CLKR_MASK |
43062306a36Sopenharmony_ci			       YCLK_POST_DIV_MASK |
43162306a36Sopenharmony_ci			       CLKF_MASK |
43262306a36Sopenharmony_ci			       CLKFRAC_MASK |
43362306a36Sopenharmony_ci			       IBIAS_MASK);
43462306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKR(encoded_reference_dividers[dividers.ref_div - 1]);
43562306a36Sopenharmony_ci	mpll_ad_func_cntl |= YCLK_POST_DIV(postdiv_yclk);
43662306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKF(clkf);
43762306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKFRAC(clkfrac);
43862306a36Sopenharmony_ci	mpll_ad_func_cntl |= IBIAS(ibias);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	if (dividers.vco_mode)
44162306a36Sopenharmony_ci		mpll_ad_func_cntl_2 |= VCO_MODE;
44262306a36Sopenharmony_ci	else
44362306a36Sopenharmony_ci		mpll_ad_func_cntl_2 &= ~VCO_MODE;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	if (pi->mem_gddr5) {
44662306a36Sopenharmony_ci		rv770_calculate_fractional_mpll_feedback_divider(memory_clock,
44762306a36Sopenharmony_ci								 reference_clock,
44862306a36Sopenharmony_ci								 pi->mem_gddr5,
44962306a36Sopenharmony_ci								 &dividers, &clkf, &clkfrac);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci		ibias = rv770_map_clkf_to_ibias(rdev, clkf);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci		ret = rv770_encode_yclk_post_div(dividers.post_div, &postdiv_yclk);
45462306a36Sopenharmony_ci		if (ret)
45562306a36Sopenharmony_ci			return ret;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci		mpll_dq_func_cntl &= ~(CLKR_MASK |
45862306a36Sopenharmony_ci				       YCLK_POST_DIV_MASK |
45962306a36Sopenharmony_ci				       CLKF_MASK |
46062306a36Sopenharmony_ci				       CLKFRAC_MASK |
46162306a36Sopenharmony_ci				       IBIAS_MASK);
46262306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKR(encoded_reference_dividers[dividers.ref_div - 1]);
46362306a36Sopenharmony_ci		mpll_dq_func_cntl |= YCLK_POST_DIV(postdiv_yclk);
46462306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKF(clkf);
46562306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKFRAC(clkfrac);
46662306a36Sopenharmony_ci		mpll_dq_func_cntl |= IBIAS(ibias);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		if (dividers.vco_mode)
46962306a36Sopenharmony_ci			mpll_dq_func_cntl_2 |= VCO_MODE;
47062306a36Sopenharmony_ci		else
47162306a36Sopenharmony_ci			mpll_dq_func_cntl_2 &= ~VCO_MODE;
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	mclk->mclk770.mclk_value = cpu_to_be32(memory_clock);
47562306a36Sopenharmony_ci	mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
47662306a36Sopenharmony_ci	mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
47762306a36Sopenharmony_ci	mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
47862306a36Sopenharmony_ci	mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
47962306a36Sopenharmony_ci	mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
48062306a36Sopenharmony_ci	mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	return 0;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic int rv770_populate_sclk_value(struct radeon_device *rdev,
48662306a36Sopenharmony_ci				     u32 engine_clock,
48762306a36Sopenharmony_ci				     RV770_SMC_SCLK_VALUE *sclk)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
49062306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
49162306a36Sopenharmony_ci	u32 spll_func_cntl =
49262306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl;
49362306a36Sopenharmony_ci	u32 spll_func_cntl_2 =
49462306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl_2;
49562306a36Sopenharmony_ci	u32 spll_func_cntl_3 =
49662306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl_3;
49762306a36Sopenharmony_ci	u32 cg_spll_spread_spectrum =
49862306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_spread_spectrum;
49962306a36Sopenharmony_ci	u32 cg_spll_spread_spectrum_2 =
50062306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_spread_spectrum_2;
50162306a36Sopenharmony_ci	u64 tmp;
50262306a36Sopenharmony_ci	u32 reference_clock = rdev->clock.spll.reference_freq;
50362306a36Sopenharmony_ci	u32 reference_divider, post_divider;
50462306a36Sopenharmony_ci	u32 fbdiv;
50562306a36Sopenharmony_ci	int ret;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
50862306a36Sopenharmony_ci					     engine_clock, false, &dividers);
50962306a36Sopenharmony_ci	if (ret)
51062306a36Sopenharmony_ci		return ret;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	reference_divider = 1 + dividers.ref_div;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	if (dividers.enable_post_div)
51562306a36Sopenharmony_ci		post_divider = (0x0f & (dividers.post_div >> 4)) + (0x0f & dividers.post_div) + 2;
51662306a36Sopenharmony_ci	else
51762306a36Sopenharmony_ci		post_divider = 1;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	tmp = (u64) engine_clock * reference_divider * post_divider * 16384;
52062306a36Sopenharmony_ci	do_div(tmp, reference_clock);
52162306a36Sopenharmony_ci	fbdiv = (u32) tmp;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	if (dividers.enable_post_div)
52462306a36Sopenharmony_ci		spll_func_cntl |= SPLL_DIVEN;
52562306a36Sopenharmony_ci	else
52662306a36Sopenharmony_ci		spll_func_cntl &= ~SPLL_DIVEN;
52762306a36Sopenharmony_ci	spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK);
52862306a36Sopenharmony_ci	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
52962306a36Sopenharmony_ci	spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf);
53062306a36Sopenharmony_ci	spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
53362306a36Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(2);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
53662306a36Sopenharmony_ci	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
53762306a36Sopenharmony_ci	spll_func_cntl_3 |= SPLL_DITHEN;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	if (pi->sclk_ss) {
54062306a36Sopenharmony_ci		struct radeon_atom_ss ss;
54162306a36Sopenharmony_ci		u32 vco_freq = engine_clock * post_divider;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
54462306a36Sopenharmony_ci						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
54562306a36Sopenharmony_ci			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
54662306a36Sopenharmony_ci			u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci			cg_spll_spread_spectrum &= ~CLKS_MASK;
54962306a36Sopenharmony_ci			cg_spll_spread_spectrum |= CLKS(clk_s);
55062306a36Sopenharmony_ci			cg_spll_spread_spectrum |= SSEN;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci			cg_spll_spread_spectrum_2 &= ~CLKV_MASK;
55362306a36Sopenharmony_ci			cg_spll_spread_spectrum_2 |= CLKV(clk_v);
55462306a36Sopenharmony_ci		}
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	sclk->sclk_value = cpu_to_be32(engine_clock);
55862306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
55962306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
56062306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
56162306a36Sopenharmony_ci	sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
56262306a36Sopenharmony_ci	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	return 0;
56562306a36Sopenharmony_ci}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ciint rv770_populate_vddc_value(struct radeon_device *rdev, u16 vddc,
56862306a36Sopenharmony_ci			      RV770_SMC_VOLTAGE_VALUE *voltage)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
57162306a36Sopenharmony_ci	int i;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	if (!pi->voltage_control) {
57462306a36Sopenharmony_ci		voltage->index = 0;
57562306a36Sopenharmony_ci		voltage->value = 0;
57662306a36Sopenharmony_ci		return 0;
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	for (i = 0; i < pi->valid_vddc_entries; i++) {
58062306a36Sopenharmony_ci		if (vddc <= pi->vddc_table[i].vddc) {
58162306a36Sopenharmony_ci			voltage->index = pi->vddc_table[i].vddc_index;
58262306a36Sopenharmony_ci			voltage->value = cpu_to_be16(vddc);
58362306a36Sopenharmony_ci			break;
58462306a36Sopenharmony_ci		}
58562306a36Sopenharmony_ci	}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (i == pi->valid_vddc_entries)
58862306a36Sopenharmony_ci		return -EINVAL;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	return 0;
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ciint rv770_populate_mvdd_value(struct radeon_device *rdev, u32 mclk,
59462306a36Sopenharmony_ci			      RV770_SMC_VOLTAGE_VALUE *voltage)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	if (!pi->mvdd_control) {
59962306a36Sopenharmony_ci		voltage->index = MVDD_HIGH_INDEX;
60062306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
60162306a36Sopenharmony_ci		return 0;
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	if (mclk <= pi->mvdd_split_frequency) {
60562306a36Sopenharmony_ci		voltage->index = MVDD_LOW_INDEX;
60662306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
60762306a36Sopenharmony_ci	} else {
60862306a36Sopenharmony_ci		voltage->index = MVDD_HIGH_INDEX;
60962306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
61062306a36Sopenharmony_ci	}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	return 0;
61362306a36Sopenharmony_ci}
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_cistatic int rv770_convert_power_level_to_smc(struct radeon_device *rdev,
61662306a36Sopenharmony_ci					    struct rv7xx_pl *pl,
61762306a36Sopenharmony_ci					    RV770_SMC_HW_PERFORMANCE_LEVEL *level,
61862306a36Sopenharmony_ci					    u8 watermark_level)
61962306a36Sopenharmony_ci{
62062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
62162306a36Sopenharmony_ci	int ret;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	level->gen2PCIE = pi->pcie_gen2 ?
62462306a36Sopenharmony_ci		((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0;
62562306a36Sopenharmony_ci	level->gen2XSP  = (pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0;
62662306a36Sopenharmony_ci	level->backbias = (pl->flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE) ? 1 : 0;
62762306a36Sopenharmony_ci	level->displayWatermark = watermark_level;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	if (rdev->family == CHIP_RV740)
63062306a36Sopenharmony_ci		ret = rv740_populate_sclk_value(rdev, pl->sclk,
63162306a36Sopenharmony_ci						&level->sclk);
63262306a36Sopenharmony_ci	else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
63362306a36Sopenharmony_ci		ret = rv730_populate_sclk_value(rdev, pl->sclk,
63462306a36Sopenharmony_ci						&level->sclk);
63562306a36Sopenharmony_ci	else
63662306a36Sopenharmony_ci		ret = rv770_populate_sclk_value(rdev, pl->sclk,
63762306a36Sopenharmony_ci						&level->sclk);
63862306a36Sopenharmony_ci	if (ret)
63962306a36Sopenharmony_ci		return ret;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	if (rdev->family == CHIP_RV740) {
64262306a36Sopenharmony_ci		if (pi->mem_gddr5) {
64362306a36Sopenharmony_ci			if (pl->mclk <= pi->mclk_strobe_mode_threshold)
64462306a36Sopenharmony_ci				level->strobeMode =
64562306a36Sopenharmony_ci					rv740_get_mclk_frequency_ratio(pl->mclk) | 0x10;
64662306a36Sopenharmony_ci			else
64762306a36Sopenharmony_ci				level->strobeMode = 0;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci			if (pl->mclk > pi->mclk_edc_enable_threshold)
65062306a36Sopenharmony_ci				level->mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG;
65162306a36Sopenharmony_ci			else
65262306a36Sopenharmony_ci				level->mcFlags =  0;
65362306a36Sopenharmony_ci		}
65462306a36Sopenharmony_ci		ret = rv740_populate_mclk_value(rdev, pl->sclk,
65562306a36Sopenharmony_ci						pl->mclk, &level->mclk);
65662306a36Sopenharmony_ci	} else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
65762306a36Sopenharmony_ci		ret = rv730_populate_mclk_value(rdev, pl->sclk,
65862306a36Sopenharmony_ci						pl->mclk, &level->mclk);
65962306a36Sopenharmony_ci	else
66062306a36Sopenharmony_ci		ret = rv770_populate_mclk_value(rdev, pl->sclk,
66162306a36Sopenharmony_ci						pl->mclk, &level->mclk);
66262306a36Sopenharmony_ci	if (ret)
66362306a36Sopenharmony_ci		return ret;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	ret = rv770_populate_vddc_value(rdev, pl->vddc,
66662306a36Sopenharmony_ci					&level->vddc);
66762306a36Sopenharmony_ci	if (ret)
66862306a36Sopenharmony_ci		return ret;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	ret = rv770_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	return ret;
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic int rv770_convert_power_state_to_smc(struct radeon_device *rdev,
67662306a36Sopenharmony_ci					    struct radeon_ps *radeon_state,
67762306a36Sopenharmony_ci					    RV770_SMC_SWSTATE *smc_state)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
68062306a36Sopenharmony_ci	int ret;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC))
68362306a36Sopenharmony_ci		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	ret = rv770_convert_power_level_to_smc(rdev,
68662306a36Sopenharmony_ci					       &state->low,
68762306a36Sopenharmony_ci					       &smc_state->levels[0],
68862306a36Sopenharmony_ci					       PPSMC_DISPLAY_WATERMARK_LOW);
68962306a36Sopenharmony_ci	if (ret)
69062306a36Sopenharmony_ci		return ret;
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	ret = rv770_convert_power_level_to_smc(rdev,
69362306a36Sopenharmony_ci					       &state->medium,
69462306a36Sopenharmony_ci					       &smc_state->levels[1],
69562306a36Sopenharmony_ci					       PPSMC_DISPLAY_WATERMARK_LOW);
69662306a36Sopenharmony_ci	if (ret)
69762306a36Sopenharmony_ci		return ret;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	ret = rv770_convert_power_level_to_smc(rdev,
70062306a36Sopenharmony_ci					       &state->high,
70162306a36Sopenharmony_ci					       &smc_state->levels[2],
70262306a36Sopenharmony_ci					       PPSMC_DISPLAY_WATERMARK_HIGH);
70362306a36Sopenharmony_ci	if (ret)
70462306a36Sopenharmony_ci		return ret;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	smc_state->levels[0].arbValue = MC_CG_ARB_FREQ_F1;
70762306a36Sopenharmony_ci	smc_state->levels[1].arbValue = MC_CG_ARB_FREQ_F2;
70862306a36Sopenharmony_ci	smc_state->levels[2].arbValue = MC_CG_ARB_FREQ_F3;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	smc_state->levels[0].seqValue = rv770_get_seq_value(rdev,
71162306a36Sopenharmony_ci							    &state->low);
71262306a36Sopenharmony_ci	smc_state->levels[1].seqValue = rv770_get_seq_value(rdev,
71362306a36Sopenharmony_ci							    &state->medium);
71462306a36Sopenharmony_ci	smc_state->levels[2].seqValue = rv770_get_seq_value(rdev,
71562306a36Sopenharmony_ci							    &state->high);
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	rv770_populate_smc_sp(rdev, radeon_state, smc_state);
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	return rv770_populate_smc_t(rdev, radeon_state, smc_state);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci}
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ciu32 rv770_calculate_memory_refresh_rate(struct radeon_device *rdev,
72462306a36Sopenharmony_ci					u32 engine_clock)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci	u32 dram_rows;
72762306a36Sopenharmony_ci	u32 dram_refresh_rate;
72862306a36Sopenharmony_ci	u32 mc_arb_rfsh_rate;
72962306a36Sopenharmony_ci	u32 tmp;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
73262306a36Sopenharmony_ci	dram_rows = 1 << (tmp + 10);
73362306a36Sopenharmony_ci	tmp = RREG32(MC_SEQ_MISC0) & 3;
73462306a36Sopenharmony_ci	dram_refresh_rate = 1 << (tmp + 3);
73562306a36Sopenharmony_ci	mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	return mc_arb_rfsh_rate;
73862306a36Sopenharmony_ci}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic void rv770_program_memory_timing_parameters(struct radeon_device *rdev,
74162306a36Sopenharmony_ci						   struct radeon_ps *radeon_state)
74262306a36Sopenharmony_ci{
74362306a36Sopenharmony_ci	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
74462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
74562306a36Sopenharmony_ci	u32 sqm_ratio;
74662306a36Sopenharmony_ci	u32 arb_refresh_rate;
74762306a36Sopenharmony_ci	u32 high_clock;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	if (state->high.sclk < (state->low.sclk * 0xFF / 0x40))
75062306a36Sopenharmony_ci		high_clock = state->high.sclk;
75162306a36Sopenharmony_ci	else
75262306a36Sopenharmony_ci		high_clock = (state->low.sclk * 0xFF / 0x40);
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	radeon_atom_set_engine_dram_timings(rdev, high_clock,
75562306a36Sopenharmony_ci					    state->high.mclk);
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	sqm_ratio =
75862306a36Sopenharmony_ci		STATE0(64 * high_clock / pi->boot_sclk) |
75962306a36Sopenharmony_ci		STATE1(64 * high_clock / state->low.sclk) |
76062306a36Sopenharmony_ci		STATE2(64 * high_clock / state->medium.sclk) |
76162306a36Sopenharmony_ci		STATE3(64 * high_clock / state->high.sclk);
76262306a36Sopenharmony_ci	WREG32(MC_ARB_SQM_RATIO, sqm_ratio);
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	arb_refresh_rate =
76562306a36Sopenharmony_ci		POWERMODE0(rv770_calculate_memory_refresh_rate(rdev, pi->boot_sclk)) |
76662306a36Sopenharmony_ci		POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) |
76762306a36Sopenharmony_ci		POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) |
76862306a36Sopenharmony_ci		POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk));
76962306a36Sopenharmony_ci	WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate);
77062306a36Sopenharmony_ci}
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_civoid rv770_enable_backbias(struct radeon_device *rdev,
77362306a36Sopenharmony_ci			   bool enable)
77462306a36Sopenharmony_ci{
77562306a36Sopenharmony_ci	if (enable)
77662306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, BACKBIAS_PAD_EN, ~BACKBIAS_PAD_EN);
77762306a36Sopenharmony_ci	else
77862306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~(BACKBIAS_VALUE | BACKBIAS_PAD_EN));
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_cistatic void rv770_enable_spread_spectrum(struct radeon_device *rdev,
78262306a36Sopenharmony_ci					 bool enable)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	if (enable) {
78762306a36Sopenharmony_ci		if (pi->sclk_ss)
78862306a36Sopenharmony_ci			WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci		if (pi->mclk_ss) {
79162306a36Sopenharmony_ci			if (rdev->family == CHIP_RV740)
79262306a36Sopenharmony_ci				rv740_enable_mclk_spread_spectrum(rdev, true);
79362306a36Sopenharmony_ci		}
79462306a36Sopenharmony_ci	} else {
79562306a36Sopenharmony_ci		WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN);
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci		WREG32_P(CG_MPLL_SPREAD_SPECTRUM, 0, ~SSEN);
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci		if (rdev->family == CHIP_RV740)
80262306a36Sopenharmony_ci			rv740_enable_mclk_spread_spectrum(rdev, false);
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_cistatic void rv770_program_mpll_timing_parameters(struct radeon_device *rdev)
80762306a36Sopenharmony_ci{
80862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV770) && !pi->mem_gddr5) {
81162306a36Sopenharmony_ci		WREG32(MPLL_TIME,
81262306a36Sopenharmony_ci		       (MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div) |
81362306a36Sopenharmony_ci			MPLL_RESET_TIME(R600_MPLLRESETTIME_DFLT)));
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_civoid rv770_setup_bsp(struct radeon_device *rdev)
81862306a36Sopenharmony_ci{
81962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
82062306a36Sopenharmony_ci	u32 xclk = radeon_get_xclk(rdev);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	r600_calculate_u_and_p(pi->asi,
82362306a36Sopenharmony_ci			       xclk,
82462306a36Sopenharmony_ci			       16,
82562306a36Sopenharmony_ci			       &pi->bsp,
82662306a36Sopenharmony_ci			       &pi->bsu);
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	r600_calculate_u_and_p(pi->pasi,
82962306a36Sopenharmony_ci			       xclk,
83062306a36Sopenharmony_ci			       16,
83162306a36Sopenharmony_ci			       &pi->pbsp,
83262306a36Sopenharmony_ci			       &pi->pbsu);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	pi->dsp = BSP(pi->bsp) | BSU(pi->bsu);
83562306a36Sopenharmony_ci	pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	WREG32(CG_BSP, pi->dsp);
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci}
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_civoid rv770_program_git(struct radeon_device *rdev)
84262306a36Sopenharmony_ci{
84362306a36Sopenharmony_ci	WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK);
84462306a36Sopenharmony_ci}
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_civoid rv770_program_tp(struct radeon_device *rdev)
84762306a36Sopenharmony_ci{
84862306a36Sopenharmony_ci	int i;
84962306a36Sopenharmony_ci	enum r600_td td = R600_TD_DFLT;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	for (i = 0; i < R600_PM_NUMBER_OF_TC; i++)
85262306a36Sopenharmony_ci		WREG32(CG_FFCT_0 + (i * 4), (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i])));
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	if (td == R600_TD_AUTO)
85562306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);
85662306a36Sopenharmony_ci	else
85762306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);
85862306a36Sopenharmony_ci	if (td == R600_TD_UP)
85962306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);
86062306a36Sopenharmony_ci	if (td == R600_TD_DOWN)
86162306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
86262306a36Sopenharmony_ci}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_civoid rv770_program_tpp(struct radeon_device *rdev)
86562306a36Sopenharmony_ci{
86662306a36Sopenharmony_ci	WREG32(CG_TPC, R600_TPC_DFLT);
86762306a36Sopenharmony_ci}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_civoid rv770_program_sstp(struct radeon_device *rdev)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT)));
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_civoid rv770_program_engine_speed_parameters(struct radeon_device *rdev)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	WREG32_P(SPLL_CNTL_MODE, SPLL_DIV_SYNC, ~SPLL_DIV_SYNC);
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistatic void rv770_enable_display_gap(struct radeon_device *rdev)
88062306a36Sopenharmony_ci{
88162306a36Sopenharmony_ci	u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
88462306a36Sopenharmony_ci	tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE) |
88562306a36Sopenharmony_ci		DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE));
88662306a36Sopenharmony_ci	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
88762306a36Sopenharmony_ci}
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_civoid rv770_program_vc(struct radeon_device *rdev)
89062306a36Sopenharmony_ci{
89162306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	WREG32(CG_FTV, pi->vrc);
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_civoid rv770_clear_vc(struct radeon_device *rdev)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	WREG32(CG_FTV, 0);
89962306a36Sopenharmony_ci}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ciint rv770_upload_firmware(struct radeon_device *rdev)
90262306a36Sopenharmony_ci{
90362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
90462306a36Sopenharmony_ci	int ret;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	rv770_reset_smc(rdev);
90762306a36Sopenharmony_ci	rv770_stop_smc_clock(rdev);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	ret = rv770_load_smc_ucode(rdev, pi->sram_end);
91062306a36Sopenharmony_ci	if (ret)
91162306a36Sopenharmony_ci		return ret;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	return 0;
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic int rv770_populate_smc_acpi_state(struct radeon_device *rdev,
91762306a36Sopenharmony_ci					 RV770_SMC_STATETABLE *table)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	u32 mpll_ad_func_cntl =
92262306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl;
92362306a36Sopenharmony_ci	u32 mpll_ad_func_cntl_2 =
92462306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl_2;
92562306a36Sopenharmony_ci	u32 mpll_dq_func_cntl =
92662306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl;
92762306a36Sopenharmony_ci	u32 mpll_dq_func_cntl_2 =
92862306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl_2;
92962306a36Sopenharmony_ci	u32 spll_func_cntl =
93062306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl;
93162306a36Sopenharmony_ci	u32 spll_func_cntl_2 =
93262306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl_2;
93362306a36Sopenharmony_ci	u32 spll_func_cntl_3 =
93462306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl_3;
93562306a36Sopenharmony_ci	u32 mclk_pwrmgt_cntl;
93662306a36Sopenharmony_ci	u32 dll_cntl;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	table->ACPIState = table->initialState;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	if (pi->acpi_vddc) {
94362306a36Sopenharmony_ci		rv770_populate_vddc_value(rdev, pi->acpi_vddc,
94462306a36Sopenharmony_ci					  &table->ACPIState.levels[0].vddc);
94562306a36Sopenharmony_ci		if (pi->pcie_gen2) {
94662306a36Sopenharmony_ci			if (pi->acpi_pcie_gen2)
94762306a36Sopenharmony_ci				table->ACPIState.levels[0].gen2PCIE = 1;
94862306a36Sopenharmony_ci			else
94962306a36Sopenharmony_ci				table->ACPIState.levels[0].gen2PCIE = 0;
95062306a36Sopenharmony_ci		} else
95162306a36Sopenharmony_ci			table->ACPIState.levels[0].gen2PCIE = 0;
95262306a36Sopenharmony_ci		if (pi->acpi_pcie_gen2)
95362306a36Sopenharmony_ci			table->ACPIState.levels[0].gen2XSP = 1;
95462306a36Sopenharmony_ci		else
95562306a36Sopenharmony_ci			table->ACPIState.levels[0].gen2XSP = 0;
95662306a36Sopenharmony_ci	} else {
95762306a36Sopenharmony_ci		rv770_populate_vddc_value(rdev, pi->min_vddc_in_table,
95862306a36Sopenharmony_ci					  &table->ACPIState.levels[0].vddc);
95962306a36Sopenharmony_ci		table->ACPIState.levels[0].gen2PCIE = 0;
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	mclk_pwrmgt_cntl = (MRDCKA0_RESET |
96862306a36Sopenharmony_ci			    MRDCKA1_RESET |
96962306a36Sopenharmony_ci			    MRDCKB0_RESET |
97062306a36Sopenharmony_ci			    MRDCKB1_RESET |
97162306a36Sopenharmony_ci			    MRDCKC0_RESET |
97262306a36Sopenharmony_ci			    MRDCKC1_RESET |
97362306a36Sopenharmony_ci			    MRDCKD0_RESET |
97462306a36Sopenharmony_ci			    MRDCKD1_RESET);
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	dll_cntl = 0xff000000;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
98162306a36Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
98462306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
98562306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
98662306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
98962306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
99462306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
99562306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.sclk_value = 0;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	table->ACPIState.levels[1] = table->ACPIState.levels[0];
100262306a36Sopenharmony_ci	table->ACPIState.levels[2] = table->ACPIState.levels[0];
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	return 0;
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ciint rv770_populate_initial_mvdd_value(struct radeon_device *rdev,
100862306a36Sopenharmony_ci				      RV770_SMC_VOLTAGE_VALUE *voltage)
100962306a36Sopenharmony_ci{
101062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	if ((pi->s0_vid_lower_smio_cntl & pi->mvdd_mask_low) ==
101362306a36Sopenharmony_ci	     (pi->mvdd_low_smio[MVDD_LOW_INDEX] & pi->mvdd_mask_low) ) {
101462306a36Sopenharmony_ci		voltage->index = MVDD_LOW_INDEX;
101562306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
101662306a36Sopenharmony_ci	} else {
101762306a36Sopenharmony_ci		voltage->index = MVDD_HIGH_INDEX;
101862306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
101962306a36Sopenharmony_ci	}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	return 0;
102262306a36Sopenharmony_ci}
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_cistatic int rv770_populate_smc_initial_state(struct radeon_device *rdev,
102562306a36Sopenharmony_ci					    struct radeon_ps *radeon_state,
102662306a36Sopenharmony_ci					    RV770_SMC_STATETABLE *table)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state);
102962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
103062306a36Sopenharmony_ci	u32 a_t;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL =
103362306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl);
103462306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 =
103562306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl_2);
103662306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL =
103762306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl);
103862306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 =
103962306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl_2);
104062306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL =
104162306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mclk_pwrmgt_cntl);
104262306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vDLL_CNTL =
104362306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.dll_cntl);
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_SS =
104662306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ss1);
104762306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_SS2 =
104862306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ss2);
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.mclk_value =
105162306a36Sopenharmony_ci		cpu_to_be32(initial_state->low.mclk);
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
105462306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl);
105562306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
105662306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_2);
105762306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
105862306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_3);
105962306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
106062306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum);
106162306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
106262306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum_2);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	table->initialState.levels[0].sclk.sclk_value =
106562306a36Sopenharmony_ci		cpu_to_be32(initial_state->low.sclk);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	table->initialState.levels[0].seqValue =
107062306a36Sopenharmony_ci		rv770_get_seq_value(rdev, &initial_state->low);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	rv770_populate_vddc_value(rdev,
107362306a36Sopenharmony_ci				  initial_state->low.vddc,
107462306a36Sopenharmony_ci				  &table->initialState.levels[0].vddc);
107562306a36Sopenharmony_ci	rv770_populate_initial_mvdd_value(rdev,
107662306a36Sopenharmony_ci					  &table->initialState.levels[0].mvdd);
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	a_t = CG_R(0xffff) | CG_L(0);
107962306a36Sopenharmony_ci	table->initialState.levels[0].aT = cpu_to_be32(a_t);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	if (pi->boot_in_gen2)
108462306a36Sopenharmony_ci		table->initialState.levels[0].gen2PCIE = 1;
108562306a36Sopenharmony_ci	else
108662306a36Sopenharmony_ci		table->initialState.levels[0].gen2PCIE = 0;
108762306a36Sopenharmony_ci	if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
108862306a36Sopenharmony_ci		table->initialState.levels[0].gen2XSP = 1;
108962306a36Sopenharmony_ci	else
109062306a36Sopenharmony_ci		table->initialState.levels[0].gen2XSP = 0;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	if (rdev->family == CHIP_RV740) {
109362306a36Sopenharmony_ci		if (pi->mem_gddr5) {
109462306a36Sopenharmony_ci			if (initial_state->low.mclk <= pi->mclk_strobe_mode_threshold)
109562306a36Sopenharmony_ci				table->initialState.levels[0].strobeMode =
109662306a36Sopenharmony_ci					rv740_get_mclk_frequency_ratio(initial_state->low.mclk) | 0x10;
109762306a36Sopenharmony_ci			else
109862306a36Sopenharmony_ci				table->initialState.levels[0].strobeMode = 0;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci			if (initial_state->low.mclk >= pi->mclk_edc_enable_threshold)
110162306a36Sopenharmony_ci				table->initialState.levels[0].mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG;
110262306a36Sopenharmony_ci			else
110362306a36Sopenharmony_ci				table->initialState.levels[0].mcFlags =  0;
110462306a36Sopenharmony_ci		}
110562306a36Sopenharmony_ci	}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	table->initialState.levels[1] = table->initialState.levels[0];
110862306a36Sopenharmony_ci	table->initialState.levels[2] = table->initialState.levels[0];
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	return 0;
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic int rv770_populate_smc_vddc_table(struct radeon_device *rdev,
111662306a36Sopenharmony_ci					 RV770_SMC_STATETABLE *table)
111762306a36Sopenharmony_ci{
111862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
111962306a36Sopenharmony_ci	int i;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	for (i = 0; i < pi->valid_vddc_entries; i++) {
112262306a36Sopenharmony_ci		table->highSMIO[pi->vddc_table[i].vddc_index] =
112362306a36Sopenharmony_ci			pi->vddc_table[i].high_smio;
112462306a36Sopenharmony_ci		table->lowSMIO[pi->vddc_table[i].vddc_index] =
112562306a36Sopenharmony_ci			cpu_to_be32(pi->vddc_table[i].low_smio);
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_VDDC] = 0;
112962306a36Sopenharmony_ci	table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_VDDC] =
113062306a36Sopenharmony_ci		cpu_to_be32(pi->vddc_mask_low);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	for (i = 0;
113362306a36Sopenharmony_ci	     ((i < pi->valid_vddc_entries) &&
113462306a36Sopenharmony_ci	      (pi->max_vddc_in_table >
113562306a36Sopenharmony_ci	       pi->vddc_table[i].vddc));
113662306a36Sopenharmony_ci	     i++);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	table->maxVDDCIndexInPPTable =
113962306a36Sopenharmony_ci		pi->vddc_table[i].vddc_index;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	return 0;
114262306a36Sopenharmony_ci}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_cistatic int rv770_populate_smc_mvdd_table(struct radeon_device *rdev,
114562306a36Sopenharmony_ci					 RV770_SMC_STATETABLE *table)
114662306a36Sopenharmony_ci{
114762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	if (pi->mvdd_control) {
115062306a36Sopenharmony_ci		table->lowSMIO[MVDD_HIGH_INDEX] |=
115162306a36Sopenharmony_ci			cpu_to_be32(pi->mvdd_low_smio[MVDD_HIGH_INDEX]);
115262306a36Sopenharmony_ci		table->lowSMIO[MVDD_LOW_INDEX] |=
115362306a36Sopenharmony_ci			cpu_to_be32(pi->mvdd_low_smio[MVDD_LOW_INDEX]);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci		table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_MVDD] = 0;
115662306a36Sopenharmony_ci		table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_MVDD] =
115762306a36Sopenharmony_ci			cpu_to_be32(pi->mvdd_mask_low);
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	return 0;
116162306a36Sopenharmony_ci}
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_cistatic int rv770_init_smc_table(struct radeon_device *rdev,
116462306a36Sopenharmony_ci				struct radeon_ps *radeon_boot_state)
116562306a36Sopenharmony_ci{
116662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
116762306a36Sopenharmony_ci	struct rv7xx_ps *boot_state = rv770_get_ps(radeon_boot_state);
116862306a36Sopenharmony_ci	RV770_SMC_STATETABLE *table = &pi->smc_statetable;
116962306a36Sopenharmony_ci	int ret;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	memset(table, 0, sizeof(RV770_SMC_STATETABLE));
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	pi->boot_sclk = boot_state->low.sclk;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	rv770_populate_smc_vddc_table(rdev, table);
117662306a36Sopenharmony_ci	rv770_populate_smc_mvdd_table(rdev, table);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	switch (rdev->pm.int_thermal_type) {
117962306a36Sopenharmony_ci	case THERMAL_TYPE_RV770:
118062306a36Sopenharmony_ci	case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
118162306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
118262306a36Sopenharmony_ci		break;
118362306a36Sopenharmony_ci	case THERMAL_TYPE_NONE:
118462306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
118562306a36Sopenharmony_ci		break;
118662306a36Sopenharmony_ci	case THERMAL_TYPE_EXTERNAL_GPIO:
118762306a36Sopenharmony_ci	default:
118862306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
118962306a36Sopenharmony_ci		break;
119062306a36Sopenharmony_ci	}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) {
119362306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT)
119662306a36Sopenharmony_ci			table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT)
119962306a36Sopenharmony_ci			table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE;
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
120362306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (pi->mem_gddr5)
120662306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
120962306a36Sopenharmony_ci		ret = rv730_populate_smc_initial_state(rdev, radeon_boot_state, table);
121062306a36Sopenharmony_ci	else
121162306a36Sopenharmony_ci		ret = rv770_populate_smc_initial_state(rdev, radeon_boot_state, table);
121262306a36Sopenharmony_ci	if (ret)
121362306a36Sopenharmony_ci		return ret;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	if (rdev->family == CHIP_RV740)
121662306a36Sopenharmony_ci		ret = rv740_populate_smc_acpi_state(rdev, table);
121762306a36Sopenharmony_ci	else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
121862306a36Sopenharmony_ci		ret = rv730_populate_smc_acpi_state(rdev, table);
121962306a36Sopenharmony_ci	else
122062306a36Sopenharmony_ci		ret = rv770_populate_smc_acpi_state(rdev, table);
122162306a36Sopenharmony_ci	if (ret)
122262306a36Sopenharmony_ci		return ret;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	table->driverState = table->initialState;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev,
122762306a36Sopenharmony_ci				       pi->state_table_start,
122862306a36Sopenharmony_ci				       (const u8 *)table,
122962306a36Sopenharmony_ci				       sizeof(RV770_SMC_STATETABLE),
123062306a36Sopenharmony_ci				       pi->sram_end);
123162306a36Sopenharmony_ci}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_cistatic int rv770_construct_vddc_table(struct radeon_device *rdev)
123462306a36Sopenharmony_ci{
123562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
123662306a36Sopenharmony_ci	u16 min, max, step;
123762306a36Sopenharmony_ci	u32 steps = 0;
123862306a36Sopenharmony_ci	u8 vddc_index = 0;
123962306a36Sopenharmony_ci	u32 i;
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	radeon_atom_get_min_voltage(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &min);
124262306a36Sopenharmony_ci	radeon_atom_get_max_voltage(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &max);
124362306a36Sopenharmony_ci	radeon_atom_get_voltage_step(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &step);
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	steps = (max - min) / step + 1;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	if (steps > MAX_NO_VREG_STEPS)
124862306a36Sopenharmony_ci		return -EINVAL;
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	for (i = 0; i < steps; i++) {
125162306a36Sopenharmony_ci		u32 gpio_pins, gpio_mask;
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci		pi->vddc_table[i].vddc = (u16)(min + i * step);
125462306a36Sopenharmony_ci		radeon_atom_get_voltage_gpio_settings(rdev,
125562306a36Sopenharmony_ci						      pi->vddc_table[i].vddc,
125662306a36Sopenharmony_ci						      SET_VOLTAGE_TYPE_ASIC_VDDC,
125762306a36Sopenharmony_ci						      &gpio_pins, &gpio_mask);
125862306a36Sopenharmony_ci		pi->vddc_table[i].low_smio = gpio_pins & gpio_mask;
125962306a36Sopenharmony_ci		pi->vddc_table[i].high_smio = 0;
126062306a36Sopenharmony_ci		pi->vddc_mask_low = gpio_mask;
126162306a36Sopenharmony_ci		if (i > 0) {
126262306a36Sopenharmony_ci			if ((pi->vddc_table[i].low_smio !=
126362306a36Sopenharmony_ci			     pi->vddc_table[i - 1].low_smio ) ||
126462306a36Sopenharmony_ci			     (pi->vddc_table[i].high_smio !=
126562306a36Sopenharmony_ci			      pi->vddc_table[i - 1].high_smio))
126662306a36Sopenharmony_ci				vddc_index++;
126762306a36Sopenharmony_ci		}
126862306a36Sopenharmony_ci		pi->vddc_table[i].vddc_index = vddc_index;
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	pi->valid_vddc_entries = (u8)steps;
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	return 0;
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_cistatic u32 rv770_get_mclk_split_point(struct atom_memory_info *memory_info)
127762306a36Sopenharmony_ci{
127862306a36Sopenharmony_ci	if (memory_info->mem_type == MEM_TYPE_GDDR3)
127962306a36Sopenharmony_ci		return 30000;
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	return 0;
128262306a36Sopenharmony_ci}
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_cistatic int rv770_get_mvdd_pin_configuration(struct radeon_device *rdev)
128562306a36Sopenharmony_ci{
128662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
128762306a36Sopenharmony_ci	u32 gpio_pins, gpio_mask;
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	radeon_atom_get_voltage_gpio_settings(rdev,
129062306a36Sopenharmony_ci					      MVDD_HIGH_VALUE, SET_VOLTAGE_TYPE_ASIC_MVDDC,
129162306a36Sopenharmony_ci					      &gpio_pins, &gpio_mask);
129262306a36Sopenharmony_ci	pi->mvdd_mask_low = gpio_mask;
129362306a36Sopenharmony_ci	pi->mvdd_low_smio[MVDD_HIGH_INDEX] =
129462306a36Sopenharmony_ci		gpio_pins & gpio_mask;
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	radeon_atom_get_voltage_gpio_settings(rdev,
129762306a36Sopenharmony_ci					      MVDD_LOW_VALUE, SET_VOLTAGE_TYPE_ASIC_MVDDC,
129862306a36Sopenharmony_ci					      &gpio_pins, &gpio_mask);
129962306a36Sopenharmony_ci	pi->mvdd_low_smio[MVDD_LOW_INDEX] =
130062306a36Sopenharmony_ci		gpio_pins & gpio_mask;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	return 0;
130362306a36Sopenharmony_ci}
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ciu8 rv770_get_memory_module_index(struct radeon_device *rdev)
130662306a36Sopenharmony_ci{
130762306a36Sopenharmony_ci	return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff);
130862306a36Sopenharmony_ci}
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_cistatic int rv770_get_mvdd_configuration(struct radeon_device *rdev)
131162306a36Sopenharmony_ci{
131262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
131362306a36Sopenharmony_ci	u8 memory_module_index;
131462306a36Sopenharmony_ci	struct atom_memory_info memory_info;
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	memory_module_index = rv770_get_memory_module_index(rdev);
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	if (radeon_atom_get_memory_info(rdev, memory_module_index, &memory_info)) {
131962306a36Sopenharmony_ci		pi->mvdd_control = false;
132062306a36Sopenharmony_ci		return 0;
132162306a36Sopenharmony_ci	}
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	pi->mvdd_split_frequency =
132462306a36Sopenharmony_ci		rv770_get_mclk_split_point(&memory_info);
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	if (pi->mvdd_split_frequency == 0) {
132762306a36Sopenharmony_ci		pi->mvdd_control = false;
132862306a36Sopenharmony_ci		return 0;
132962306a36Sopenharmony_ci	}
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	return rv770_get_mvdd_pin_configuration(rdev);
133262306a36Sopenharmony_ci}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_civoid rv770_enable_voltage_control(struct radeon_device *rdev,
133562306a36Sopenharmony_ci				  bool enable)
133662306a36Sopenharmony_ci{
133762306a36Sopenharmony_ci	if (enable)
133862306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN);
133962306a36Sopenharmony_ci	else
134062306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN);
134162306a36Sopenharmony_ci}
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_cistatic void rv770_program_display_gap(struct radeon_device *rdev)
134462306a36Sopenharmony_ci{
134562306a36Sopenharmony_ci	u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
134862306a36Sopenharmony_ci	if (rdev->pm.dpm.new_active_crtcs & 1) {
134962306a36Sopenharmony_ci		tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
135062306a36Sopenharmony_ci		tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
135162306a36Sopenharmony_ci	} else if (rdev->pm.dpm.new_active_crtcs & 2) {
135262306a36Sopenharmony_ci		tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
135362306a36Sopenharmony_ci		tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
135462306a36Sopenharmony_ci	} else {
135562306a36Sopenharmony_ci		tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
135662306a36Sopenharmony_ci		tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
135762306a36Sopenharmony_ci	}
135862306a36Sopenharmony_ci	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
135962306a36Sopenharmony_ci}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_cistatic void rv770_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
136262306a36Sopenharmony_ci					   bool enable)
136362306a36Sopenharmony_ci{
136462306a36Sopenharmony_ci	rv770_enable_bif_dynamic_pcie_gen2(rdev, enable);
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	if (enable)
136762306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE);
136862306a36Sopenharmony_ci	else
136962306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE);
137062306a36Sopenharmony_ci}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cistatic void r7xx_program_memory_timing_parameters(struct radeon_device *rdev,
137362306a36Sopenharmony_ci						  struct radeon_ps *radeon_new_state)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) ||
137662306a36Sopenharmony_ci	    (rdev->family == CHIP_RV710) ||
137762306a36Sopenharmony_ci	    (rdev->family == CHIP_RV740))
137862306a36Sopenharmony_ci		rv730_program_memory_timing_parameters(rdev, radeon_new_state);
137962306a36Sopenharmony_ci	else
138062306a36Sopenharmony_ci		rv770_program_memory_timing_parameters(rdev, radeon_new_state);
138162306a36Sopenharmony_ci}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_cistatic int rv770_upload_sw_state(struct radeon_device *rdev,
138462306a36Sopenharmony_ci				 struct radeon_ps *radeon_new_state)
138562306a36Sopenharmony_ci{
138662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
138762306a36Sopenharmony_ci	u16 address = pi->state_table_start +
138862306a36Sopenharmony_ci		offsetof(RV770_SMC_STATETABLE, driverState);
138962306a36Sopenharmony_ci	RV770_SMC_SWSTATE state = { 0 };
139062306a36Sopenharmony_ci	int ret;
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	ret = rv770_convert_power_state_to_smc(rdev, radeon_new_state, &state);
139362306a36Sopenharmony_ci	if (ret)
139462306a36Sopenharmony_ci		return ret;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, address, (const u8 *)&state,
139762306a36Sopenharmony_ci				       sizeof(RV770_SMC_SWSTATE),
139862306a36Sopenharmony_ci				       pi->sram_end);
139962306a36Sopenharmony_ci}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ciint rv770_halt_smc(struct radeon_device *rdev)
140262306a36Sopenharmony_ci{
140362306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_Halt) != PPSMC_Result_OK)
140462306a36Sopenharmony_ci		return -EINVAL;
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci	if (rv770_wait_for_smc_inactive(rdev) != PPSMC_Result_OK)
140762306a36Sopenharmony_ci		return -EINVAL;
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	return 0;
141062306a36Sopenharmony_ci}
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ciint rv770_resume_smc(struct radeon_device *rdev)
141362306a36Sopenharmony_ci{
141462306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_Resume) != PPSMC_Result_OK)
141562306a36Sopenharmony_ci		return -EINVAL;
141662306a36Sopenharmony_ci	return 0;
141762306a36Sopenharmony_ci}
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ciint rv770_set_sw_state(struct radeon_device *rdev)
142062306a36Sopenharmony_ci{
142162306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToSwState) != PPSMC_Result_OK)
142262306a36Sopenharmony_ci		DRM_DEBUG("rv770_set_sw_state failed\n");
142362306a36Sopenharmony_ci	return 0;
142462306a36Sopenharmony_ci}
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ciint rv770_set_boot_state(struct radeon_device *rdev)
142762306a36Sopenharmony_ci{
142862306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) != PPSMC_Result_OK)
142962306a36Sopenharmony_ci		return -EINVAL;
143062306a36Sopenharmony_ci	return 0;
143162306a36Sopenharmony_ci}
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_civoid rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
143462306a36Sopenharmony_ci					      struct radeon_ps *new_ps,
143562306a36Sopenharmony_ci					      struct radeon_ps *old_ps)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	struct rv7xx_ps *new_state = rv770_get_ps(new_ps);
143862306a36Sopenharmony_ci	struct rv7xx_ps *current_state = rv770_get_ps(old_ps);
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	if ((new_ps->vclk == old_ps->vclk) &&
144162306a36Sopenharmony_ci	    (new_ps->dclk == old_ps->dclk))
144262306a36Sopenharmony_ci		return;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	if (new_state->high.sclk >= current_state->high.sclk)
144562306a36Sopenharmony_ci		return;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
144862306a36Sopenharmony_ci}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_civoid rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
145162306a36Sopenharmony_ci					     struct radeon_ps *new_ps,
145262306a36Sopenharmony_ci					     struct radeon_ps *old_ps)
145362306a36Sopenharmony_ci{
145462306a36Sopenharmony_ci	struct rv7xx_ps *new_state = rv770_get_ps(new_ps);
145562306a36Sopenharmony_ci	struct rv7xx_ps *current_state = rv770_get_ps(old_ps);
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	if ((new_ps->vclk == old_ps->vclk) &&
145862306a36Sopenharmony_ci	    (new_ps->dclk == old_ps->dclk))
145962306a36Sopenharmony_ci		return;
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	if (new_state->high.sclk < current_state->high.sclk)
146262306a36Sopenharmony_ci		return;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
146562306a36Sopenharmony_ci}
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ciint rv770_restrict_performance_levels_before_switch(struct radeon_device *rdev)
146862306a36Sopenharmony_ci{
146962306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_NoForcedLevel)) != PPSMC_Result_OK)
147062306a36Sopenharmony_ci		return -EINVAL;
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_TwoLevelsDisabled)) != PPSMC_Result_OK)
147362306a36Sopenharmony_ci		return -EINVAL;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	return 0;
147662306a36Sopenharmony_ci}
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ciint rv770_dpm_force_performance_level(struct radeon_device *rdev,
147962306a36Sopenharmony_ci				      enum radeon_dpm_forced_level level)
148062306a36Sopenharmony_ci{
148162306a36Sopenharmony_ci	PPSMC_Msg msg;
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
148462306a36Sopenharmony_ci		if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_ZeroLevelsDisabled) != PPSMC_Result_OK)
148562306a36Sopenharmony_ci			return -EINVAL;
148662306a36Sopenharmony_ci		msg = PPSMC_MSG_ForceHigh;
148762306a36Sopenharmony_ci	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
148862306a36Sopenharmony_ci		if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
148962306a36Sopenharmony_ci			return -EINVAL;
149062306a36Sopenharmony_ci		msg = (PPSMC_Msg)(PPSMC_MSG_TwoLevelsDisabled);
149162306a36Sopenharmony_ci	} else {
149262306a36Sopenharmony_ci		if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
149362306a36Sopenharmony_ci			return -EINVAL;
149462306a36Sopenharmony_ci		msg = (PPSMC_Msg)(PPSMC_MSG_ZeroLevelsDisabled);
149562306a36Sopenharmony_ci	}
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, msg) != PPSMC_Result_OK)
149862306a36Sopenharmony_ci		return -EINVAL;
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	rdev->pm.dpm.forced_level = level;
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	return 0;
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_civoid r7xx_start_smc(struct radeon_device *rdev)
150662306a36Sopenharmony_ci{
150762306a36Sopenharmony_ci	rv770_start_smc(rdev);
150862306a36Sopenharmony_ci	rv770_start_smc_clock(rdev);
150962306a36Sopenharmony_ci}
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_civoid r7xx_stop_smc(struct radeon_device *rdev)
151362306a36Sopenharmony_ci{
151462306a36Sopenharmony_ci	rv770_reset_smc(rdev);
151562306a36Sopenharmony_ci	rv770_stop_smc_clock(rdev);
151662306a36Sopenharmony_ci}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_cistatic void rv770_read_clock_registers(struct radeon_device *rdev)
151962306a36Sopenharmony_ci{
152062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	pi->clk_regs.rv770.cg_spll_func_cntl =
152362306a36Sopenharmony_ci		RREG32(CG_SPLL_FUNC_CNTL);
152462306a36Sopenharmony_ci	pi->clk_regs.rv770.cg_spll_func_cntl_2 =
152562306a36Sopenharmony_ci		RREG32(CG_SPLL_FUNC_CNTL_2);
152662306a36Sopenharmony_ci	pi->clk_regs.rv770.cg_spll_func_cntl_3 =
152762306a36Sopenharmony_ci		RREG32(CG_SPLL_FUNC_CNTL_3);
152862306a36Sopenharmony_ci	pi->clk_regs.rv770.cg_spll_spread_spectrum =
152962306a36Sopenharmony_ci		RREG32(CG_SPLL_SPREAD_SPECTRUM);
153062306a36Sopenharmony_ci	pi->clk_regs.rv770.cg_spll_spread_spectrum_2 =
153162306a36Sopenharmony_ci		RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
153262306a36Sopenharmony_ci	pi->clk_regs.rv770.mpll_ad_func_cntl =
153362306a36Sopenharmony_ci		RREG32(MPLL_AD_FUNC_CNTL);
153462306a36Sopenharmony_ci	pi->clk_regs.rv770.mpll_ad_func_cntl_2 =
153562306a36Sopenharmony_ci		RREG32(MPLL_AD_FUNC_CNTL_2);
153662306a36Sopenharmony_ci	pi->clk_regs.rv770.mpll_dq_func_cntl =
153762306a36Sopenharmony_ci		RREG32(MPLL_DQ_FUNC_CNTL);
153862306a36Sopenharmony_ci	pi->clk_regs.rv770.mpll_dq_func_cntl_2 =
153962306a36Sopenharmony_ci		RREG32(MPLL_DQ_FUNC_CNTL_2);
154062306a36Sopenharmony_ci	pi->clk_regs.rv770.mclk_pwrmgt_cntl =
154162306a36Sopenharmony_ci		RREG32(MCLK_PWRMGT_CNTL);
154262306a36Sopenharmony_ci	pi->clk_regs.rv770.dll_cntl = RREG32(DLL_CNTL);
154362306a36Sopenharmony_ci}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_cistatic void r7xx_read_clock_registers(struct radeon_device *rdev)
154662306a36Sopenharmony_ci{
154762306a36Sopenharmony_ci	if (rdev->family == CHIP_RV740)
154862306a36Sopenharmony_ci		rv740_read_clock_registers(rdev);
154962306a36Sopenharmony_ci	else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
155062306a36Sopenharmony_ci		rv730_read_clock_registers(rdev);
155162306a36Sopenharmony_ci	else
155262306a36Sopenharmony_ci		rv770_read_clock_registers(rdev);
155362306a36Sopenharmony_ci}
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_civoid rv770_read_voltage_smio_registers(struct radeon_device *rdev)
155662306a36Sopenharmony_ci{
155762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	pi->s0_vid_lower_smio_cntl =
156062306a36Sopenharmony_ci		RREG32(S0_VID_LOWER_SMIO_CNTL);
156162306a36Sopenharmony_ci}
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_civoid rv770_reset_smio_status(struct radeon_device *rdev)
156462306a36Sopenharmony_ci{
156562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
156662306a36Sopenharmony_ci	u32 sw_smio_index, vid_smio_cntl;
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	sw_smio_index =
156962306a36Sopenharmony_ci		(RREG32(GENERAL_PWRMGT) & SW_SMIO_INDEX_MASK) >> SW_SMIO_INDEX_SHIFT;
157062306a36Sopenharmony_ci	switch (sw_smio_index) {
157162306a36Sopenharmony_ci	case 3:
157262306a36Sopenharmony_ci		vid_smio_cntl = RREG32(S3_VID_LOWER_SMIO_CNTL);
157362306a36Sopenharmony_ci		break;
157462306a36Sopenharmony_ci	case 2:
157562306a36Sopenharmony_ci		vid_smio_cntl = RREG32(S2_VID_LOWER_SMIO_CNTL);
157662306a36Sopenharmony_ci		break;
157762306a36Sopenharmony_ci	case 1:
157862306a36Sopenharmony_ci		vid_smio_cntl = RREG32(S1_VID_LOWER_SMIO_CNTL);
157962306a36Sopenharmony_ci		break;
158062306a36Sopenharmony_ci	case 0:
158162306a36Sopenharmony_ci		return;
158262306a36Sopenharmony_ci	default:
158362306a36Sopenharmony_ci		vid_smio_cntl = pi->s0_vid_lower_smio_cntl;
158462306a36Sopenharmony_ci		break;
158562306a36Sopenharmony_ci	}
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	WREG32(S0_VID_LOWER_SMIO_CNTL, vid_smio_cntl);
158862306a36Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, SW_SMIO_INDEX(0), ~SW_SMIO_INDEX_MASK);
158962306a36Sopenharmony_ci}
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_civoid rv770_get_memory_type(struct radeon_device *rdev)
159262306a36Sopenharmony_ci{
159362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
159462306a36Sopenharmony_ci	u32 tmp;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	tmp = RREG32(MC_SEQ_MISC0);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	if (((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT) ==
159962306a36Sopenharmony_ci	    MC_SEQ_MISC0_GDDR5_VALUE)
160062306a36Sopenharmony_ci		pi->mem_gddr5 = true;
160162306a36Sopenharmony_ci	else
160262306a36Sopenharmony_ci		pi->mem_gddr5 = false;
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci}
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_civoid rv770_get_pcie_gen2_status(struct radeon_device *rdev)
160762306a36Sopenharmony_ci{
160862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
160962306a36Sopenharmony_ci	u32 tmp;
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
161462306a36Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
161562306a36Sopenharmony_ci		pi->pcie_gen2 = true;
161662306a36Sopenharmony_ci	else
161762306a36Sopenharmony_ci		pi->pcie_gen2 = false;
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci	if (pi->pcie_gen2) {
162062306a36Sopenharmony_ci		if (tmp & LC_CURRENT_DATA_RATE)
162162306a36Sopenharmony_ci			pi->boot_in_gen2 = true;
162262306a36Sopenharmony_ci		else
162362306a36Sopenharmony_ci			pi->boot_in_gen2 = false;
162462306a36Sopenharmony_ci	} else
162562306a36Sopenharmony_ci		pi->boot_in_gen2 = false;
162662306a36Sopenharmony_ci}
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci#if 0
162962306a36Sopenharmony_cistatic int rv770_enter_ulp_state(struct radeon_device *rdev)
163062306a36Sopenharmony_ci{
163162306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	if (pi->gfx_clock_gating) {
163462306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
163562306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
163662306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
163762306a36Sopenharmony_ci		RREG32(GB_TILING_CONFIG);
163862306a36Sopenharmony_ci	}
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower),
164162306a36Sopenharmony_ci		 ~HOST_SMC_MSG_MASK);
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	udelay(7000);
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	return 0;
164662306a36Sopenharmony_ci}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cistatic int rv770_exit_ulp_state(struct radeon_device *rdev)
164962306a36Sopenharmony_ci{
165062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
165162306a36Sopenharmony_ci	int i;
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_ResumeFromMinimumPower),
165462306a36Sopenharmony_ci		 ~HOST_SMC_MSG_MASK);
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	udelay(7000);
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
165962306a36Sopenharmony_ci		if (((RREG32(SMC_MSG) & HOST_SMC_RESP_MASK) >> HOST_SMC_RESP_SHIFT) == 1)
166062306a36Sopenharmony_ci			break;
166162306a36Sopenharmony_ci		udelay(1000);
166262306a36Sopenharmony_ci	}
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
166562306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	return 0;
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci#endif
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_cistatic void rv770_get_mclk_odt_threshold(struct radeon_device *rdev)
167262306a36Sopenharmony_ci{
167362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
167462306a36Sopenharmony_ci	u8 memory_module_index;
167562306a36Sopenharmony_ci	struct atom_memory_info memory_info;
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	pi->mclk_odt_threshold = 0;
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) {
168062306a36Sopenharmony_ci		memory_module_index = rv770_get_memory_module_index(rdev);
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci		if (radeon_atom_get_memory_info(rdev, memory_module_index, &memory_info))
168362306a36Sopenharmony_ci			return;
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci		if (memory_info.mem_type == MEM_TYPE_DDR2 ||
168662306a36Sopenharmony_ci		    memory_info.mem_type == MEM_TYPE_DDR3)
168762306a36Sopenharmony_ci			pi->mclk_odt_threshold = 30000;
168862306a36Sopenharmony_ci	}
168962306a36Sopenharmony_ci}
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_civoid rv770_get_max_vddc(struct radeon_device *rdev)
169262306a36Sopenharmony_ci{
169362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
169462306a36Sopenharmony_ci	u16 vddc;
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc))
169762306a36Sopenharmony_ci		pi->max_vddc = 0;
169862306a36Sopenharmony_ci	else
169962306a36Sopenharmony_ci		pi->max_vddc = vddc;
170062306a36Sopenharmony_ci}
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_civoid rv770_program_response_times(struct radeon_device *rdev)
170362306a36Sopenharmony_ci{
170462306a36Sopenharmony_ci	u32 voltage_response_time, backbias_response_time;
170562306a36Sopenharmony_ci	u32 acpi_delay_time, vbi_time_out;
170662306a36Sopenharmony_ci	u32 vddc_dly, bb_dly, acpi_dly, vbi_dly;
170762306a36Sopenharmony_ci	u32 reference_clock;
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time;
171062306a36Sopenharmony_ci	backbias_response_time = (u32)rdev->pm.dpm.backbias_response_time;
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	if (voltage_response_time == 0)
171362306a36Sopenharmony_ci		voltage_response_time = 1000;
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	if (backbias_response_time == 0)
171662306a36Sopenharmony_ci		backbias_response_time = 1000;
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	acpi_delay_time = 15000;
171962306a36Sopenharmony_ci	vbi_time_out = 100000;
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	reference_clock = radeon_get_xclk(rdev);
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	vddc_dly = (voltage_response_time  * reference_clock) / 1600;
172462306a36Sopenharmony_ci	bb_dly = (backbias_response_time * reference_clock) / 1600;
172562306a36Sopenharmony_ci	acpi_dly = (acpi_delay_time * reference_clock) / 1600;
172662306a36Sopenharmony_ci	vbi_dly = (vbi_time_out * reference_clock) / 1600;
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
172962306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_delay_vreg, vddc_dly);
173062306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
173162306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_delay_bbias, bb_dly);
173262306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
173362306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_delay_acpi, acpi_dly);
173462306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
173562306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
173662306a36Sopenharmony_ci#if 0
173762306a36Sopenharmony_ci	/* XXX look up hw revision */
173862306a36Sopenharmony_ci	if (WEKIVA_A21)
173962306a36Sopenharmony_ci		rv770_write_smc_soft_register(rdev,
174062306a36Sopenharmony_ci					      RV770_SMC_SOFT_REGISTER_baby_step_timer,
174162306a36Sopenharmony_ci					      0x10);
174262306a36Sopenharmony_ci#endif
174362306a36Sopenharmony_ci}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_cistatic void rv770_program_dcodt_before_state_switch(struct radeon_device *rdev,
174662306a36Sopenharmony_ci						    struct radeon_ps *radeon_new_state,
174762306a36Sopenharmony_ci						    struct radeon_ps *radeon_current_state)
174862306a36Sopenharmony_ci{
174962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
175062306a36Sopenharmony_ci	struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state);
175162306a36Sopenharmony_ci	struct rv7xx_ps *current_state = rv770_get_ps(radeon_current_state);
175262306a36Sopenharmony_ci	bool current_use_dc = false;
175362306a36Sopenharmony_ci	bool new_use_dc = false;
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	if (pi->mclk_odt_threshold == 0)
175662306a36Sopenharmony_ci		return;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci	if (current_state->high.mclk <= pi->mclk_odt_threshold)
175962306a36Sopenharmony_ci		current_use_dc = true;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	if (new_state->high.mclk <= pi->mclk_odt_threshold)
176262306a36Sopenharmony_ci		new_use_dc = true;
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci	if (current_use_dc == new_use_dc)
176562306a36Sopenharmony_ci		return;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	if (!current_use_dc && new_use_dc)
176862306a36Sopenharmony_ci		return;
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
177162306a36Sopenharmony_ci		rv730_program_dcodt(rdev, new_use_dc);
177262306a36Sopenharmony_ci}
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_cistatic void rv770_program_dcodt_after_state_switch(struct radeon_device *rdev,
177562306a36Sopenharmony_ci						   struct radeon_ps *radeon_new_state,
177662306a36Sopenharmony_ci						   struct radeon_ps *radeon_current_state)
177762306a36Sopenharmony_ci{
177862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
177962306a36Sopenharmony_ci	struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state);
178062306a36Sopenharmony_ci	struct rv7xx_ps *current_state = rv770_get_ps(radeon_current_state);
178162306a36Sopenharmony_ci	bool current_use_dc = false;
178262306a36Sopenharmony_ci	bool new_use_dc = false;
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	if (pi->mclk_odt_threshold == 0)
178562306a36Sopenharmony_ci		return;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	if (current_state->high.mclk <= pi->mclk_odt_threshold)
178862306a36Sopenharmony_ci		current_use_dc = true;
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	if (new_state->high.mclk <= pi->mclk_odt_threshold)
179162306a36Sopenharmony_ci		new_use_dc = true;
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	if (current_use_dc == new_use_dc)
179462306a36Sopenharmony_ci		return;
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	if (current_use_dc && !new_use_dc)
179762306a36Sopenharmony_ci		return;
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
180062306a36Sopenharmony_ci		rv730_program_dcodt(rdev, new_use_dc);
180162306a36Sopenharmony_ci}
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_cistatic void rv770_retrieve_odt_values(struct radeon_device *rdev)
180462306a36Sopenharmony_ci{
180562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	if (pi->mclk_odt_threshold == 0)
180862306a36Sopenharmony_ci		return;
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
181162306a36Sopenharmony_ci		rv730_get_odt_values(rdev);
181262306a36Sopenharmony_ci}
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_cistatic void rv770_set_dpm_event_sources(struct radeon_device *rdev, u32 sources)
181562306a36Sopenharmony_ci{
181662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
181762306a36Sopenharmony_ci	bool want_thermal_protection;
181862306a36Sopenharmony_ci	enum radeon_dpm_event_src dpm_event_src;
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	switch (sources) {
182162306a36Sopenharmony_ci	case 0:
182262306a36Sopenharmony_ci	default:
182362306a36Sopenharmony_ci		want_thermal_protection = false;
182462306a36Sopenharmony_ci		break;
182562306a36Sopenharmony_ci	case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL):
182662306a36Sopenharmony_ci		want_thermal_protection = true;
182762306a36Sopenharmony_ci		dpm_event_src = RADEON_DPM_EVENT_SRC_DIGITAL;
182862306a36Sopenharmony_ci		break;
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL):
183162306a36Sopenharmony_ci		want_thermal_protection = true;
183262306a36Sopenharmony_ci		dpm_event_src = RADEON_DPM_EVENT_SRC_EXTERNAL;
183362306a36Sopenharmony_ci		break;
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	case ((1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL) |
183662306a36Sopenharmony_ci	      (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL)):
183762306a36Sopenharmony_ci		want_thermal_protection = true;
183862306a36Sopenharmony_ci		dpm_event_src = RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL;
183962306a36Sopenharmony_ci		break;
184062306a36Sopenharmony_ci	}
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	if (want_thermal_protection) {
184362306a36Sopenharmony_ci		WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK);
184462306a36Sopenharmony_ci		if (pi->thermal_protection)
184562306a36Sopenharmony_ci			WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
184662306a36Sopenharmony_ci	} else {
184762306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
184862306a36Sopenharmony_ci	}
184962306a36Sopenharmony_ci}
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_civoid rv770_enable_auto_throttle_source(struct radeon_device *rdev,
185262306a36Sopenharmony_ci				       enum radeon_dpm_auto_throttle_src source,
185362306a36Sopenharmony_ci				       bool enable)
185462306a36Sopenharmony_ci{
185562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci	if (enable) {
185862306a36Sopenharmony_ci		if (!(pi->active_auto_throttle_sources & (1 << source))) {
185962306a36Sopenharmony_ci			pi->active_auto_throttle_sources |= 1 << source;
186062306a36Sopenharmony_ci			rv770_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources);
186162306a36Sopenharmony_ci		}
186262306a36Sopenharmony_ci	} else {
186362306a36Sopenharmony_ci		if (pi->active_auto_throttle_sources & (1 << source)) {
186462306a36Sopenharmony_ci			pi->active_auto_throttle_sources &= ~(1 << source);
186562306a36Sopenharmony_ci			rv770_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources);
186662306a36Sopenharmony_ci		}
186762306a36Sopenharmony_ci	}
186862306a36Sopenharmony_ci}
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_cistatic int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
187162306a36Sopenharmony_ci					       int min_temp, int max_temp)
187262306a36Sopenharmony_ci{
187362306a36Sopenharmony_ci	int low_temp = 0 * 1000;
187462306a36Sopenharmony_ci	int high_temp = 255 * 1000;
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci	if (low_temp < min_temp)
187762306a36Sopenharmony_ci		low_temp = min_temp;
187862306a36Sopenharmony_ci	if (high_temp > max_temp)
187962306a36Sopenharmony_ci		high_temp = max_temp;
188062306a36Sopenharmony_ci	if (high_temp < low_temp) {
188162306a36Sopenharmony_ci		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
188262306a36Sopenharmony_ci		return -EINVAL;
188362306a36Sopenharmony_ci	}
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK);
188662306a36Sopenharmony_ci	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK);
188762306a36Sopenharmony_ci	WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK);
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	rdev->pm.dpm.thermal.min_temp = low_temp;
189062306a36Sopenharmony_ci	rdev->pm.dpm.thermal.max_temp = high_temp;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	return 0;
189362306a36Sopenharmony_ci}
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ciint rv770_dpm_enable(struct radeon_device *rdev)
189662306a36Sopenharmony_ci{
189762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
189862306a36Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
189962306a36Sopenharmony_ci	int ret;
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
190262306a36Sopenharmony_ci		rv770_restore_cgcg(rdev);
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	if (rv770_dpm_enabled(rdev))
190562306a36Sopenharmony_ci		return -EINVAL;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	if (pi->voltage_control) {
190862306a36Sopenharmony_ci		rv770_enable_voltage_control(rdev, true);
190962306a36Sopenharmony_ci		ret = rv770_construct_vddc_table(rdev);
191062306a36Sopenharmony_ci		if (ret) {
191162306a36Sopenharmony_ci			DRM_ERROR("rv770_construct_vddc_table failed\n");
191262306a36Sopenharmony_ci			return ret;
191362306a36Sopenharmony_ci		}
191462306a36Sopenharmony_ci	}
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	if (pi->dcodt)
191762306a36Sopenharmony_ci		rv770_retrieve_odt_values(rdev);
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	if (pi->mvdd_control) {
192062306a36Sopenharmony_ci		ret = rv770_get_mvdd_configuration(rdev);
192162306a36Sopenharmony_ci		if (ret) {
192262306a36Sopenharmony_ci			DRM_ERROR("rv770_get_mvdd_configuration failed\n");
192362306a36Sopenharmony_ci			return ret;
192462306a36Sopenharmony_ci		}
192562306a36Sopenharmony_ci	}
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS)
192862306a36Sopenharmony_ci		rv770_enable_backbias(rdev, true);
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	rv770_enable_spread_spectrum(rdev, true);
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_ci	if (pi->thermal_protection)
193362306a36Sopenharmony_ci		rv770_enable_thermal_protection(rdev, true);
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	rv770_program_mpll_timing_parameters(rdev);
193662306a36Sopenharmony_ci	rv770_setup_bsp(rdev);
193762306a36Sopenharmony_ci	rv770_program_git(rdev);
193862306a36Sopenharmony_ci	rv770_program_tp(rdev);
193962306a36Sopenharmony_ci	rv770_program_tpp(rdev);
194062306a36Sopenharmony_ci	rv770_program_sstp(rdev);
194162306a36Sopenharmony_ci	rv770_program_engine_speed_parameters(rdev);
194262306a36Sopenharmony_ci	rv770_enable_display_gap(rdev);
194362306a36Sopenharmony_ci	rv770_program_vc(rdev);
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
194662306a36Sopenharmony_ci		rv770_enable_dynamic_pcie_gen2(rdev, true);
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	ret = rv770_upload_firmware(rdev);
194962306a36Sopenharmony_ci	if (ret) {
195062306a36Sopenharmony_ci		DRM_ERROR("rv770_upload_firmware failed\n");
195162306a36Sopenharmony_ci		return ret;
195262306a36Sopenharmony_ci	}
195362306a36Sopenharmony_ci	ret = rv770_init_smc_table(rdev, boot_ps);
195462306a36Sopenharmony_ci	if (ret) {
195562306a36Sopenharmony_ci		DRM_ERROR("rv770_init_smc_table failed\n");
195662306a36Sopenharmony_ci		return ret;
195762306a36Sopenharmony_ci	}
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci	rv770_program_response_times(rdev);
196062306a36Sopenharmony_ci	r7xx_start_smc(rdev);
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
196362306a36Sopenharmony_ci		rv730_start_dpm(rdev);
196462306a36Sopenharmony_ci	else
196562306a36Sopenharmony_ci		rv770_start_dpm(rdev);
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
196862306a36Sopenharmony_ci		rv770_gfx_clock_gating_enable(rdev, true);
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	if (pi->mg_clock_gating)
197162306a36Sopenharmony_ci		rv770_mg_clock_gating_enable(rdev, true);
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	return 0;
197662306a36Sopenharmony_ci}
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ciint rv770_dpm_late_enable(struct radeon_device *rdev)
197962306a36Sopenharmony_ci{
198062306a36Sopenharmony_ci	int ret;
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	if (rdev->irq.installed &&
198362306a36Sopenharmony_ci	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
198462306a36Sopenharmony_ci		PPSMC_Result result;
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci		ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
198762306a36Sopenharmony_ci		if (ret)
198862306a36Sopenharmony_ci			return ret;
198962306a36Sopenharmony_ci		rdev->irq.dpm_thermal = true;
199062306a36Sopenharmony_ci		radeon_irq_set(rdev);
199162306a36Sopenharmony_ci		result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci		if (result != PPSMC_Result_OK)
199462306a36Sopenharmony_ci			DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
199562306a36Sopenharmony_ci	}
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	return 0;
199862306a36Sopenharmony_ci}
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_civoid rv770_dpm_disable(struct radeon_device *rdev)
200162306a36Sopenharmony_ci{
200262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci	if (!rv770_dpm_enabled(rdev))
200562306a36Sopenharmony_ci		return;
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	rv770_clear_vc(rdev);
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	if (pi->thermal_protection)
201062306a36Sopenharmony_ci		rv770_enable_thermal_protection(rdev, false);
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	rv770_enable_spread_spectrum(rdev, false);
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
201562306a36Sopenharmony_ci		rv770_enable_dynamic_pcie_gen2(rdev, false);
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	if (rdev->irq.installed &&
201862306a36Sopenharmony_ci	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
201962306a36Sopenharmony_ci		rdev->irq.dpm_thermal = false;
202062306a36Sopenharmony_ci		radeon_irq_set(rdev);
202162306a36Sopenharmony_ci	}
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
202462306a36Sopenharmony_ci		rv770_gfx_clock_gating_enable(rdev, false);
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	if (pi->mg_clock_gating)
202762306a36Sopenharmony_ci		rv770_mg_clock_gating_enable(rdev, false);
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
203062306a36Sopenharmony_ci		rv730_stop_dpm(rdev);
203162306a36Sopenharmony_ci	else
203262306a36Sopenharmony_ci		rv770_stop_dpm(rdev);
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci	r7xx_stop_smc(rdev);
203562306a36Sopenharmony_ci	rv770_reset_smio_status(rdev);
203662306a36Sopenharmony_ci}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ciint rv770_dpm_set_power_state(struct radeon_device *rdev)
203962306a36Sopenharmony_ci{
204062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
204162306a36Sopenharmony_ci	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
204262306a36Sopenharmony_ci	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
204362306a36Sopenharmony_ci	int ret;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	ret = rv770_restrict_performance_levels_before_switch(rdev);
204662306a36Sopenharmony_ci	if (ret) {
204762306a36Sopenharmony_ci		DRM_ERROR("rv770_restrict_performance_levels_before_switch failed\n");
204862306a36Sopenharmony_ci		return ret;
204962306a36Sopenharmony_ci	}
205062306a36Sopenharmony_ci	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
205162306a36Sopenharmony_ci	ret = rv770_halt_smc(rdev);
205262306a36Sopenharmony_ci	if (ret) {
205362306a36Sopenharmony_ci		DRM_ERROR("rv770_halt_smc failed\n");
205462306a36Sopenharmony_ci		return ret;
205562306a36Sopenharmony_ci	}
205662306a36Sopenharmony_ci	ret = rv770_upload_sw_state(rdev, new_ps);
205762306a36Sopenharmony_ci	if (ret) {
205862306a36Sopenharmony_ci		DRM_ERROR("rv770_upload_sw_state failed\n");
205962306a36Sopenharmony_ci		return ret;
206062306a36Sopenharmony_ci	}
206162306a36Sopenharmony_ci	r7xx_program_memory_timing_parameters(rdev, new_ps);
206262306a36Sopenharmony_ci	if (pi->dcodt)
206362306a36Sopenharmony_ci		rv770_program_dcodt_before_state_switch(rdev, new_ps, old_ps);
206462306a36Sopenharmony_ci	ret = rv770_resume_smc(rdev);
206562306a36Sopenharmony_ci	if (ret) {
206662306a36Sopenharmony_ci		DRM_ERROR("rv770_resume_smc failed\n");
206762306a36Sopenharmony_ci		return ret;
206862306a36Sopenharmony_ci	}
206962306a36Sopenharmony_ci	ret = rv770_set_sw_state(rdev);
207062306a36Sopenharmony_ci	if (ret) {
207162306a36Sopenharmony_ci		DRM_ERROR("rv770_set_sw_state failed\n");
207262306a36Sopenharmony_ci		return ret;
207362306a36Sopenharmony_ci	}
207462306a36Sopenharmony_ci	if (pi->dcodt)
207562306a36Sopenharmony_ci		rv770_program_dcodt_after_state_switch(rdev, new_ps, old_ps);
207662306a36Sopenharmony_ci	rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci	return 0;
207962306a36Sopenharmony_ci}
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci#if 0
208262306a36Sopenharmony_civoid rv770_dpm_reset_asic(struct radeon_device *rdev)
208362306a36Sopenharmony_ci{
208462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
208562306a36Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	rv770_restrict_performance_levels_before_switch(rdev);
208862306a36Sopenharmony_ci	if (pi->dcodt)
208962306a36Sopenharmony_ci		rv770_program_dcodt_before_state_switch(rdev, boot_ps, boot_ps);
209062306a36Sopenharmony_ci	rv770_set_boot_state(rdev);
209162306a36Sopenharmony_ci	if (pi->dcodt)
209262306a36Sopenharmony_ci		rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps);
209362306a36Sopenharmony_ci}
209462306a36Sopenharmony_ci#endif
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_civoid rv770_dpm_setup_asic(struct radeon_device *rdev)
209762306a36Sopenharmony_ci{
209862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	r7xx_read_clock_registers(rdev);
210162306a36Sopenharmony_ci	rv770_read_voltage_smio_registers(rdev);
210262306a36Sopenharmony_ci	rv770_get_memory_type(rdev);
210362306a36Sopenharmony_ci	if (pi->dcodt)
210462306a36Sopenharmony_ci		rv770_get_mclk_odt_threshold(rdev);
210562306a36Sopenharmony_ci	rv770_get_pcie_gen2_status(rdev);
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci	rv770_enable_acpi_pm(rdev);
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci	if (radeon_aspm != 0) {
211062306a36Sopenharmony_ci		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s)
211162306a36Sopenharmony_ci			rv770_enable_l0s(rdev);
211262306a36Sopenharmony_ci		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1)
211362306a36Sopenharmony_ci			rv770_enable_l1(rdev);
211462306a36Sopenharmony_ci		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1)
211562306a36Sopenharmony_ci			rv770_enable_pll_sleep_in_l1(rdev);
211662306a36Sopenharmony_ci	}
211762306a36Sopenharmony_ci}
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_civoid rv770_dpm_display_configuration_changed(struct radeon_device *rdev)
212062306a36Sopenharmony_ci{
212162306a36Sopenharmony_ci	rv770_program_display_gap(rdev);
212262306a36Sopenharmony_ci}
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ciunion power_info {
212562306a36Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO info;
212662306a36Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V2 info_2;
212762306a36Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V3 info_3;
212862306a36Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
212962306a36Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
213062306a36Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
213162306a36Sopenharmony_ci};
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ciunion pplib_clock_info {
213462306a36Sopenharmony_ci	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
213562306a36Sopenharmony_ci	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
213662306a36Sopenharmony_ci	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
213762306a36Sopenharmony_ci	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
213862306a36Sopenharmony_ci};
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ciunion pplib_power_state {
214162306a36Sopenharmony_ci	struct _ATOM_PPLIB_STATE v1;
214262306a36Sopenharmony_ci	struct _ATOM_PPLIB_STATE_V2 v2;
214362306a36Sopenharmony_ci};
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_cistatic void rv7xx_parse_pplib_non_clock_info(struct radeon_device *rdev,
214662306a36Sopenharmony_ci					     struct radeon_ps *rps,
214762306a36Sopenharmony_ci					     struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
214862306a36Sopenharmony_ci					     u8 table_rev)
214962306a36Sopenharmony_ci{
215062306a36Sopenharmony_ci	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
215162306a36Sopenharmony_ci	rps->class = le16_to_cpu(non_clock_info->usClassification);
215262306a36Sopenharmony_ci	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
215562306a36Sopenharmony_ci		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
215662306a36Sopenharmony_ci		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
215762306a36Sopenharmony_ci	} else {
215862306a36Sopenharmony_ci		rps->vclk = 0;
215962306a36Sopenharmony_ci		rps->dclk = 0;
216062306a36Sopenharmony_ci	}
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	if (r600_is_uvd_state(rps->class, rps->class2)) {
216362306a36Sopenharmony_ci		if ((rps->vclk == 0) || (rps->dclk == 0)) {
216462306a36Sopenharmony_ci			rps->vclk = RV770_DEFAULT_VCLK_FREQ;
216562306a36Sopenharmony_ci			rps->dclk = RV770_DEFAULT_DCLK_FREQ;
216662306a36Sopenharmony_ci		}
216762306a36Sopenharmony_ci	}
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
217062306a36Sopenharmony_ci		rdev->pm.dpm.boot_ps = rps;
217162306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
217262306a36Sopenharmony_ci		rdev->pm.dpm.uvd_ps = rps;
217362306a36Sopenharmony_ci}
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_cistatic void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
217662306a36Sopenharmony_ci					 struct radeon_ps *rps, int index,
217762306a36Sopenharmony_ci					 union pplib_clock_info *clock_info)
217862306a36Sopenharmony_ci{
217962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
218062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
218162306a36Sopenharmony_ci	struct rv7xx_ps *ps = rv770_get_ps(rps);
218262306a36Sopenharmony_ci	u32 sclk, mclk;
218362306a36Sopenharmony_ci	struct rv7xx_pl *pl;
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci	switch (index) {
218662306a36Sopenharmony_ci	case 0:
218762306a36Sopenharmony_ci		pl = &ps->low;
218862306a36Sopenharmony_ci		break;
218962306a36Sopenharmony_ci	case 1:
219062306a36Sopenharmony_ci		pl = &ps->medium;
219162306a36Sopenharmony_ci		break;
219262306a36Sopenharmony_ci	case 2:
219362306a36Sopenharmony_ci	default:
219462306a36Sopenharmony_ci		pl = &ps->high;
219562306a36Sopenharmony_ci		break;
219662306a36Sopenharmony_ci	}
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	if (rdev->family >= CHIP_CEDAR) {
219962306a36Sopenharmony_ci		sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
220062306a36Sopenharmony_ci		sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
220162306a36Sopenharmony_ci		mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
220262306a36Sopenharmony_ci		mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci		pl->vddc = le16_to_cpu(clock_info->evergreen.usVDDC);
220562306a36Sopenharmony_ci		pl->vddci = le16_to_cpu(clock_info->evergreen.usVDDCI);
220662306a36Sopenharmony_ci		pl->flags = le32_to_cpu(clock_info->evergreen.ulFlags);
220762306a36Sopenharmony_ci	} else {
220862306a36Sopenharmony_ci		sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
220962306a36Sopenharmony_ci		sclk |= clock_info->r600.ucEngineClockHigh << 16;
221062306a36Sopenharmony_ci		mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow);
221162306a36Sopenharmony_ci		mclk |= clock_info->r600.ucMemoryClockHigh << 16;
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci		pl->vddc = le16_to_cpu(clock_info->r600.usVDDC);
221462306a36Sopenharmony_ci		pl->flags = le32_to_cpu(clock_info->r600.ulFlags);
221562306a36Sopenharmony_ci	}
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci	pl->mclk = mclk;
221862306a36Sopenharmony_ci	pl->sclk = sclk;
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci	/* patch up vddc if necessary */
222162306a36Sopenharmony_ci	if (pl->vddc == 0xff01) {
222262306a36Sopenharmony_ci		if (pi->max_vddc)
222362306a36Sopenharmony_ci			pl->vddc = pi->max_vddc;
222462306a36Sopenharmony_ci	}
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
222762306a36Sopenharmony_ci		pi->acpi_vddc = pl->vddc;
222862306a36Sopenharmony_ci		if (rdev->family >= CHIP_CEDAR)
222962306a36Sopenharmony_ci			eg_pi->acpi_vddci = pl->vddci;
223062306a36Sopenharmony_ci		if (ps->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
223162306a36Sopenharmony_ci			pi->acpi_pcie_gen2 = true;
223262306a36Sopenharmony_ci		else
223362306a36Sopenharmony_ci			pi->acpi_pcie_gen2 = false;
223462306a36Sopenharmony_ci	}
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	if (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) {
223762306a36Sopenharmony_ci		if (rdev->family >= CHIP_BARTS) {
223862306a36Sopenharmony_ci			eg_pi->ulv.supported = true;
223962306a36Sopenharmony_ci			eg_pi->ulv.pl = pl;
224062306a36Sopenharmony_ci		}
224162306a36Sopenharmony_ci	}
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci	if (pi->min_vddc_in_table > pl->vddc)
224462306a36Sopenharmony_ci		pi->min_vddc_in_table = pl->vddc;
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci	if (pi->max_vddc_in_table < pl->vddc)
224762306a36Sopenharmony_ci		pi->max_vddc_in_table = pl->vddc;
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	/* patch up boot state */
225062306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
225162306a36Sopenharmony_ci		u16 vddc, vddci, mvdd;
225262306a36Sopenharmony_ci		radeon_atombios_get_default_voltages(rdev, &vddc, &vddci, &mvdd);
225362306a36Sopenharmony_ci		pl->mclk = rdev->clock.default_mclk;
225462306a36Sopenharmony_ci		pl->sclk = rdev->clock.default_sclk;
225562306a36Sopenharmony_ci		pl->vddc = vddc;
225662306a36Sopenharmony_ci		pl->vddci = vddci;
225762306a36Sopenharmony_ci	}
225862306a36Sopenharmony_ci
225962306a36Sopenharmony_ci	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
226062306a36Sopenharmony_ci	    ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
226162306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
226262306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
226362306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
226462306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
226562306a36Sopenharmony_ci	}
226662306a36Sopenharmony_ci}
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ciint rv7xx_parse_power_table(struct radeon_device *rdev)
226962306a36Sopenharmony_ci{
227062306a36Sopenharmony_ci	struct radeon_mode_info *mode_info = &rdev->mode_info;
227162306a36Sopenharmony_ci	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
227262306a36Sopenharmony_ci	union pplib_power_state *power_state;
227362306a36Sopenharmony_ci	int i, j;
227462306a36Sopenharmony_ci	union pplib_clock_info *clock_info;
227562306a36Sopenharmony_ci	union power_info *power_info;
227662306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
227762306a36Sopenharmony_ci	u16 data_offset;
227862306a36Sopenharmony_ci	u8 frev, crev;
227962306a36Sopenharmony_ci	struct rv7xx_ps *ps;
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
228262306a36Sopenharmony_ci				   &frev, &crev, &data_offset))
228362306a36Sopenharmony_ci		return -EINVAL;
228462306a36Sopenharmony_ci	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
228762306a36Sopenharmony_ci				  sizeof(struct radeon_ps),
228862306a36Sopenharmony_ci				  GFP_KERNEL);
228962306a36Sopenharmony_ci	if (!rdev->pm.dpm.ps)
229062306a36Sopenharmony_ci		return -ENOMEM;
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
229362306a36Sopenharmony_ci		power_state = (union pplib_power_state *)
229462306a36Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
229562306a36Sopenharmony_ci			 le16_to_cpu(power_info->pplib.usStateArrayOffset) +
229662306a36Sopenharmony_ci			 i * power_info->pplib.ucStateEntrySize);
229762306a36Sopenharmony_ci		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
229862306a36Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
229962306a36Sopenharmony_ci			 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
230062306a36Sopenharmony_ci			 (power_state->v1.ucNonClockStateIndex *
230162306a36Sopenharmony_ci			  power_info->pplib.ucNonClockSize));
230262306a36Sopenharmony_ci		if (power_info->pplib.ucStateEntrySize - 1) {
230362306a36Sopenharmony_ci			u8 *idx;
230462306a36Sopenharmony_ci			ps = kzalloc(sizeof(struct rv7xx_ps), GFP_KERNEL);
230562306a36Sopenharmony_ci			if (ps == NULL) {
230662306a36Sopenharmony_ci				kfree(rdev->pm.dpm.ps);
230762306a36Sopenharmony_ci				return -ENOMEM;
230862306a36Sopenharmony_ci			}
230962306a36Sopenharmony_ci			rdev->pm.dpm.ps[i].ps_priv = ps;
231062306a36Sopenharmony_ci			rv7xx_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
231162306a36Sopenharmony_ci							 non_clock_info,
231262306a36Sopenharmony_ci							 power_info->pplib.ucNonClockSize);
231362306a36Sopenharmony_ci			idx = (u8 *)&power_state->v1.ucClockStateIndices[0];
231462306a36Sopenharmony_ci			for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
231562306a36Sopenharmony_ci				clock_info = (union pplib_clock_info *)
231662306a36Sopenharmony_ci					(mode_info->atom_context->bios + data_offset +
231762306a36Sopenharmony_ci					 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
231862306a36Sopenharmony_ci					 (idx[j] * power_info->pplib.ucClockInfoSize));
231962306a36Sopenharmony_ci				rv7xx_parse_pplib_clock_info(rdev,
232062306a36Sopenharmony_ci							     &rdev->pm.dpm.ps[i], j,
232162306a36Sopenharmony_ci							     clock_info);
232262306a36Sopenharmony_ci			}
232362306a36Sopenharmony_ci		}
232462306a36Sopenharmony_ci	}
232562306a36Sopenharmony_ci	rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates;
232662306a36Sopenharmony_ci	return 0;
232762306a36Sopenharmony_ci}
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_civoid rv770_get_engine_memory_ss(struct radeon_device *rdev)
233062306a36Sopenharmony_ci{
233162306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
233262306a36Sopenharmony_ci	struct radeon_atom_ss ss;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	pi->sclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
233562306a36Sopenharmony_ci						       ASIC_INTERNAL_ENGINE_SS, 0);
233662306a36Sopenharmony_ci	pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
233762306a36Sopenharmony_ci						       ASIC_INTERNAL_MEMORY_SS, 0);
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	if (pi->sclk_ss || pi->mclk_ss)
234062306a36Sopenharmony_ci		pi->dynamic_ss = true;
234162306a36Sopenharmony_ci	else
234262306a36Sopenharmony_ci		pi->dynamic_ss = false;
234362306a36Sopenharmony_ci}
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ciint rv770_dpm_init(struct radeon_device *rdev)
234662306a36Sopenharmony_ci{
234762306a36Sopenharmony_ci	struct rv7xx_power_info *pi;
234862306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
234962306a36Sopenharmony_ci	int ret;
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci	pi = kzalloc(sizeof(struct rv7xx_power_info), GFP_KERNEL);
235262306a36Sopenharmony_ci	if (pi == NULL)
235362306a36Sopenharmony_ci		return -ENOMEM;
235462306a36Sopenharmony_ci	rdev->pm.dpm.priv = pi;
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci	rv770_get_max_vddc(rdev);
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci	pi->acpi_vddc = 0;
235962306a36Sopenharmony_ci	pi->min_vddc_in_table = 0;
236062306a36Sopenharmony_ci	pi->max_vddc_in_table = 0;
236162306a36Sopenharmony_ci
236262306a36Sopenharmony_ci	ret = r600_get_platform_caps(rdev);
236362306a36Sopenharmony_ci	if (ret)
236462306a36Sopenharmony_ci		return ret;
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	ret = rv7xx_parse_power_table(rdev);
236762306a36Sopenharmony_ci	if (ret)
236862306a36Sopenharmony_ci		return ret;
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci	if (rdev->pm.dpm.voltage_response_time == 0)
237162306a36Sopenharmony_ci		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
237262306a36Sopenharmony_ci	if (rdev->pm.dpm.backbias_response_time == 0)
237362306a36Sopenharmony_ci		rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
237662306a36Sopenharmony_ci					     0, false, &dividers);
237762306a36Sopenharmony_ci	if (ret)
237862306a36Sopenharmony_ci		pi->ref_div = dividers.ref_div + 1;
237962306a36Sopenharmony_ci	else
238062306a36Sopenharmony_ci		pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci	pi->mclk_strobe_mode_threshold = 30000;
238362306a36Sopenharmony_ci	pi->mclk_edc_enable_threshold = 30000;
238462306a36Sopenharmony_ci
238562306a36Sopenharmony_ci	pi->rlp = RV770_RLP_DFLT;
238662306a36Sopenharmony_ci	pi->rmp = RV770_RMP_DFLT;
238762306a36Sopenharmony_ci	pi->lhp = RV770_LHP_DFLT;
238862306a36Sopenharmony_ci	pi->lmp = RV770_LMP_DFLT;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	pi->voltage_control =
239162306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, 0);
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	pi->mvdd_control =
239462306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0);
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	rv770_get_engine_memory_ss(rdev);
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	pi->asi = RV770_ASI_DFLT;
239962306a36Sopenharmony_ci	pi->pasi = RV770_HASI_DFLT;
240062306a36Sopenharmony_ci	pi->vrc = RV770_VRC_DFLT;
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	pi->power_gating = false;
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci	pi->gfx_clock_gating = true;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	pi->mg_clock_gating = true;
240762306a36Sopenharmony_ci	pi->mgcgtssm = true;
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	pi->dynamic_pcie_gen2 = true;
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
241262306a36Sopenharmony_ci		pi->thermal_protection = true;
241362306a36Sopenharmony_ci	else
241462306a36Sopenharmony_ci		pi->thermal_protection = false;
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	pi->display_gap = true;
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_MOBILITY)
241962306a36Sopenharmony_ci		pi->dcodt = true;
242062306a36Sopenharmony_ci	else
242162306a36Sopenharmony_ci		pi->dcodt = false;
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	pi->ulps = true;
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_ci	pi->mclk_stutter_mode_threshold = 0;
242662306a36Sopenharmony_ci
242762306a36Sopenharmony_ci	pi->sram_end = SMC_RAM_END;
242862306a36Sopenharmony_ci	pi->state_table_start = RV770_SMC_TABLE_ADDRESS;
242962306a36Sopenharmony_ci	pi->soft_regs_start = RV770_SMC_SOFT_REGISTERS_START;
243062306a36Sopenharmony_ci
243162306a36Sopenharmony_ci	return 0;
243262306a36Sopenharmony_ci}
243362306a36Sopenharmony_ci
243462306a36Sopenharmony_civoid rv770_dpm_print_power_state(struct radeon_device *rdev,
243562306a36Sopenharmony_ci				 struct radeon_ps *rps)
243662306a36Sopenharmony_ci{
243762306a36Sopenharmony_ci	struct rv7xx_ps *ps = rv770_get_ps(rps);
243862306a36Sopenharmony_ci	struct rv7xx_pl *pl;
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci	r600_dpm_print_class_info(rps->class, rps->class2);
244162306a36Sopenharmony_ci	r600_dpm_print_cap_info(rps->caps);
244262306a36Sopenharmony_ci	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
244362306a36Sopenharmony_ci	if (rdev->family >= CHIP_CEDAR) {
244462306a36Sopenharmony_ci		pl = &ps->low;
244562306a36Sopenharmony_ci		printk("\t\tpower level 0    sclk: %u mclk: %u vddc: %u vddci: %u\n",
244662306a36Sopenharmony_ci		       pl->sclk, pl->mclk, pl->vddc, pl->vddci);
244762306a36Sopenharmony_ci		pl = &ps->medium;
244862306a36Sopenharmony_ci		printk("\t\tpower level 1    sclk: %u mclk: %u vddc: %u vddci: %u\n",
244962306a36Sopenharmony_ci		       pl->sclk, pl->mclk, pl->vddc, pl->vddci);
245062306a36Sopenharmony_ci		pl = &ps->high;
245162306a36Sopenharmony_ci		printk("\t\tpower level 2    sclk: %u mclk: %u vddc: %u vddci: %u\n",
245262306a36Sopenharmony_ci		       pl->sclk, pl->mclk, pl->vddc, pl->vddci);
245362306a36Sopenharmony_ci	} else {
245462306a36Sopenharmony_ci		pl = &ps->low;
245562306a36Sopenharmony_ci		printk("\t\tpower level 0    sclk: %u mclk: %u vddc: %u\n",
245662306a36Sopenharmony_ci		       pl->sclk, pl->mclk, pl->vddc);
245762306a36Sopenharmony_ci		pl = &ps->medium;
245862306a36Sopenharmony_ci		printk("\t\tpower level 1    sclk: %u mclk: %u vddc: %u\n",
245962306a36Sopenharmony_ci		       pl->sclk, pl->mclk, pl->vddc);
246062306a36Sopenharmony_ci		pl = &ps->high;
246162306a36Sopenharmony_ci		printk("\t\tpower level 2    sclk: %u mclk: %u vddc: %u\n",
246262306a36Sopenharmony_ci		       pl->sclk, pl->mclk, pl->vddc);
246362306a36Sopenharmony_ci	}
246462306a36Sopenharmony_ci	r600_dpm_print_ps_status(rdev, rps);
246562306a36Sopenharmony_ci}
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_civoid rv770_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
246862306a36Sopenharmony_ci						       struct seq_file *m)
246962306a36Sopenharmony_ci{
247062306a36Sopenharmony_ci	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
247162306a36Sopenharmony_ci	struct rv7xx_ps *ps = rv770_get_ps(rps);
247262306a36Sopenharmony_ci	struct rv7xx_pl *pl;
247362306a36Sopenharmony_ci	u32 current_index =
247462306a36Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
247562306a36Sopenharmony_ci		CURRENT_PROFILE_INDEX_SHIFT;
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci	if (current_index > 2) {
247862306a36Sopenharmony_ci		seq_printf(m, "invalid dpm profile %d\n", current_index);
247962306a36Sopenharmony_ci	} else {
248062306a36Sopenharmony_ci		if (current_index == 0)
248162306a36Sopenharmony_ci			pl = &ps->low;
248262306a36Sopenharmony_ci		else if (current_index == 1)
248362306a36Sopenharmony_ci			pl = &ps->medium;
248462306a36Sopenharmony_ci		else /* current_index == 2 */
248562306a36Sopenharmony_ci			pl = &ps->high;
248662306a36Sopenharmony_ci		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
248762306a36Sopenharmony_ci		if (rdev->family >= CHIP_CEDAR) {
248862306a36Sopenharmony_ci			seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
248962306a36Sopenharmony_ci				   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
249062306a36Sopenharmony_ci		} else {
249162306a36Sopenharmony_ci			seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u\n",
249262306a36Sopenharmony_ci				   current_index, pl->sclk, pl->mclk, pl->vddc);
249362306a36Sopenharmony_ci		}
249462306a36Sopenharmony_ci	}
249562306a36Sopenharmony_ci}
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_ciu32 rv770_dpm_get_current_sclk(struct radeon_device *rdev)
249862306a36Sopenharmony_ci{
249962306a36Sopenharmony_ci	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
250062306a36Sopenharmony_ci	struct rv7xx_ps *ps = rv770_get_ps(rps);
250162306a36Sopenharmony_ci	struct rv7xx_pl *pl;
250262306a36Sopenharmony_ci	u32 current_index =
250362306a36Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
250462306a36Sopenharmony_ci		CURRENT_PROFILE_INDEX_SHIFT;
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci	if (current_index > 2) {
250762306a36Sopenharmony_ci		return 0;
250862306a36Sopenharmony_ci	} else {
250962306a36Sopenharmony_ci		if (current_index == 0)
251062306a36Sopenharmony_ci			pl = &ps->low;
251162306a36Sopenharmony_ci		else if (current_index == 1)
251262306a36Sopenharmony_ci			pl = &ps->medium;
251362306a36Sopenharmony_ci		else /* current_index == 2 */
251462306a36Sopenharmony_ci			pl = &ps->high;
251562306a36Sopenharmony_ci		return  pl->sclk;
251662306a36Sopenharmony_ci	}
251762306a36Sopenharmony_ci}
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ciu32 rv770_dpm_get_current_mclk(struct radeon_device *rdev)
252062306a36Sopenharmony_ci{
252162306a36Sopenharmony_ci	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
252262306a36Sopenharmony_ci	struct rv7xx_ps *ps = rv770_get_ps(rps);
252362306a36Sopenharmony_ci	struct rv7xx_pl *pl;
252462306a36Sopenharmony_ci	u32 current_index =
252562306a36Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
252662306a36Sopenharmony_ci		CURRENT_PROFILE_INDEX_SHIFT;
252762306a36Sopenharmony_ci
252862306a36Sopenharmony_ci	if (current_index > 2) {
252962306a36Sopenharmony_ci		return 0;
253062306a36Sopenharmony_ci	} else {
253162306a36Sopenharmony_ci		if (current_index == 0)
253262306a36Sopenharmony_ci			pl = &ps->low;
253362306a36Sopenharmony_ci		else if (current_index == 1)
253462306a36Sopenharmony_ci			pl = &ps->medium;
253562306a36Sopenharmony_ci		else /* current_index == 2 */
253662306a36Sopenharmony_ci			pl = &ps->high;
253762306a36Sopenharmony_ci		return  pl->mclk;
253862306a36Sopenharmony_ci	}
253962306a36Sopenharmony_ci}
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_civoid rv770_dpm_fini(struct radeon_device *rdev)
254262306a36Sopenharmony_ci{
254362306a36Sopenharmony_ci	int i;
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
254662306a36Sopenharmony_ci		kfree(rdev->pm.dpm.ps[i].ps_priv);
254762306a36Sopenharmony_ci	}
254862306a36Sopenharmony_ci	kfree(rdev->pm.dpm.ps);
254962306a36Sopenharmony_ci	kfree(rdev->pm.dpm.priv);
255062306a36Sopenharmony_ci}
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ciu32 rv770_dpm_get_sclk(struct radeon_device *rdev, bool low)
255362306a36Sopenharmony_ci{
255462306a36Sopenharmony_ci	struct rv7xx_ps *requested_state = rv770_get_ps(rdev->pm.dpm.requested_ps);
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ci	if (low)
255762306a36Sopenharmony_ci		return requested_state->low.sclk;
255862306a36Sopenharmony_ci	else
255962306a36Sopenharmony_ci		return requested_state->high.sclk;
256062306a36Sopenharmony_ci}
256162306a36Sopenharmony_ci
256262306a36Sopenharmony_ciu32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low)
256362306a36Sopenharmony_ci{
256462306a36Sopenharmony_ci	struct rv7xx_ps *requested_state = rv770_get_ps(rdev->pm.dpm.requested_ps);
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci	if (low)
256762306a36Sopenharmony_ci		return requested_state->low.mclk;
256862306a36Sopenharmony_ci	else
256962306a36Sopenharmony_ci		return requested_state->high.mclk;
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_cibool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
257362306a36Sopenharmony_ci{
257462306a36Sopenharmony_ci	u32 vblank_time = r600_dpm_get_vblank_time(rdev);
257562306a36Sopenharmony_ci	u32 switch_limit = 200; /* 300 */
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	/* RV770 */
257862306a36Sopenharmony_ci	/* mclk switching doesn't seem to work reliably on desktop RV770s */
257962306a36Sopenharmony_ci	if ((rdev->family == CHIP_RV770) &&
258062306a36Sopenharmony_ci	    !(rdev->flags & RADEON_IS_MOBILITY))
258162306a36Sopenharmony_ci		switch_limit = 0xffffffff; /* disable mclk switching */
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	if (vblank_time < switch_limit)
258462306a36Sopenharmony_ci		return true;
258562306a36Sopenharmony_ci	else
258662306a36Sopenharmony_ci		return false;
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci}
2589